Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Implemented by: Aires Marco S. Ladaga ??/03/2020
- Description:
- Consolidated SSW 4.3.1 (d) (ii), SSW 4.3.1 (d) (iii) and SSW 4.3.1 (d) (iv)
- ToDo:
- Updated by: --
- Description: --
- ToDo: --
- """
- import json
- import threading
- from json import encoder #<< Python Library; Including the python module>>
- def ModifyTableStructure(queryArr):#creates Dictionary, with mainElement GUID as index, with value of --> table of table of items
- modifiedIndexTbl = {}
- for ele in queryArr["Table1"]:
- icGUID, siteGUID, wallGUID = ele["elementid"], ele["siteid"], ele["wallid"]
- if icGUID is not None:
- val = modifiedIndexTbl.get(icGUID) #Check if index eleGUID is available. if None, will create one and add list under it
- if val is None:
- tempTbl = []
- modifiedIndexTbl[icGUID] = tempTbl
- modifiedIndexTbl[icGUID].append([siteGUID, wallGUID])
- return modifiedIndexTbl
- def main():
- BindCheckFunc("CheckRule")
- RunPipeLine()
- def CheckRule():
- inspectionChamberQuery = GetQueryByElementGroupName("Inspection chamber")
- pipeQuery = GetQueryByElementGroupName("Pipe")
- manholeQuery = GetQueryByElementGroupName("Manhole")
- junctionQuery = GetQueryByElementGroupName("Junction")
- siteQuery = GetQueryByElementGroupName("Site")
- boundaryWallQuery = GetQueryByElementGroupName("Boundary wall")
- queryEle = """select distinct allele.* from(
- select ic.elementid , 'ic' as separator from(
- """+inspectionChamberQuery+"""
- )ic
- UNION
- select pipe.elementid , 'pipe' as separator from(
- """+pipeQuery+"""
- )pipe
- UNION
- select manhole.elementid , 'manhole' as separator from(
- """+manholeQuery+"""
- )manhole
- UNION
- select junction.elementid , 'junction' as separator from(
- """+junctionQuery+"""
- )junction
- )allele"""
- queryDIIChecking = """
- select distinct ic.elementid, site.siteid, wall.wallid from(
- select ic.elementid, sp.xminbound, sp.xmaxbound, sp.yminbound, sp.ymaxbound from(
- """+inspectionChamberQuery+"""
- )ic inner join bimrl_spatialindex sp
- on ic.elementid = sp.elementid
- )ic left join
- (
- select site.elementid as siteid, spforsite.xminbound, spforsite.xmaxbound, spforsite.yminbound, spforsite.ymaxbound from(
- """+siteQuery+"""
- )site inner join bimrl_spatialindex spforsite
- on site.elementid = spforsite.elementid
- )site on ic.xminbound = site.xminbound
- and ic.xmaxbound = site.xmaxbound
- and ic.yminbound = site.yminbound
- and ic.ymaxbound = site.ymaxbound
- inner join bimrl_spatialindex spforwall
- on site.siteid = spforwall.elementid
- left join
- (
- select wall.elementid as wallid, sp.xminbound, sp.xmaxbound, sp.yminbound, sp.ymaxbound from(
- """+boundaryWallQuery+"""
- )wall inner join bimrl_spatialindex sp
- on wall.elementid = sp.elementid
- )wall on spforwall.xminbound = wall.xminbound
- and spforwall.xmaxbound = wall.xmaxbound
- and spforwall.yminbound = wall.yminbound
- and spforwall.ymaxbound = wall.ymaxbound
- """
- queryHighestLowestElev = """select worldbbox[1]::point3d as wordlowpos, worldbbox[2]::point3d as worldhighpos
- from bimrl_federatedmodel
- where federatedid = '"""+str(GetFederatedId())+"""'"""
- eleQueryArr = FXBIMRL.GetJsonObjFromQuery(queryEle)
- DIIQueryArr = FXBIMRL.GetJsonObjFromQuery(queryDIIChecking)
- worldbboxArr = FXBIMRL.GetJsonObjFromQuery(queryHighestLowestElev)
- icTbl, sewerJuncTbl, sewerPipeTbl, manholeTbl = list(), list(), list(), list()
- icDictSiteWall = ModifyTableStructure(DIIQueryArr)
- worldBBoxLP = worldbboxArr["Table1"][0]["wordlowpos"]
- worldBBoxHP = worldbboxArr["Table1"][0]["worldhighpos"]
- for tbl in eleQueryArr["Table1"]:
- guid = tbl["elementid"]
- eleSeparator = tbl["separator"]
- if eleSeparator == "ic": icTbl.append(guid)
- elif eleSeparator == "pipe": sewerPipeTbl.append(guid)
- elif eleSeparator == "manhole": manholeTbl.append(guid)
- elif eleSeparator == "junction": sewerJuncTbl.append(guid)
- GenerateSysGraph(2)
- sewerConTbl, lastICTable, lastMHTable, backDropTbl = GetSewerConnection(icTbl, manholeTbl, sewerJuncTbl)
- if lastICTable:
- for index, lastIcGuid in enumerate(lastICTable):
- icExtrude, icPolyhedron, icProjection = GetExtrusionFromLowestToHighest(lastIcGuid, worldBBoxHP["Z"], worldBBoxLP["Z"])
- icMidPnt = icPolyhedron.boundingBox.Center
- eleObj = GetObjectByElementId(lastIcGuid)
- thisSewerConTbl = sewerConTbl[index]
- lastELeToPublicSewerGUID = lastMHTable[index]
- lastEleToPublicSewerObj = GetObjectByElementId(lastELeToPublicSewerGUID)
- lastElePredef = lastEleToPublicSewerObj.TypeData["predefinedtype"]
- # sewerConDiam = PipeGeom.GetPipeDiameter(thisSewerConTbl[0])*1000
- listOfListSiteWall = icDictSiteWall.get(lastIcGuid)
- print lastElePredef
- if lastElePredef == "MANHOLE":
- for sewerConGUID in thisSewerConTbl:
- sewerConObj = GetObjectByElementId(sewerConGUID)
- sewerConDiam = round(PipeGeom.GetPipeDiameter(sewerConGUID)*1000)
- pipeStatus = filter(lambda x:x["propertyname"] == "Status", sewerConObj.PropertyTable)
- pipeStatus = ", ".join([str(x) for x in pipeStatus]) #join with separator works well with str
- if pipeStatus and "new" in pipeStatus.lower():
- if sewerConDiam >= 200:
- print lastIcGuid,sewerConGUID,sewerConDiam,"Compliant"
- else:
- print lastIcGuid,sewerConGUID,sewerConDiam,"NC"
- pipeMaterial = map(lambda x:x["materialname"], sewerConObj.MaterialTable)
- pipeMaterial = ", ".join([str(x) for x in pipeMaterial]) #join with separator works well with str
- if "upvc" not in pipeMaterial.lower():
- print lastIcGuid,sewerConGUID,pipeMaterial,"Compliant"
- else:
- print lastIcGuid,sewerConGUID,pipeMaterial,"NC"
- else:
- print lastIcGuid,sewerConGUID,"NOT NEW"
- elif lastElePredef == "JUNCTION":
- yJuncPublicSewer = GetConnectedPipe(lastELeToPublicSewerGUID)
- yJuncPublicSewer = [guid for guid in yJuncPublicSewer if guid not in thisSewerConTbl]
- if len(yJuncPublicSewer) > 0:
- yJuncPublicSewerDiam = list(set([round(PipeGeom.GetPipeDiameter(guid)*1000) for guid in yJuncPublicSewer]))
- if len(yJuncPublicSewerDiam) == 1:
- for sewerConGUID in thisSewerConTbl:
- sewerConObj = GetObjectByElementId(sewerConGUID)
- sewerConDiam = round(PipeGeom.GetPipeDiameter(sewerConGUID)*1000)
- if sewerConDiam == yJuncPublicSewerDiam[0]:
- print (lastIcGuid,sewerConGUID, "Compliant same diam", sewerConDiam, yJuncPublicSewerDiam[0])
- print ("SHJALL follow material")
- else:
- print (lastIcGuid,sewerConGUID, "NC not same diam",sewerConDiam, yJuncPublicSewerDiam[0])
- else:
- print (lastIcGuid, yJuncPublicSewerDiam, "INCONSISTENT public sewer diameter")
- else:
- print (lastELeToPublicSewerGUID, "No connected public sewer")
- dictSiteWithWall = dict()
- trueDictSiteAboveICWithWall = dict()
- for tbl in listOfListSiteWall:#Modify data to dict, index = siteGUID value = listOfWalls
- siteGUID, bounaryWallGUID = tbl[0], tbl[1]
- if siteGUID is not None:
- if dictSiteWithWall.get(siteGUID) is None:
- tempTbl = list()
- dictSiteWithWall[siteGUID] = tempTbl
- if bounaryWallGUID is not None:
- dictSiteWithWall[siteGUID].append(bounaryWallGUID)
- # dictSiteWithWall = { for tbl in listOfListSiteWall if tbl[0] is not }
- sitePartialCoverTbl = list()#site partially covering IC
- # siteTotallyCoveredTbl = list()#site totally covering IC
- for siteGUID,tblWall in dictSiteWithWall.items(): #Use geometry to validate if Site if Intersecting to IC, and Site if intersecting to Wall, since all are still candidates
- #CHANGE EXTRUDE FROM ALLBOTTOMFACES
- siteExtrude, sitePolyhedron, siteProjection = GetExtrusionFromLowestToHighest(siteGUID, worldBBoxHP["Z"], worldBBoxLP["Z"])
- if FXGeometry.IsIntersectOrInside(icExtrude, sitePolyhedron):
- if checkSubtractedPrj(icProjection, siteProjection): #check if site if fully covering IC via projection
- trueTblWall = list()
- print tblWall
- for wallGUID in tblWall:
- wallPolyhed = FXGeometry.GetGeometryBodyByGUID(wallGUID)
- # CheckReport.DisplayResult("Attention", eleObj, "Elements to check are not provided.", None)
- # CheckReport.AddRelatedGeometry(wallPolyhed, "obb", "1,1,0", "W")
- # CheckReport.AddRelatedGeometry(siteExtrude, "obb", "1,1,0", "W")
- if FXGeometry.IsIntersectOrInside(siteExtrude, wallPolyhed):
- trueTblWall.append([wallGUID, wallPolyhed])
- trueDictSiteAboveICWithWall[siteGUID] = [trueTblWall, siteProjection]
- else:
- sitePartialCoverTbl.append(siteGUID)
- if sitePartialCoverTbl:
- print ("SITE PARTIALLY COVERING IC ", sitePartialCoverTbl)
- else:
- sewerConLine = PipeGeom.GetPipeCenterLine(thisSewerConTbl[0])
- pointDisToIcMid = {Point3D().sqDistance(pnt, icMidPnt):pnt for pnt in [sewerConLine.startPoint, sewerConLine.endPoint]}
- sortedPoint = [Point3D(pointDisToIcMid[i].X, pointDisToIcMid[i].Y, 0) for i in sorted(pointDisToIcMid)]
- modifiedSewerConLine = LineSegment3D(sortedPoint[0], sortedPoint[1])
- #worldBBoxDiagDist value will used to extend to sewerConLine, for Line to Line intersection
- worldBBoxDiagDist = LineSegment3D(Point3D(worldBBoxLP["X"], worldBBoxLP["Y"],0), Point3D(worldBBoxHP["X"], worldBBoxHP["Y"],0)).extent
- modifiedSewerConLine.extendAtEnd(worldBBoxDiagDist)
- closestBoundaryDist = None
- closestBoundaryDistArrow = None
- print (trueDictSiteAboveICWithWall)
- for siteGUID, tbl in trueDictSiteAboveICWithWall.items():
- tblWallWithPolyhed = tbl[0]
- sitePrj = tbl[1]
- if tblWallWithPolyhed:
- polyList = List[Polyhedron]()
- for tbl in tblWallWithPolyhed:
- polyList.Add(tbl[1])
- boundaryWallprj = FXGeometry.GetProjection(polyList, 0) #create projection to lowest elevation
- print (boundaryWallprj)
- for face in boundaryWallprj:
- print "wall",face.OuterAndInnerBoundaries, icMidPnt, closestBoundaryDist, closestBoundaryDistArrow
- closestBoundaryDist, closestBoundaryDistArrow = GetClosestDistance(modifiedSewerConLine, face.OuterAndInnerBoundaries, icMidPnt, closestBoundaryDist, closestBoundaryDistArrow)
- for face in sitePrj:
- print "site", face.OuterAndInnerBoundaries, icMidPnt, closestBoundaryDist, closestBoundaryDistArrow
- closestBoundaryDist, closestBoundaryDistArrow = GetClosestDistance(modifiedSewerConLine, face.OuterAndInnerBoundaries, icMidPnt, closestBoundaryDist, closestBoundaryDistArrow)
- # intersect line3dSegment to line3dSegment, by lengh of worldBBox
- # dictSiteWithWall = { for siteGUID, tblWall in enumerate(dictSiteWithWall) }
- else:
- print ("Last ic is not provided.")
- def GetClosestDistance(modifiedSewerConLine, tblBoundaries, icMidPnt, closestBoundaryDist, closestBoundaryDistArrow):
- closestDist, closestDD = None, None
- for line in tblBoundaries:
- if str(type(line)) == "<type 'List[LineSegment3D]'>": #outer boundaries
- for trueLine in line:
- startPnt = trueLine.startPoint
- endPnt = trueLine.endPoint
- trueLine = LineSegment3D(Point3D(startPnt.X, startPnt.Y, 0), Point3D(endPnt.X, endPnt.Y, 0))
- print LineSegment3D().intersect(modifiedSewerConLine, trueLine)
- else: #inner boundaries
- startPnt = line.startPoint
- endPnt = line.endPoint
- line = LineSegment3D(Point3D(startPnt.X, startPnt.Y, 0), Point3D(endPnt.X, endPnt.Y, 0))
- print LineSegment3D().intersect(modifiedSewerConLine, line)
- return closestDist, closestDD
- def checkSubtractedPrj(elePrj, prj2): #Check If prj2 is fully covering elePrj
- def SubPrjWithVal(face1, face2, elev, numSet):
- subbedPrj = FXGeometry.SubtractProjection(face1, face2, elev)
- if len(subbedPrj) > 0:
- numSet.append([face.Area for face in subbedPrj if face.Area is not None and int(face.Area) > 0 ])#add area thats not None and greater than 1 in areaSet
- prjThreadList = list()
- areaSet = set()
- for i in range(len(elePrj)):
- for u in range(len(prj2)):
- thread = threading.Thread(target=SubPrjWithVal, args=(elePrj[i], prj2[u], 0, areaSet))
- thread.start()
- prjThreadList.append(thread)
- for thread in prjThreadList:
- thread.join()
- if len(areaSet) > 0 : #if there's one of the area is greater than one, means it is not fully covered
- return False
- else:
- return True
- def GenerateSysGraph(flowdir, *args):
- excludeTbl = ["Dummy Port Element"]
- if len(args) > 0:
- excludeTbl = excludeTbl + list(args)
- SystemGraph.InitFullSystemGraphs()
- SystemGraph.ExcludeElementID(excludeTbl)
- SystemGraph.SetSystemFlowDirection(flowdir)
- SystemGraph.GenerateGraph()
- def GetConnectedPipe(elementid):
- query = """select rl.connectedelementid from bimrl_relconnection rl, bimrl_element e, bimrl_type t
- where rl.connectingelementid = '"""+elementid+"""'
- and rl.connectedelementid = e.elementid
- and e.typeid = t.elementid
- and t.ifctype = 'IFCPIPESEGMENTTYPE'
- and t.predefinedtype in ('NOTDEFINED','RIGIDSEGMENT')"""
- arr = FXBIMRL.GetJsonObjFromQuery(query)
- return [tbl["connectedelementid"] for tbl in arr["Table1"]]
- def GetSewerConnection(inspectionChamberTable, manholeTable, junctionTable):
- # NOTE: RETURN SEWER CONNECTION, LAST IC, MANHOLE/JUNCTION, BACKDROP
- if manholeTable:
- mhTargetStr = GetTarget(manholeTable)
- sewerJunctionAndManholeTable = manholeTable + junctionTable
- lastICTable = []
- lastMHTable = []
- sewerConnTbl = []
- backDropTbl = []
- for ic in inspectionChamberTable:
- for mh in sewerJunctionAndManholeTable:
- path = list(SystemGraph.FindPath(ic, mh, 0))
- if path:
- path = path[1:-1] #removing 1st and last item(-1 in python)
- #NOTE: LAST IC: ELEMENTS IN modefied path(removed start ele and end ele) SHOULD BE PIPES AND FITTINGS(NOT JUNCTION)
- isLastIC = True
- # 1) mapping/ dict comprehension
- pathWithEleType = {id:str(GetObjectByElementId(id).ElementData['elementtype']).lower() for id in path}
- # 2) check different element type and junction
- diffEleTypeAndJunc = { k:v for (k,v) in pathWithEleType.items()
- if ("segment" not in v)
- or ("fitting" in v and (FXGeometry.GetFacesNearPortLocation(k).Count == 3) )
- }
- if len(diffEleTypeAndJunc) > 0:
- isLastIC = False
- if isLastIC:
- lastICTable.append(ic)
- pipeConnTbl = filter(lambda x: "segment" in str(GetObjectByElementId(x).ElementData['elementtype']).lower() , path)
- mhObj = GetObjectByElementId(mh)
- if "fitting" not in str(mhObj.ElementData['elementtype']).lower():
- # print " MANHOLE"
- lastMHTable.append(mh)
- else: #FOR LAST IC TO JUNCTION
- # print " JUNCTION", GetObjectByElementId(mh).ElementData["elementtype"]
- faces = []
- dictFacesList = FXGeometry.GetClusterOfFacesNearPortLocation(mh)
- for keyPair in dictFacesList:
- distance = None
- closestFace = None
- # print "wut"
- for face in keyPair.Value:
- dist = Point3D().distance(face.boundingBox.Center, keyPair.Key)
- if not closestFace:
- distance = dist
- closestFace = face
- else:
- if distance > dist:
- distance = dist
- closestFace = face
- faces.append(closestFace)
- oneFacedDown = []
- twoHorizontal = []
- for face in faces:
- dot = face.basePlane.normalVector.Z
- # print "dot", dot
- if dot <= -0.35:
- oneFacedDown.append(face)
- elif dot >= -0.02 and dot <= 0.02:
- twoHorizontal.append(face)
- isBackDrop = len(oneFacedDown) == 1 and len(twoHorizontal) == 2
- # print "isBackDrop", isBackDrop
- if not isBackDrop:
- lastMHTable.append(mh)
- else:
- # print "BACKDROP"
- backDropTbl.append(mh)
- path = SystemGraph.FindPathToSpecificTypeObject(mh, mhTargetStr, 0)
- if len(path) > 1:
- manhole = path[-1] #last item(-1 in python)
- path = path[1:-1] #removing 1st and last item(-1 in python)
- SystemGraph.ResetGraph()
- GenerateSysGraph(2,path)
- path1 = SystemGraph.FindPath(manhole, mh, 0)
- if len(path1) > 1:
- path1 = filter(lambda x: "segment" in str(GetObjectByElementId(x).ElementData['elementtype']).lower() , path1)
- pipeConnTbl = pipeConnTbl + path + path1 #combining to lists of pipe
- sewerConnTbl.append(pipeConnTbl)
- return sewerConnTbl, lastICTable, lastMHTable, backDropTbl
- def GetTarget(elementidList):
- def getTarget(x):
- tbl = []
- List = ['NOTDEFINED', 'USERDEFINED']
- obj = GetObjectByElementId(x)
- predefinedType = str(obj.TypeData["predefinedtype"])
- objType = str(obj.ElementData["objecttype"])
- ifcType = str(obj.TypeData["ifctype"])
- if predefinedType not in List:
- Value = predefinedType.upper()
- else:
- Value = objType.upper()
- tbl.extend([ifcType, Value])
- return tbl
- targetStr = ""
- if len(elementidList) > 0:
- TargetList = map(getTarget, elementidList)
- targetStr = ",".join(TargetList[0])
- return targetStr
- class PipeGeom:
- @staticmethod
- def GetPipeCenterLine(elementid):
- # Get centerline by Pipe's Portlocation
- # Args: elementid
- # Return: centerLine(Line3D)
- if not ("segment" in str(GetObjectByElementId(elementid).ElementData["elementtype"]).lower()):
- return
- centerLine = LineSegment3D()
- query = """SELECT con.connectingportlocation AS portpnt
- FROM bimrl_relconnection con
- WHERE con.connectingelementid = '"""+elementid+"""' """
- PortArr = FXBIMRL.GetJsonObjFromQuery(query)
- PortArr = map(lambda x: x["portpnt"], PortArr["Table1"])
- # NOTE: IF len(PortArr) > 2, NEED TO DETERMINE THE 2 FARTHEST PNTS
- if len(PortArr) > 2:
- for v in PortArr:
- pnt1 = Point3D(v["X"], v["Y"], v["Z"])
- for v2 in PortArr:
- pnt2 = Point3D(v2["X"], v2["Y"], v2["Z"])
- if not pnt1.Equals(pnt2):
- line = LineSegment3D(pnt1, pnt2)
- if centerLine is None or centerLine.extent < line.extent:
- centerLine = line
- else:
- pnt1 = Point3D(PortArr[0]["X"], PortArr[0]["Y"], PortArr[0]["Z"])
- pnt2 = Point3D(PortArr[1]["X"], PortArr[1]["Y"], PortArr[1]["Z"])
- centerLine = LineSegment3D(pnt1, pnt2)
- return centerLine
- @staticmethod
- def GetPipeDiameter(elementid):
- # Get Diameter by circular face
- # Args: elementid
- # Return: Diameter(number) in meter
- if not ("segment" in str(GetObjectByElementId(elementid).ElementData["elementtype"]).lower()):
- print "expected segment, got "+ GetObjectByElementId(elementid).ElementData["elementtype"]
- return None
- diameter = 0
- circleFaces = PipeGeom.GetCircularFaces(elementid)
- if circleFaces:
- cntrPnt = circleFaces[0]['centroid']
- outerPnt = circleFaces[0]['face'].OuterVertices[0]
- diameter = (LineSegment3D(cntrPnt, outerPnt).extent) * 2
- return diameter
- @staticmethod
- def GetCircularFaces(elementid):
- # Get circular face using IsFaceCircular API
- # Args: elementid
- # Return: List["face":(Face3D), "centroid":(Point3D)]
- faceQuery = """SELECT polygon, centroid, normal
- FROM bimrl_topo_face
- WHERE elementid = '"""+ elementid +"""'
- AND type = 'BODY' """
- faceArr = FXBIMRL.GetJsonObjFromQuery(faceQuery)
- if faceArr is None: return None
- circleFaces = filter(lambda x: FXGeometry.IsFaceCircular(FXGeometry.CreatePolygonFace(x["polygon"]), 0.1), faceArr["Table1"])
- circleFaces = map(lambda x: {"face": FXGeometry.CreatePolygonFace(x["polygon"]), "centroid": Point3D(x["centroid"]["X"], x["centroid"]["Y"], x["centroid"]["Z"])}, circleFaces)
- return circleFaces
- def GetExtrusionFromLowestToHighest(guid, highElev, lowElev, polyhedron = False):
- if polyhedron is False:
- polyhedron = FXGeometry.GetGeometryBodyByGUID(guid)
- polyList = List[Polyhedron]()
- polyList.Add(polyhedron)
- prj = FXGeometry.GetProjection(polyList, lowElev) #create projection to lowest elevation
- extrudedPolyList = List[Polyhedron]()
- extrudeHeight = abs(float(highElev) - float(lowElev))
- extrudedPolyList.Add(FXGeometry.ExtrudeFaces(prj, Vector3D(0,0,1) , extrudeHeight)) # then extrude to highest elevation
- extrudedPoly = FXGeometry.UnionPolyhedronList(extrudedPolyList)
- return extrudedPoly, polyhedron, prj
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement