diff --git a/Optimization/Genetic/Evaluator.py b/Optimization/Genetic/Evaluator.py index 63919f0..b761e08 100644 --- a/Optimization/Genetic/Evaluator.py +++ b/Optimization/Genetic/Evaluator.py @@ -40,7 +40,7 @@ def calculateFitnessWall(self,wallSkeleton): lengthX = 0 lengthY = 0 vec = Pnt(0,0) - for voileSkeleton in wallSkeleton.attachedVoiles: + for voileSkeleton in wallSkeleton.getAllVoiles(): # for voileSkeleton in voiles: # print ("looping") centerV = voileSkeleton.poly.centroid() diff --git a/Optimization/Genetic/GeneticAlgorithm.py b/Optimization/Genetic/GeneticAlgorithm.py index 69d684c..eabca0b 100644 --- a/Optimization/Genetic/GeneticAlgorithm.py +++ b/Optimization/Genetic/GeneticAlgorithm.py @@ -36,7 +36,7 @@ def mutationSelection(mutationRate,population): if random.uniform(0,1) < mutationRate: yield p -def search(levelSkeleton,popSize=40,crossRate=0.3,mutRate=0.4,maxIterations=60 +def search(levelSkeleton,popSize=30,crossRate=0.3,mutRate=0.5,maxIterations=70 ,geneticOps=GeneticOperations2): start = timeit.default_timer() population = generatePopulation(levelSkeleton,popSize) diff --git a/Optimization/Genetic/GeneticOperations2.py b/Optimization/Genetic/GeneticOperations2.py index c2ab943..44908b1 100644 --- a/Optimization/Genetic/GeneticOperations2.py +++ b/Optimization/Genetic/GeneticOperations2.py @@ -1,5 +1,4 @@ import random -import timeit from Optimization.Solution import Solution from Skeleton.LevelSkeleton import LevelSkeleton @@ -46,8 +45,12 @@ def mutateWall(wallSkeleton,positive=True,mutationSize=1): if positive or len(wallSkeleton.attachedVoiles) == 0: r = random.uniform(0,1) if r < 0.5 or len(wallSkeleton.attachedVoiles) == 0: #add new shear wall - start = int(random.uniform(0,wallSkeleton.vecLength.magn()-WallSkeleton.miniVoileLength)) - end = start + WallSkeleton.miniVoileLength + if WallSkeleton.miniVoileLength*0.8 < wallSkeleton.vecLength.magn() <= WallSkeleton.miniVoileLength: + start = 0 + end = wallSkeleton.vecLength.magn() + else: + start = int(random.uniform(0,wallSkeleton.vecLength.magn()-WallSkeleton.miniVoileLength)) + end = start + WallSkeleton.miniVoileLength wallSkeleton.attachVoile(VoileSkeleton(wallSkeleton,start,end)) else: # change shear wall size rand = int(random.uniform(0,len(wallSkeleton.attachedVoiles)-0.1)) diff --git a/Optimization/Solution.py b/Optimization/Solution.py index d91eda6..40e8025 100644 --- a/Optimization/Solution.py +++ b/Optimization/Solution.py @@ -53,9 +53,9 @@ def createRandomSolutionFromSkeleton2(levelS): # print ("time it took copy1: " + str(e - s)) levelSkeleton = LevelSkeleton(walls,levelS.slabSkeleton.copy(),levelS.level) - - totalLength = levelSkeleton.getWallsTotalLength() - needed = levelSkeleton.getVoileLengthNeeded()*2 + voilesfixedLength = levelSkeleton.getVoilesTotalLength() + totalLength = levelSkeleton.getWallsTotalLength() - voilesfixedLength + needed = levelSkeleton.getVoileLengthNeeded()*2 - voilesfixedLength # print("needed : " + str(needed) + " total length: " + str(totalLength)) size = len(levelSkeleton.wallSkeletons) indexes = range(size) @@ -69,9 +69,10 @@ def createRandomSolutionFromSkeleton2(levelS): length, voiles = wallSkeleton.createRandomVoilesFromLengthNeeded(totalLength, needed) # e = timeit.default_timer() # print ("time it took create voiles: " + str(e - s)) + totalLength -= (wallSkeleton.vecLength.magn() - wallSkeleton.getVoilesLength()) wallSkeleton.attachVoiles(voiles) needed -= length - totalLength -= wallSkeleton.vecLength.magn() + # print("total length left: " + str(totalLength) + " needed left: " + str(needed)) # e1 = timeit.default_timer() @@ -82,7 +83,7 @@ def getValidVoilesPoints(self): if not self.validPoints: allVoiles = [voile for wallSkeleton in self.levelSkeleton.wallSkeletons - for voile in wallSkeleton.attachedVoiles] + for voile in wallSkeleton.getAllVoiles()] for cpt,voileSkeleton in enumerate(allVoiles): for i in range(cpt+1,len(allVoiles)): @@ -117,7 +118,7 @@ def getNonValidVoilesPoints(self): if not self.nonValidPoints: validPoints = self.getValidVoilesPoints() allVoiles = [voile for wallSkeleton in self.levelSkeleton.wallSkeletons - for voile in wallSkeleton.attachedVoiles] + for voile in wallSkeleton.getAllVoiles()] self.nonValidPoints = [pnt for voileSkeleton in allVoiles for index, pnt in enumerate(voileSkeleton.getPointsList()) if not voileSkeleton.isPointValid[index]] @@ -127,7 +128,7 @@ def getNonValidVoilesPoints(self): def getValidVoilesBoxes(self): if not self.validBoxes: allVoiles = [voile for wallSkeleton in self.levelSkeleton.wallSkeletons - for voile in wallSkeleton.attachedVoiles] + for voile in wallSkeleton.getAllVoiles()] acceptedBoxes = [] done = [False for v in allVoiles] for cpt,voil in enumerate(allVoiles): diff --git a/Skeleton/LevelSkeleton.py b/Skeleton/LevelSkeleton.py index 2ab4a23..7edc464 100644 --- a/Skeleton/LevelSkeleton.py +++ b/Skeleton/LevelSkeleton.py @@ -35,6 +35,9 @@ def getWallsTotalLength(self): length += wallSkeleton.vecLength.magn() return length + def getVoilesTotalLength(self): + return sum(wallSkeleton.getVoilesLength() for wallSkeleton in self.wallSkeletons) + def getRatio(self): if self.getWallsTotalLength() == 0: return 1 @@ -93,5 +96,19 @@ def restrictLevelUsableWalls(self,levelSkeleton): self.wallSkeletons = resultWalls + def copyLevelsVoiles(self,levelSkeleton): + aboveWalls = levelSkeleton.wallSkeletons + for wallSkeleton in aboveWalls: + if not wallSkeleton.getVoilesLength(): + continue + for wallSkeleton2 in self.wallSkeletons: + intersection = wallSkeleton.poly.intersection(wallSkeleton2.poly) + if intersection and wallSkeleton.poly.area() == intersection.area(): # test if polygons are equal + voiles = wallSkeleton.getAllVoiles() + for voileSkeleton in voiles: + voileSkeleton = voileSkeleton.copy() + voileSkeleton.setParentWall(wallSkeleton2,True) + wallSkeleton2.attachFixedVoile(voileSkeleton) + break def getPolys(self): return [wallSkeleton.poly for wallSkeleton in self.wallSkeletons] \ No newline at end of file diff --git a/Skeleton/VoileSkeleton.py b/Skeleton/VoileSkeleton.py index cdee972..e2cb03a 100644 --- a/Skeleton/VoileSkeleton.py +++ b/Skeleton/VoileSkeleton.py @@ -17,8 +17,11 @@ def __init__(self,parent,start,end): self.pointsList = None self.isPointValid = None - def setParentWall(self,wallSkeleton): + def setParentWall(self,wallSkeleton,update=False): self.parentWall = wallSkeleton + if update: + return self.updateStartEnd() + return True def getPolyFromStartEnd(self,start,end): parent = self.parentWall @@ -35,6 +38,24 @@ def getPolyFromStartEnd(self,start,end): poly = Poly([topLeftPnt, pnt1, pnt2, pnt3]) return poly + def updateStartEnd(self): + parent = self.parentWall + vecL = parent.vecLength + topLeftPnt = parent.topLeftPnt + vecs = [] + for pnt in self.poly.points: + vec = pnt - topLeftPnt + if vec.isParallel(vecL,0.005): + vecs.append(vec) + if len(vecs) != 2: + print("ERROR UPDATE START END VOILESKELETON: NUMBER OF" + " PARALLEL VECTORS EXPECTED: 2, FOUND: ",len(vecs)) + return False + print('INFO UPDATE START END VOILESKELETON: CORRECT NUMBER') + self.start = min([vecs[0].magn(), vecs[1].magn()]) + self.end = max([vecs[0].magn(), vecs[1].magn()]) + return True + def getLength(self): return self.end - self.start diff --git a/Skeleton/WallSkeleton.py b/Skeleton/WallSkeleton.py index d0a9dd1..e0d3e4d 100644 --- a/Skeleton/WallSkeleton.py +++ b/Skeleton/WallSkeleton.py @@ -21,6 +21,7 @@ class WallSkeleton(BoxSkeleton): def __init__(self, poly,pnts=None): super(WallSkeleton, self).__init__(poly,pnts) self.attachedVoiles = [] + self.fixedVoiles = [] self.sums = None @staticmethod @@ -130,9 +131,16 @@ def createRandomVoilesFromLengthNeeded1(self, totalLength, needed): def createRandomVoilesFromLengthNeeded2(self, totalLength, needed): lengthDiscreted = self.vecLength.magn()/WallSkeleton.discreteFactor + proba = min([needed / totalLength, 1]) + if proba <= 0: + return 0,[] + if 0.8 < lengthDiscreted < 1: + if random.uniform(0,1) < proba: + return self.vecLength.magn(),[VoileSkeleton(self,0,self.vecLength.magn())] + return 0,[] minVoileLen = WallSkeleton.miniVoileLength/WallSkeleton.discreteFactor voiles = [] - proba = min([needed / totalLength,1]) + lengthCreated = 0 n = numpy.random.binomial(lengthDiscreted,proba) length = n*WallSkeleton.discreteFactor @@ -192,6 +200,14 @@ def attachVoile(self,voileSkeleton): from Optimization.Genetic.GeneticOperations import mergeVoile mergeVoile(self.attachedVoiles,voileSkeleton) + def attachFixedVoile(self,voileSkeleton): + # self.attachedVoiles.append(voileSkeleton) + # voileSkeleton.setParentWall(self) + self.reInitFitness() + voileSkeleton.setParentWall(self) + from Optimization.Genetic.GeneticOperations import mergeVoile + mergeVoile(self.fixedVoiles,voileSkeleton) + # gets voile starting from most left point to distance def getVoilesBetween(self, mini=0,maxi=1): mini = mini*self.vecLength.magn() @@ -204,6 +220,9 @@ def getVoilesBetween(self, mini=0,maxi=1): newVoiles.append(VoileSkeleton(self, mini, min(maxi, voile.end))) return newVoiles + def getAllVoiles(self): + return self.attachedVoiles+self.fixedVoiles + def removeVoile(self,index): self.reInitFitness() del self.attachedVoiles[index] @@ -216,11 +235,13 @@ def copy(self): wallSkeleton = WallSkeleton(self.poly.copy(),(self.topLeftPnt, self.vecLength, self.vecWidth)) wallSkeleton.evalData = self.evalData wallSkeleton.attachVoiles([voileSkeleton.copy() for voileSkeleton in self.attachedVoiles]) + wallSkeleton.fixedVoiles = self.fixedVoiles return wallSkeleton def copyWithoutVoiles(self): wallSkeleton = WallSkeleton(self.poly.copy(),(self.topLeftPnt, self.vecLength, self.vecWidth)) wallSkeleton.evalData = self.evalData + wallSkeleton.fixedVoiles = self.fixedVoiles return wallSkeleton def reInitFitness(self): @@ -234,7 +255,7 @@ def getSums(self): sumLi2 = 0 sumLixi = 0 sumLiyi = 0 - for voileSkeleton in self.attachedVoiles: + for voileSkeleton in self.getAllVoiles(): centerV = voileSkeleton.poly.centroid() centerV = Pnt(centerV.x, centerV.y) x3 = math.pow(abs(voileSkeleton.vecLength.x()), 3) @@ -246,5 +267,8 @@ def getSums(self): self.sums = sumLi1,sumLi2,sumLixi,sumLiyi return self.sums + def getVoilesLength(self): + return sum(voileSkeleton.getLength() for voileSkeleton in self.getAllVoiles()) + diff --git a/UI/main.py b/UI/main.py index 9191bed..436556f 100644 --- a/UI/main.py +++ b/UI/main.py @@ -46,6 +46,7 @@ def __init__(self, parent=None, wallShapes=None, slabShapes=None): prevLevel = levelSkeleton # plt.show() self.skeletonLevels = [levelSkeleton for levelSkeleton in self.skeletonLevels if len(levelSkeleton.getPolys())] + self.solutions = {} # for skeletonLevel in self.skeletonLevels: # # print("needed ratio: " + str(skeletonLevel.getRatio())) # for wallSkeleton in skeletonLevel.wallSkeletons: @@ -110,52 +111,14 @@ def showLowerFun(self): self.draw(polys) def mergeCB(self): - solution = search(self.skeletonLevels[self.selectedRow]) - polys = self.getPolygonsFromLevelSkeletons(solution.levelSkeleton) - c1 = solution.levelSkeleton.getCenterFromSlab() - c2 = solution.levelSkeleton.getCenterFromShear() - e1 = Ellip(c1,0.4) - e2 = Ellip(c2,0.4) - ells = [e1,e2] - colors = [QtGui.QColor(0,255,0),QtGui.QColor(0,0,255)] - # for wallSkeleton in solution.levelSkeleton.wallSkeletons: - # for voileSkeleton in wallSkeleton.attachedVoiles: - # ells.append(Ellip(voileSkeleton.getStartPoint()-Pnt(4,4), 8)) - # ells.append(Ellip(voileSkeleton.getEndPoint()-Pnt(4,4), 8)) - # q1 = QtGui.QColor(0, 255, 0) - # q1.setAlpha(60) - # q2 = QtGui.QColor(0, 0, 255) - # q2.setAlpha(60) - # colors.append(q1) - # colors.append(q2) - d = 8. - ellipses = [] - # for pnt in solution.getValidVoilesPoints(): - # ells.append(Ellip(pnt - Pnt(d/2, d/2), d)) - # q1 = QtGui.QColor(0, 255, 0) - # q1.setAlpha(20) - # colors.append(q1) - # - # for pnt in solution.getNonValidVoilesPoints(): - # ells.append(Ellip(pnt - Pnt(d/2, d/2), d)) - # q1 = QtGui.QColor(255, 0, 0) - # q1.setAlpha(20) - # colors.append(q1) - # ellipses = ells,colors - for box in solution.getValidVoilesBoxes(): - polys[0].append(Poly([Pnt(pnt[0],pnt[1]) for pnt in box.exterior.coords])) - q1 = QtGui.QColor(0, 255, 0) - q1.setAlpha(20) - polys[1].append(q1) - - for box in solution.getNonValidVoilesBoxes(): - polys[0].append(Poly([Pnt(pnt[0],pnt[1]) for pnt in box.exterior.coords])) - q1 = QtGui.QColor(255, 0, 0) - q1.setAlpha(20) - polys[1].append(q1) - - - self.draw(polys,ellipses) + prev = None + for levelSkeleton in self.skeletonLevels[::-1]: + if prev: + levelSkeleton.copyLevelsVoiles(prev) + solution = search(levelSkeleton) + self.solutions[levelSkeleton] = solution + self.drawSkeleton(levelSkeleton) + prev = solution.levelSkeleton def crossCB(self): @@ -204,11 +167,11 @@ def getPolygonsFromLevelSkeletons(self, levelSkeleton): polygons += [voileSkeleton.poly.copy() for wallSkeleton in levelSkeleton.wallSkeletons - for voileSkeleton in wallSkeleton.getVoilesBetween()] + for voileSkeleton in wallSkeleton.getAllVoiles()] colors += [QtGui.QColor(255,0,0) for wallSkeleton in levelSkeleton.wallSkeletons - for voileSkeleton in wallSkeleton.attachedVoiles] + for voileSkeleton in wallSkeleton.getAllVoiles()] if not len(polygons): return @@ -232,14 +195,40 @@ def drawPolygons(self,shapes): from UI.DrawUtils import Window self.scrollTab.setWidget(Window(polygons,rect=self.scrollTab.geometry())) + def drawSkeleton(self,levelSkeleton): + + ellipses = [] + if levelSkeleton in self.solutions: + solution = self.solutions[levelSkeleton] + polys = self.getPolygonsFromLevelSkeletons(solution.levelSkeleton) + c1 = solution.levelSkeleton.getCenterFromSlab() + c2 = solution.levelSkeleton.getCenterFromShear() + e1 = Ellip(c1, 0.4) + e2 = Ellip(c2, 0.4) + ells = [e1, e2] + for box in solution.getValidVoilesBoxes(): + polys[0].append(Poly([Pnt(pnt[0], pnt[1]) for pnt in box.exterior.coords])) + q1 = QtGui.QColor(0, 255, 0) + q1.setAlpha(20) + polys[1].append(q1) + + for box in solution.getNonValidVoilesBoxes(): + polys[0].append(Poly([Pnt(pnt[0], pnt[1]) for pnt in box.exterior.coords])) + q1 = QtGui.QColor(255, 0, 0) + q1.setAlpha(20) + polys[1].append(q1) + else: + polys = self.getPolygonsFromLevelSkeletons(levelSkeleton) + self.draw(polys, ellipses) + def listViewSelected(self, index): self.selectedRow = row = index.row() # print ('selected item index found at %s with data: %s' % (index.row(), index.data().toString())) shapes = [wall.shape for wall in self.levels[row].walls] # self.drawPolygons(shapes) - polys = self.getPolygonsFromLevelSkeletons(self.skeletonLevels[row]) - self.draw(polys) + # polys = self.getPolygonsFromLevelSkeletons(self.skeletonLevels[row]) + self.drawSkeleton(self.skeletonLevels[row]) shapes.append(self.levels[row].slab.shape) self.setViewerDisplay("Selected",shapes) @@ -264,7 +253,7 @@ def createShapes(file): return wShapes,sShapes def main(): - file = "../IFCFiles/Immeuble2.ifc" + file = "../IFCFiles/Immeuble39.ifc" wShapes,sShapes = createShapes(file) app = QtGui.QApplication(sys.argv) form = TryApp(wallShapes=wShapes,slabShapes=sShapes)