diff --git a/scripts/colorCADmat.py b/scripts/colorCADmat.py index 8d95e2d1..5185c9a9 100644 --- a/scripts/colorCADmat.py +++ b/scripts/colorCADmat.py @@ -1,50 +1,51 @@ import re import sys -sys.path.append('/usr/lib64/freecad/lib64/') +sys.path.append("/usr/lib64/freecad/lib64/") import ImportGui bd = 255 -gd = 255*255 -rd = 255* 255* 255 -matNumber=re.compile(r"Material_(?P\d+)") +gd = 255 * 255 +rd = 255 * 255 * 255 +matNumber = re.compile(r"Material_(?P\d+)") -def getColor(num,vmin=0,vmax=rd): + +def getColor(num, vmin=0, vmax=rd): colRange = rd - dnum = vmax - vmin + dnum = vmax - vmin dx = num - vmin - scale = colRange/dnum + scale = colRange / dnum snum = dx * scale + 1 - - red = snum//gd - r = snum - red * gd + + red = snum // gd + r = snum - red * gd green = r // bd blue = r - green * bd - return (red/255,green/255,blue/255) + return (red / 255, green / 255, blue / 255) + def setColorMaterial(documents): featureObj = [] matMin = 999999999 matMax = 0 for obj in documents.Objects: - if obj.TypeId == 'Part::Feature' : - for o in obj.InListRecursive: - m = matNumber.search(o.Label) - if m : - mat = int(m.group('matnum')) - matMin = min(matMin,mat) - matMax = max(matMax,mat) - featureObj.append((obj,mat)) - - for obj,mat in featureObj: - obj.ViewObject.ShapeColor = getColor(mat,matMin,matMax) + if obj.TypeId == "Part::Feature": + for o in obj.InListRecursive: + m = matNumber.search(o.Label) + if m: + mat = int(m.group("matnum")) + matMin = min(matMin, mat) + matMax = max(matMax, mat) + featureObj.append((obj, mat)) + + for obj, mat in featureObj: + obj.ViewObject.ShapeColor = getColor(mat, matMin, matMax) # color solids in a Freecad document with respect to the material number doc = App.ActiveDocument setColorMaterial(doc) name = doc.Label -outname = name+'_color' -ImportGui.export(doc.RootObjects,outname+'.stp') -doc.saveAs(outname+'.FCStd') - +outname = name + "_color" +ImportGui.export(doc.RootObjects, outname + ".stp") +doc.saveAs(outname + ".FCStd") diff --git a/scripts/geouned.py b/scripts/geouned.py index be827c05..3bacb556 100644 --- a/scripts/geouned.py +++ b/scripts/geouned.py @@ -5,42 +5,43 @@ # only if modules are not in the PYTHONPATH or directly installed in the python distribution used import sys -#geo_path="C:\\Users\\Juan\\Documents\\work\\GEOUNED\\RepoGit\\GitHub\\GEOUNEDcode\\src" -#sys.path.append(geo_path) -#sys.path.append('C:\\Program Files\\FreeCAD 0.19\\bin...') + +# geo_path="C:\\Users\\Juan\\Documents\\work\\GEOUNED\\RepoGit\\GitHub\\GEOUNEDcode\\src" +# sys.path.append(geo_path) +# sys.path.append('C:\\Program Files\\FreeCAD 0.19\\bin...') import geouned from geouned.GEOReverse import reverse runReverse = False -if len(sys.argv) < 2 : - inifile = 'config.ini' +if len(sys.argv) < 2: + inifile = "config.ini" -elif len(sys.argv) == 2 : - if sys.argv[1] == '-r': - runReverse = True - inifile = 'configReverse.ini' - else: - inifile = sys.argv[1] +elif len(sys.argv) == 2: + if sys.argv[1] == "-r": + runReverse = True + inifile = "configReverse.ini" + else: + inifile = sys.argv[1] elif len(sys.argv) == 3: - if sys.argv[1] == '-r': - runReverse = True - inifile = sys.argv[2] - elif sys.argv[2] == '-r': - runReverse = True - inifile = sys.argv[1] - else: - raise ValueError('Bad option') + if sys.argv[1] == "-r": + runReverse = True + inifile = sys.argv[2] + elif sys.argv[2] == "-r": + runReverse = True + inifile = sys.argv[1] + else: + raise ValueError("Bad option") else: - raise ValueError('Too many input arguments') + raise ValueError("Too many input arguments") -if not runReverse : - GEO = GEOUNED.GEOUNED(inifile) - GEO.SetOptions() - GEO.Start() +if not runReverse: + GEO = GEOUNED.GEOUNED(inifile) + GEO.SetOptions() + GEO.Start() else: - print(inifile) - reverse(inifile) + print(inifile) + reverse(inifile) diff --git a/src/geouned/GEOReverse/CodeVersion.py b/src/geouned/GEOReverse/CodeVersion.py index 2e516c65..be96f656 100644 --- a/src/geouned/GEOReverse/CodeVersion.py +++ b/src/geouned/GEOReverse/CodeVersion.py @@ -1,4 +1,4 @@ -''' Starting beta stable version 0.9 +""" Starting beta stable version 0.9 - new in version 0.9.1 - read MCNP macrobodies : RPP, BOX, RCC, REC, TRC @@ -7,8 +7,7 @@ elliptical cone and elliptical torus surfaces have been added. Changes have not been fully checked, some bugs may still remains. Please contact the authors in case of failure. -''' - -GEOReverse_Version = '0.9.1' -GEOReverse_ReleaseDate = '16/11/2023' +""" +GEOReverse_Version = "0.9.1" +GEOReverse_ReleaseDate = "16/11/2023" diff --git a/src/geouned/GEOReverse/Modules/MCNPinput.py b/src/geouned/GEOReverse/Modules/MCNPinput.py index 55a26bb4..b52fac8f 100644 --- a/src/geouned/GEOReverse/Modules/MCNPinput.py +++ b/src/geouned/GEOReverse/Modules/MCNPinput.py @@ -12,366 +12,455 @@ class MCNPinput: - def __init__(self,name): + def __init__(self, name): if not os.path.isfile(name): - raise FileNotFoundError (f"File {name} does not exist") - self.__inputcards__ = list(mp.get_cards(name)) + raise FileNotFoundError(f"File {name} does not exist") + self.__inputcards__ = list(mp.get_cards(name)) self.Transformations = self.__getTransList__() return - def GetFilteredCells(self,Surfaces,config): - levels,contLevels,Universes = self.GetLevelStructure() + def GetFilteredCells(self, Surfaces, config): + levels, contLevels, Universes = self.GetLevelStructure() - FilteredCells = {} - - Ustart = config['Ustart'] - subUniverses = getSubUniverses(Ustart,Universes) + FilteredCells = {} + + Ustart = config["Ustart"] + subUniverses = getSubUniverses(Ustart, Universes) subUniverses.add(Ustart) - if config['levelMax'] =='all': - levelMax = len(levels) - else : - levelMax = config['levelMax'] + 1 + if config["levelMax"] == "all": + levelMax = len(levels) + else: + levelMax = config["levelMax"] + 1 - levelUniverse = set() - for lev in range(0,levelMax) : - for U in levels[lev]: - levelUniverse.add(U) + levelUniverse = set() + for lev in range(0, levelMax): + for U in levels[lev]: + levelUniverse.add(U) subUniverses = subUniverses.intersection(levelUniverse) for U in list(Universes.keys()): - if U not in subUniverses : del(Universes[U]) - + if U not in subUniverses: + del Universes[U] + for U in Universes.keys(): - FilteredCells[U] = selectCells(Universes[U],config) - processSurfaces(FilteredCells[U],Surfaces) + FilteredCells[U] = selectCells(Universes[U], config) + processSurfaces(FilteredCells[U], Surfaces) # change the surface name in surface dict newSurfaces = {} for k in Surfaces.keys(): - newkey = Surfaces[k].id - newSurfaces[newkey] = Surfaces[k] + newkey = Surfaces[k].id + newSurfaces[newkey] = Surfaces[k] - - for U,universe in FilteredCells.items() : - substituteLikeCell(universe,newSurfaces) - - # set cell as CAD cell Object - for cname,c in universe.items(): - #print(cname,c.geom.str) - universe[cname] = CADCell(c) - - return levels,FilteredCells,newSurfaces + for U, universe in FilteredCells.items(): + substituteLikeCell(universe, newSurfaces) + # set cell as CAD cell Object + for cname, c in universe.items(): + # print(cname,c.geom.str) + universe[cname] = CADCell(c) + return levels, FilteredCells, newSurfaces - def GetLevelStructure(self): + def GetLevelStructure(self): containers = [] Universe_dict = {} cellCards = {} - - - for c in self.__inputcards__ : - if c.ctype != mp.CID.cell : continue - c.get_values() - cstr = cell_card_string(''.join(c.lines)) - - if cstr.TRCL : cstr.TRCL = TransformationMatrix(cstr.TRCL,self.Transformations) - if cstr.TR : cstr.TR = TransformationMatrix(cstr.TR,self.Transformations) - cellCards[c.name] = cstr - - setExplicitCellDefinition(cellCards) - for cname,c in cellCards.items(): - if c.U is None: c.U = 0 - if c.U not in Universe_dict.keys(): Universe_dict[c.U] = {} - Universe_dict[c.U].update({c.name:c}) - - if c.FILL : - containers.append(c) - - + for c in self.__inputcards__: + if c.ctype != mp.CID.cell: + continue + c.get_values() + cstr = cell_card_string("".join(c.lines)) + + if cstr.TRCL: + cstr.TRCL = TransformationMatrix(cstr.TRCL, self.Transformations) + if cstr.TR: + cstr.TR = TransformationMatrix(cstr.TR, self.Transformations) + cellCards[c.name] = cstr + + setExplicitCellDefinition(cellCards) + for cname, c in cellCards.items(): + if c.U is None: + c.U = 0 + if c.U not in Universe_dict.keys(): + Universe_dict[c.U] = {} + Universe_dict[c.U].update({c.name: c}) + + if c.FILL: + containers.append(c) + currentLevel = [0] - nextLevel = [] - contLevel ={0:[(0,0)]} - univLevel = {0 : {0}} + nextLevel = [] + contLevel = {0: [(0, 0)]} + univLevel = {0: {0}} level = 0 - + while True: - level += 1 - contLevel[level] = [] - univLevel[level] = set() - for c in reversed(containers) : - if c.U in currentLevel : - c.Level = level - nextLevel.append(c.FILL) - contLevel[level].append((c.U,c.name)) - univLevel[level].add(c.FILL) - - containers.remove(c) - - if nextLevel == [] : break - currentLevel = nextLevel - nextLevel = [] - - return univLevel,contLevel,Universe_dict - - - def GetCells(self,U=None,Fill=None): + level += 1 + contLevel[level] = [] + univLevel[level] = set() + for c in reversed(containers): + if c.U in currentLevel: + c.Level = level + nextLevel.append(c.FILL) + contLevel[level].append((c.U, c.name)) + univLevel[level].add(c.FILL) + + containers.remove(c) + + if nextLevel == []: + break + currentLevel = nextLevel + nextLevel = [] + + return univLevel, contLevel, Universe_dict + + def GetCells(self, U=None, Fill=None): cell_cards = {} - for c in self.__inputcards__ : - if c.ctype != mp.CID.cell : continue - c.get_values() - U_cell = c.get_u() - Fill_cell = c.get_f() - if ( U is None and Fill is None) : - cell_cards[c.name] = c - elif U_cell == U and U is not None: - cell_cards[c.name] = c - elif Fill_cell == Fill and Fill is not None: - cell_cards[c.name] = c - - return cell_cards - - def GetSurfaces(self,scale=1.): + for c in self.__inputcards__: + if c.ctype != mp.CID.cell: + continue + c.get_values() + U_cell = c.get_u() + Fill_cell = c.get_f() + if U is None and Fill is None: + cell_cards[c.name] = c + elif U_cell == U and U is not None: + cell_cards[c.name] = c + elif Fill_cell == Fill and Fill is not None: + cell_cards[c.name] = c + + return cell_cards + + def GetSurfaces(self, scale=1.0): surf_cards = {} number = 1 - for c in self.__inputcards__ : - if c.ctype != mp.CID.surface : continue - c.get_values() - c.TR = TransformationMatrix(c.TR,self.Transformations) - surf_cards[c.name] = (c.stype,c.scoefs,c.TR,number) - number += 1 + for c in self.__inputcards__: + if c.ctype != mp.CID.surface: + continue + c.get_values() + c.TR = TransformationMatrix(c.TR, self.Transformations) + surf_cards[c.name] = (c.stype, c.scoefs, c.TR, number) + number += 1 # return surface as surface Objects type - return Get_primitive_surfaces(surf_cards,scale) + return Get_primitive_surfaces(surf_cards, scale) def __getTransList__(self): trl = {} - for c in self.__inputcards__ : - if c.ctype != mp.CID.data : continue - c.get_values() - if c.dtype == 'TRn' : - trValues = [] - for v in c.values[1:]: - trValues.append(v[0]) - trl[c.name]= getTransMatrix(trValues,c.unit) - return trl - - -def getTransMatrix(trsf,unit='',scale=10.): - - if len(trsf) == 3 : - trsfMat = FreeCAD.Matrix(1,0,0, trsf[0]*scale, - 0,1,0, trsf[1]*scale, - 0,0,1, trsf[2]*scale, - 0,0,0, 1) + for c in self.__inputcards__: + if c.ctype != mp.CID.data: + continue + c.get_values() + if c.dtype == "TRn": + trValues = [] + for v in c.values[1:]: + trValues.append(v[0]) + trl[c.name] = getTransMatrix(trValues, c.unit) + return trl + + +def getTransMatrix(trsf, unit="", scale=10.0): + + if len(trsf) == 3: + trsfMat = FreeCAD.Matrix( + 1, + 0, + 0, + trsf[0] * scale, + 0, + 1, + 0, + trsf[1] * scale, + 0, + 0, + 1, + trsf[2] * scale, + 0, + 0, + 0, + 1, + ) else: - if unit == '*': - coeff = tuple(map(math.radians,trsf[3:12] )) - coeff = tuple(map(math.cos,coeff)) - else: - coeff = trsf[3:12] - - trsfMat = FreeCAD.Matrix(coeff[0],coeff[3] ,coeff[6], trsf[0]*scale, - coeff[1],coeff[4] ,coeff[7], trsf[1]*scale, - coeff[2],coeff[5] ,coeff[8], trsf[2]*scale, - 0,0,0, 1) - -def substituteLikeCell(universe,Surfaces): + if unit == "*": + coeff = tuple(map(math.radians, trsf[3:12])) + coeff = tuple(map(math.cos, coeff)) + else: + coeff = trsf[3:12] + + trsfMat = FreeCAD.Matrix( + coeff[0], + coeff[3], + coeff[6], + trsf[0] * scale, + coeff[1], + coeff[4], + coeff[7], + trsf[1] * scale, + coeff[2], + coeff[5], + coeff[8], + trsf[2] * scale, + 0, + 0, + 0, + 1, + ) + + +def substituteLikeCell(universe, Surfaces): number = re.compile(r"\#?\s*\d+") newId = len(Surfaces) - # create new cells objects for like cell cells - for c in universe.values(): - if c.likeCell : c.geom = universe[c.likeCell].geom.copy() - if not c.TRCL : continue # likebut cell should have TRCL card + # create new cells objects for like cell cells + for c in universe.values(): + if c.likeCell: + c.geom = universe[c.likeCell].geom.copy() + if not c.TRCL: + continue # likebut cell should have TRCL card # transform change cell the parameters if needed for c in universe.values(): - if not c.TRCL : continue - cellSurf = c.geom.getSurfacesNumbers() - surfDict = {} - for surf in cellSurf: - newId += 1 - surfDict[surf] = newId - Surfaces[newId] = Surfaces[surf].copy() - Surfaces[newId].id = newId - Surfaces[newId].transform(c.TRCL) - if c.FILL : c.TR = c.TRCL - c.TRCL = None - - # rename the surface of the like cell - pos = 0 - while True: - m = number.search(c.geom.str,pos) - if not m : break - if "#" in m.group(): - pos = m.end() - continue - surf = int(m.group()) - pos = c.geom.replace(surf,surfDict[surf],pos) - if pos < 0 : break - -def selectCells(cellList,config): + if not c.TRCL: + continue + cellSurf = c.geom.getSurfacesNumbers() + surfDict = {} + for surf in cellSurf: + newId += 1 + surfDict[surf] = newId + Surfaces[newId] = Surfaces[surf].copy() + Surfaces[newId].id = newId + Surfaces[newId].transform(c.TRCL) + if c.FILL: + c.TR = c.TRCL + c.TRCL = None + + # rename the surface of the like cell + pos = 0 + while True: + m = number.search(c.geom.str, pos) + if not m: + break + if "#" in m.group(): + pos = m.end() + continue + surf = int(m.group()) + pos = c.geom.replace(surf, surfDict[surf], pos) + if pos < 0: + break + + +def selectCells(cellList, config): selected = {} - # options are 'all' material - if config['mat'][0] == 'all' : - if config['cell'][0]=='all' : - selected = cellList - elif config['cell'][0]=='exclude' : - for name,c in cellList.items(): - if name not in config['cell'][1]: - selected[name] = c - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if name in config['cell'][1]: - selected[name] = c - - # options are 'exclude' material - elif config['mat'][0] == 'exclude': - if config['cell'][0]=='all' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: + # options are 'all' material + if config["mat"][0] == "all": + if config["cell"][0] == "all": + selected = cellList + elif config["cell"][0] == "exclude": + for name, c in cellList.items(): + if name not in config["cell"][1]: selected[name] = c - else: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='exclude' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: - if name not in config['cell'][1]: - selected[name] = c - else: - if name not in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: - if name in config['cell'][1]: - selected[name] = c - else: - if name in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - - # options are 'include' material - elif config['mat'][0] == 'include': - if config['cell'][0]=='all' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT in config['mat'][1]: + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if name in config["cell"][1]: selected[name] = c - else: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='exclude' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT in config['mat'][1]: - if name not in config['cell'][1]: - selected[name] = c - else: - if name not in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT in config['mat'][1]: - if name in config['cell'][1]: - selected[name] = c - else: - if name in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number + # options are 'exclude' material + elif config["mat"][0] == "exclude": + if config["cell"][0] == "all": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + selected[name] = c + else: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "exclude": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + if name not in config["cell"][1]: + selected[name] = c + else: + if name not in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + if name in config["cell"][1]: + selected[name] = c + else: + if name in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + + # options are 'include' material + elif config["mat"][0] == "include": + if config["cell"][0] == "all": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT in config["mat"][1]: + selected[name] = c + else: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "exclude": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT in config["mat"][1]: + if name not in config["cell"][1]: + selected[name] = c + else: + if name not in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT in config["mat"][1]: + if name in config["cell"][1]: + selected[name] = c + else: + if name in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) # remove complementary in cell of the universe - for cname,c in selected.items() : - c.geom = remove_hash(cellList,cname) + for cname, c in selected.items(): + c.geom = remove_hash(cellList, cname) if not selected: - raise ValueError("No cells selected. Check input or selection criteria in config file.") + raise ValueError( + "No cells selected. Check input or selection criteria in config file." + ) + + return selected + - return selected - -#Change implicit cell definition (like-but type or cell with #) +# Change implicit cell definition (like-but type or cell with #) # to explicit cell definition (only surface number) def setExplicitCellDefinition(universeCells): - for cname,c in universeCells.items(): - if c.likeCell : - lkc = universeCells[c.likeCell] - c.geom = lkc.geom - if not c.U : c.U = lkc.U - if not c.FILL : c.FILL = lkc.FILL - if not c.MAT : c.MAT = lkc.MAT - if not c.TR : c.TR = lkc.TR - if not c.TRCL : c.TRCL = lkc.TRCL - return - - -def processSurfaces(UCells,Surfaces): + for cname, c in universeCells.items(): + if c.likeCell: + lkc = universeCells[c.likeCell] + c.geom = lkc.geom + if not c.U: + c.U = lkc.U + if not c.FILL: + c.FILL = lkc.FILL + if not c.MAT: + c.MAT = lkc.MAT + if not c.TR: + c.TR = lkc.TR + if not c.TRCL: + c.TRCL = lkc.TRCL + return + + +def processSurfaces(UCells, Surfaces): number = re.compile(r"\#?\s*\d+") - for cname,c in UCells.items() : - c.geom.remove_comments(full=True) + for cname, c in UCells.items(): + c.geom.remove_comments(full=True) pos = 0 while True: - m = number.search(c.geom.str,pos) - if not m : break - if "#" in m.group(): - pos = m.end() - continue - surf = int(m.group()) - if surf == 0 : - print(c.name) - print(m) - print(c.geom.str) - pos = c.geom.replace(surf,Surfaces[surf].id,pos) - - -def getTransMatrix(trsf,unit='',scale=10.): - - if len(trsf) == 3 : - trsfMat = FreeCAD.Matrix(1,0,0, trsf[0]*scale, - 0,1,0, trsf[1]*scale, - 0,0,1, trsf[2]*scale, - 0,0,0, 1) + m = number.search(c.geom.str, pos) + if not m: + break + if "#" in m.group(): + pos = m.end() + continue + surf = int(m.group()) + if surf == 0: + print(c.name) + print(m) + print(c.geom.str) + pos = c.geom.replace(surf, Surfaces[surf].id, pos) + + +def getTransMatrix(trsf, unit="", scale=10.0): + + if len(trsf) == 3: + trsfMat = FreeCAD.Matrix( + 1, + 0, + 0, + trsf[0] * scale, + 0, + 1, + 0, + trsf[1] * scale, + 0, + 0, + 1, + trsf[2] * scale, + 0, + 0, + 0, + 1, + ) else: - if unit == '*': - coeff = tuple(map(math.radians,trsf[3:12] )) - coeff = tuple(map(math.cos,coeff)) - else: - coeff = trsf[3:12] - - trsfMat = FreeCAD.Matrix(coeff[0],coeff[3] ,coeff[6], trsf[0]*scale, - coeff[1],coeff[4] ,coeff[7], trsf[1]*scale, - coeff[2],coeff[5] ,coeff[8], trsf[2]*scale, - 0,0,0, 1) - return trsfMat - -def TransformationMatrix(TRSF,Transformations): - - if TRSF : - if type(TRSF) is int : - return Transformations[TRSF] - - else: - return getTransMatrix(TRSF) - else: - return TRSF - + if unit == "*": + coeff = tuple(map(math.radians, trsf[3:12])) + coeff = tuple(map(math.cos, coeff)) + else: + coeff = trsf[3:12] + + trsfMat = FreeCAD.Matrix( + coeff[0], + coeff[3], + coeff[6], + trsf[0] * scale, + coeff[1], + coeff[4], + coeff[7], + trsf[1] * scale, + coeff[2], + coeff[5], + coeff[8], + trsf[2] * scale, + 0, + 0, + 0, + 1, + ) + return trsfMat + + +def TransformationMatrix(TRSF, Transformations): + + if TRSF: + if type(TRSF) is int: + return Transformations[TRSF] + + else: + return getTransMatrix(TRSF) + else: + return TRSF -def getSubUniverses(Ustart,Universes): - Uid = set() - for c in Universes[Ustart].values() : - if c.FILL : Uid.add(c.FILL) +def getSubUniverses(Ustart, Universes): + Uid = set() + for c in Universes[Ustart].values(): + if c.FILL: + Uid.add(c.FILL) AllU = Uid.copy() for U in Uid: - AllU = AllU.union(getSubUniverses(U,Universes)) - - return AllU + AllU = AllU.union(getSubUniverses(U, Universes)) + + return AllU + # traduce mcnp surface definition for Solid_Cell class # planes: @@ -394,802 +483,867 @@ def getSubUniverses(Ustart,Universes): # Stype = 'torus' # params = [[px,py,pz],[vx,vy,vz],ra,r] + # Return a diccionary with the corresponding surface Object -def Get_primitive_surfaces(mcnp_surfaces,scale=10.) : - - X_vec = FreeCAD.Vector(1.0,0.0,0.0) - Y_vec = FreeCAD.Vector(0.0,1.0,0.0) - Z_vec = FreeCAD.Vector(0.0,0.0,1.0) - negX_vec = -X_vec - negY_vec = -Y_vec - negZ_vec = -Z_vec - origin= FreeCAD.Vector(0.0,0.0,0.0) - - surfaces = {} - for Sid in mcnp_surfaces.keys() : - MCNPtype = mcnp_surfaces[Sid][0].upper() - MCNPparams = mcnp_surfaces[Sid][1] - trsf = mcnp_surfaces[Sid][2] - number = mcnp_surfaces[Sid][3] - - params = [] - Stype = None - if MCNPtype in ('P','PX','PY','PZ'): - Stype = 'plane' - if MCNPtype == 'P': - if len(MCNPparams) == 4 : - normal = FreeCAD.Vector(MCNPparams[0:3]) - params = (normal, MCNPparams[3]*scale) +def Get_primitive_surfaces(mcnp_surfaces, scale=10.0): + + X_vec = FreeCAD.Vector(1.0, 0.0, 0.0) + Y_vec = FreeCAD.Vector(0.0, 1.0, 0.0) + Z_vec = FreeCAD.Vector(0.0, 0.0, 1.0) + negX_vec = -X_vec + negY_vec = -Y_vec + negZ_vec = -Z_vec + origin = FreeCAD.Vector(0.0, 0.0, 0.0) + + surfaces = {} + for Sid in mcnp_surfaces.keys(): + MCNPtype = mcnp_surfaces[Sid][0].upper() + MCNPparams = mcnp_surfaces[Sid][1] + trsf = mcnp_surfaces[Sid][2] + number = mcnp_surfaces[Sid][3] + + params = [] + Stype = None + if MCNPtype in ("P", "PX", "PY", "PZ"): + Stype = "plane" + if MCNPtype == "P": + if len(MCNPparams) == 4: + normal = FreeCAD.Vector(MCNPparams[0:3]) + params = (normal, MCNPparams[3] * scale) else: - coeffs = pointsToCoeffs(MCNPparams[0:9]) - normal = FreeCAD.Vector(coeffs[0:3]) - point = coeffs[3]/normal.Length - normal.normalize() - params = (normal, point*scale) - elif MCNPtype == 'PX': - params = (X_vec, MCNPparams[0]*scale ) - elif MCNPtype == 'PY': - params = ( Y_vec, MCNPparams[0]*scale ) - elif MCNPtype == 'PZ': - params = ( Z_vec, MCNPparams[0]*scale ) - - elif MCNPtype in ['S','SX','SY','SZ','SO','SPH'] : - Stype = 'sphere' - if MCNPtype in ['S','SPH']: - params = (FreeCAD.Vector(MCNPparams[0:3])*scale, MCNPparams[3]*scale) - elif MCNPtype == 'SX': - params = ( FreeCAD.Vector(MCNPparams[0]*scale, 0.0, 0.0), MCNPparams[1]*scale ) - elif MCNPtype == 'SY': - params = ( FreeCAD.Vector(0.0, MCNPparams[0]*scale, 0.0), MCNPparams[1]*scale ) - elif MCNPtype == 'SZ': - params = ( FreeCAD.Vector(0.0, 0.0, MCNPparams[0]*scale), MCNPparams[1]*scale ) - elif MCNPtype == 'SO': - params = ( origin, MCNPparams[0]*scale ) - - elif MCNPtype in ['CX','C/X','CY','C/Y','CZ','C/Z'] : - if MCNPtype in ['CX','CY','CZ']: - R = MCNPparams[0] + coeffs = pointsToCoeffs(MCNPparams[0:9]) + normal = FreeCAD.Vector(coeffs[0:3]) + point = coeffs[3] / normal.Length + normal.normalize() + params = (normal, point * scale) + elif MCNPtype == "PX": + params = (X_vec, MCNPparams[0] * scale) + elif MCNPtype == "PY": + params = (Y_vec, MCNPparams[0] * scale) + elif MCNPtype == "PZ": + params = (Z_vec, MCNPparams[0] * scale) + + elif MCNPtype in ["S", "SX", "SY", "SZ", "SO", "SPH"]: + Stype = "sphere" + if MCNPtype in ["S", "SPH"]: + params = ( + FreeCAD.Vector(MCNPparams[0:3]) * scale, + MCNPparams[3] * scale, + ) + elif MCNPtype == "SX": + params = ( + FreeCAD.Vector(MCNPparams[0] * scale, 0.0, 0.0), + MCNPparams[1] * scale, + ) + elif MCNPtype == "SY": + params = ( + FreeCAD.Vector(0.0, MCNPparams[0] * scale, 0.0), + MCNPparams[1] * scale, + ) + elif MCNPtype == "SZ": + params = ( + FreeCAD.Vector(0.0, 0.0, MCNPparams[0] * scale), + MCNPparams[1] * scale, + ) + elif MCNPtype == "SO": + params = (origin, MCNPparams[0] * scale) + + elif MCNPtype in ["CX", "C/X", "CY", "C/Y", "CZ", "C/Z"]: + if MCNPtype in ["CX", "CY", "CZ"]: + R = MCNPparams[0] else: - R = MCNPparams[2] - x1 = MCNPparams[0] - x2 = MCNPparams[1] - - Stype = 'cylinder' - - if MCNPtype == 'CX': + R = MCNPparams[2] + x1 = MCNPparams[0] + x2 = MCNPparams[1] + + Stype = "cylinder" + + if MCNPtype == "CX": v = X_vec p = origin - elif MCNPtype == 'CY': + elif MCNPtype == "CY": v = Y_vec p = origin - elif MCNPtype == 'CZ': + elif MCNPtype == "CZ": v = Z_vec p = origin - elif MCNPtype == 'C/X': + elif MCNPtype == "C/X": v = X_vec - p = FreeCAD.Vector(0., x1, x2) - elif MCNPtype == 'C/Y': + p = FreeCAD.Vector(0.0, x1, x2) + elif MCNPtype == "C/Y": v = Y_vec - p = FreeCAD.Vector(x1, 0., x2) - elif MCNPtype == 'C/Z': + p = FreeCAD.Vector(x1, 0.0, x2) + elif MCNPtype == "C/Z": v = Z_vec - p = FreeCAD.Vector(x1, x2, 0.) + p = FreeCAD.Vector(x1, x2, 0.0) - if scale != 1.0 : - p = p.multiply(scale) - R *= scale + if scale != 1.0: + p = p.multiply(scale) + R *= scale - params = ( p,v,R ) + params = (p, v, R) - elif MCNPtype in ['KX','KY','KZ'] : - Stype = 'cone' - x1,t2 = MCNPparams[0:2] - t = math.sqrt(t2) + elif MCNPtype in ["KX", "KY", "KZ"]: + Stype = "cone" + x1, t2 = MCNPparams[0:2] + t = math.sqrt(t2) dblsht = True if len(MCNPparams) == 3: - dblsht = False - sht = MCNPparams[2] - if sht == 0. : - dblsht = True - - if MCNPtype == 'KX': - p = FreeCAD.Vector(x1,0.0,0.0) - v = X_vec - if not dblsht : - if sht < 0 : - v = negX_vec - elif MCNPtype == 'KY': - p = FreeCAD.Vector(0.0,x1,0.0) - v = Y_vec - if not dblsht : - if sht < 0 : - v = negY_vec - elif MCNPtype == 'KZ': - p = FreeCAD.Vector(0.0,0.0,x1) - v = Z_vec - if not dblsht : - if sht < 0 : - v = negZ_vec + dblsht = False + sht = MCNPparams[2] + if sht == 0.0: + dblsht = True + + if MCNPtype == "KX": + p = FreeCAD.Vector(x1, 0.0, 0.0) + v = X_vec + if not dblsht: + if sht < 0: + v = negX_vec + elif MCNPtype == "KY": + p = FreeCAD.Vector(0.0, x1, 0.0) + v = Y_vec + if not dblsht: + if sht < 0: + v = negY_vec + elif MCNPtype == "KZ": + p = FreeCAD.Vector(0.0, 0.0, x1) + v = Z_vec + if not dblsht: + if sht < 0: + v = negZ_vec p = p.multiply(scale) - params = (p,v,t,dblsht) + params = (p, v, t, dblsht) - - elif MCNPtype in ['K/X','K/Y','K/Z'] : - Stype = 'cone' - p = FreeCAD.Vector(MCNPparams[0:3]) + elif MCNPtype in ["K/X", "K/Y", "K/Z"]: + Stype = "cone" + p = FreeCAD.Vector(MCNPparams[0:3]) t2 = MCNPparams[3] - t = math.sqrt(t2) + t = math.sqrt(t2) dblsht = True if len(MCNPparams) == 5: - dblsht = False - sht = MCNPparams[4] - if sht == 0. : - dblsht = True - - if MCNPtype == 'K/X': - v = X_vec - if not dblsht : - if sht < 0 : - v = negX_vec - elif MCNPtype == 'K/Y': - v = Y_vec - if not dblsht : - if sht < 0 : - v = negY_vec - elif MCNPtype == 'K/Z': - v = Z_vec - if not dblsht : - if sht < 0 : - v = negZ_vec + dblsht = False + sht = MCNPparams[4] + if sht == 0.0: + dblsht = True + + if MCNPtype == "K/X": + v = X_vec + if not dblsht: + if sht < 0: + v = negX_vec + elif MCNPtype == "K/Y": + v = Y_vec + if not dblsht: + if sht < 0: + v = negY_vec + elif MCNPtype == "K/Z": + v = Z_vec + if not dblsht: + if sht < 0: + v = negZ_vec p = p.multiply(scale) - params = (p,v,t,dblsht) - - elif MCNPtype in ['TX','TY','TZ'] : - Stype = 'torus' - p = FreeCAD.Vector(MCNPparams[0:3]) - Ra,Rb,Rc = MCNPparams[3:6] - - if MCNPtype == 'TX': - v = X_vec - elif MCNPtype == 'TY': - v = Y_vec - elif MCNPtype == 'TZ': - v = Z_vec - - if scale != 1.0 : - Ra *= scale - Rb *= scale - Rc *= scale - p = p.multiply(scale) - - params = ( p,v,Ra,Rb,Rc) - - elif MCNPtype == 'GQ' or MCNPtype == 'SQ': - Qparams = tuple(MCNPparams[0:10]) - - if MCNPtype == 'SQ' : - Stype,quadric = sq2params(Qparams) + params = (p, v, t, dblsht) + + elif MCNPtype in ["TX", "TY", "TZ"]: + Stype = "torus" + p = FreeCAD.Vector(MCNPparams[0:3]) + Ra, Rb, Rc = MCNPparams[3:6] + + if MCNPtype == "TX": + v = X_vec + elif MCNPtype == "TY": + v = Y_vec + elif MCNPtype == "TZ": + v = Z_vec + + if scale != 1.0: + Ra *= scale + Rb *= scale + Rc *= scale + p = p.multiply(scale) + + params = (p, v, Ra, Rb, Rc) + + elif MCNPtype == "GQ" or MCNPtype == "SQ": + Qparams = tuple(MCNPparams[0:10]) + + if MCNPtype == "SQ": + Stype, quadric = sq2params(Qparams) else: - Stype,quadric = gq2params(Qparams) + Stype, quadric = gq2params(Qparams) - if Stype == 'cylinder' : + if Stype == "cylinder": # p = FreeCAD.Vector(quadric[0:3]) # v = FreeCAD.Vector(quadric[3:6]) # R = quadric[6] - p,v,R = quadric - if scale != 1.0 : - R *= scale - p = p.multiply(scale) - - params = ( p,v,R ) - - elif Stype == 'cylinder_elliptic' : - p,v,radii,raxes = quadric - if scale != 1.0 : - radii[0] *= scale - radii[1] *= scale - p = p.multiply(scale) - params = ( p,v,radii,raxes ) - - elif Stype == 'cylinder_hyperbolic' : - p,v,radii,raxes = quadric - if scale != 1.0 : - radii[0] *= scale - radii[1] *= scale - p = p.multiply(scale) - params = ( p,v,radii,raxes ) - - elif Stype == 'cone' : - #p = FreeCAD.Vector(quadric[0:3]) - #v = FreeCAD.Vector(quadric[3:6]) - #t = quadric[6] - #dblsht = quadric[7] - p,v,t,dblsht = quadric - if scale != 1.0 : + p, v, R = quadric + if scale != 1.0: + R *= scale + p = p.multiply(scale) + + params = (p, v, R) + + elif Stype == "cylinder_elliptic": + p, v, radii, raxes = quadric + if scale != 1.0: + radii[0] *= scale + radii[1] *= scale + p = p.multiply(scale) + params = (p, v, radii, raxes) + + elif Stype == "cylinder_hyperbolic": + p, v, radii, raxes = quadric + if scale != 1.0: + radii[0] *= scale + radii[1] *= scale + p = p.multiply(scale) + params = (p, v, radii, raxes) + + elif Stype == "cone": + # p = FreeCAD.Vector(quadric[0:3]) + # v = FreeCAD.Vector(quadric[3:6]) + # t = quadric[6] + # dblsht = quadric[7] + p, v, t, dblsht = quadric + if scale != 1.0: + p = p.multiply(scale) + params = (p, v, t, dblsht) + + elif Stype == "cone_elliptic": + p, v, Ra, radii, raxes, dblsht = quadric + if scale != 1.0: + Ra *= scale + radii[0] *= scale + radii[1] *= scale + p = p.multiply(scale) + params = (p, v, Ra, radii, raxes, dblsht) + + elif Stype == "hyperboloid": + p, v, radii, raxes, onesht = quadric + if scale != 1.0: + radii[0] *= scale + radii[1] *= scale + p = p.multiply(scale) + params = (p, v, radii, raxes, onesht) + + elif Stype == "ellipsoid": + p, v, radii, raxes = quadric + if scale != 1.0: + radii[0] *= scale + radii[1] *= scale p = p.multiply(scale) - params = ( p,v,t,dblsht ) - - elif Stype == 'cone_elliptic' : - p,v,Ra,radii,raxes,dblsht = quadric - if scale != 1.0 : - Ra *= scale - radii[0] *= scale - radii[1] *= scale - p = p.multiply(scale) - params = ( p,v,Ra,radii,raxes,dblsht ) - - elif Stype == 'hyperboloid' : - p,v,radii,raxes,onesht = quadric - if scale != 1.0 : - radii[0] *= scale - radii[1] *= scale - p = p.multiply(scale) - params = ( p,v,radii,raxes,onesht ) - - elif Stype == 'ellipsoid' : - p,v,radii,raxes = quadric - if scale != 1.0 : - radii[0] *= scale - radii[1] *= scale - p = p.multiply(scale) - params = ( p,v,radii,raxes ) - - elif Stype == 'paraboloid' : - p,v,focal = quadric - if scale != 1.0 : - focal *= scale - p = p.multiply(scale) - - params = ( p,v,focal ) + params = (p, v, radii, raxes) + + elif Stype == "paraboloid": + p, v, focal = quadric + if scale != 1.0: + focal *= scale + p = p.multiply(scale) + + params = (p, v, focal) else: - print ( Stype ) + print(Stype) params = None -# get_quadric_surface(params) - - elif MCNPtype == 'X' : - if len(MCNPparams) == 2 : - Stype = 'plane' - params = (X_vec, MCNPparams[0]*scale ) - elif len(MCNPparams) == 4 : - if ( abs(MCNPparams[1] - MCNPparams[3]) ) > 1.e-12 : - Stype = 'cone' + # get_quadric_surface(params) + + elif MCNPtype == "X": + if len(MCNPparams) == 2: + Stype = "plane" + params = (X_vec, MCNPparams[0] * scale) + elif len(MCNPparams) == 4: + if (abs(MCNPparams[1] - MCNPparams[3])) > 1.0e-12: + Stype = "cone" dblsht = False - t = (MCNPparams[3] - MCNPparams[1])/(MCNPparams[2] - MCNPparams[0]) - x = MCNPparams[0] - MCNPparams[1]/t - if (MCNPparams[0]-x)*(MCNPparams[2]-x) > 0 : - p = FreeCAD.Vector(x,0.,0.) - if (MCNPparams[0]-x) > 0 : - v = X_vec + t = (MCNPparams[3] - MCNPparams[1]) / ( + MCNPparams[2] - MCNPparams[0] + ) + x = MCNPparams[0] - MCNPparams[1] / t + if (MCNPparams[0] - x) * (MCNPparams[2] - x) > 0: + p = FreeCAD.Vector(x, 0.0, 0.0) + if (MCNPparams[0] - x) > 0: + v = X_vec else: - v = negX_vec - if scale != 1.0 : p *= scale - params = (p,v,abs(t),dblsht) - elif abs(MCNPparams[1]) < 1.e-12 : - Stype = 'plane' - if ( abs(MCNPparams[0] - MCNPparams[2]) ) < 1.e-12 : - params = (X_vec, MCNPparams[0]*scale ) - else: - Stype = 'cylinder' - if scale != 1.0 : - p = p.multiply(scale) - R *= scale - params = ( origin,X_vec,MCNPparams[1] ) - else: - print('not implemented surfaces defined by point with more than 2couples of value') - - elif MCNPtype == 'Y' : - if len(MCNPparams) == 2 : - Stype = 'plane' - params = (Y_vec, MCNPparams[0]*scale ) - elif len(MCNPparams) == 4 : - if ( abs(MCNPparams[1] - MCNPparams[3]) ) > 1.e-12 : - Stype = 'cone' + v = negX_vec + if scale != 1.0: + p *= scale + params = (p, v, abs(t), dblsht) + elif abs(MCNPparams[1]) < 1.0e-12: + Stype = "plane" + if (abs(MCNPparams[0] - MCNPparams[2])) < 1.0e-12: + params = (X_vec, MCNPparams[0] * scale) + else: + Stype = "cylinder" + if scale != 1.0: + p = p.multiply(scale) + R *= scale + params = (origin, X_vec, MCNPparams[1]) + else: + print( + "not implemented surfaces defined by point with more than 2couples of value" + ) + + elif MCNPtype == "Y": + if len(MCNPparams) == 2: + Stype = "plane" + params = (Y_vec, MCNPparams[0] * scale) + elif len(MCNPparams) == 4: + if (abs(MCNPparams[1] - MCNPparams[3])) > 1.0e-12: + Stype = "cone" dblsht = False - t = (MCNPparams[3] - MCNPparams[1])/(MCNPparams[2] - MCNPparams[0]) - y = MCNPparams[0] - MCNPparams[1]/t - if (MCNPparams[0]-y)*(MCNPparams[2]-y) > 0 : - p = FreeCAD.Vector(0.,y,0.) - if (MCNPparams[0]-y) > 0 : - v = Y_vec + t = (MCNPparams[3] - MCNPparams[1]) / ( + MCNPparams[2] - MCNPparams[0] + ) + y = MCNPparams[0] - MCNPparams[1] / t + if (MCNPparams[0] - y) * (MCNPparams[2] - y) > 0: + p = FreeCAD.Vector(0.0, y, 0.0) + if (MCNPparams[0] - y) > 0: + v = Y_vec else: - v = negY_vec - if scale != 1.0 : p = p.multiply(scale) - params = (p,v,abs(t),dblsht) - elif abs(MCNPparams[1]) < 1.e-12 : - Stype = 'plane' - if ( abs(MCNPparams[0] - MCNPparams[2]) ) < 1.e-12 : - params = (Y_vec, MCNPparams[0]*scale ) - else: - Stype = 'cylinder' - if scale != 1.0 : - p = p.multiply(scale) - R *= scale - params = ( origin,Y_vec,MCNPparams[1] ) - else: - print('not implemented surfaces defined by point with more than 2couples of value') - - elif MCNPtype == 'Z' : - if len(MCNPparams) == 2 : - Stype = 'plane' - params = (Z_vec, MCNPparams[0]*scale ) - elif len(MCNPparams) == 4 : - if ( abs(MCNPparams[1] - MCNPparams[3]) ) > 1.e-12 : - Stype = 'cone' + v = negY_vec + if scale != 1.0: + p = p.multiply(scale) + params = (p, v, abs(t), dblsht) + elif abs(MCNPparams[1]) < 1.0e-12: + Stype = "plane" + if (abs(MCNPparams[0] - MCNPparams[2])) < 1.0e-12: + params = (Y_vec, MCNPparams[0] * scale) + else: + Stype = "cylinder" + if scale != 1.0: + p = p.multiply(scale) + R *= scale + params = (origin, Y_vec, MCNPparams[1]) + else: + print( + "not implemented surfaces defined by point with more than 2couples of value" + ) + + elif MCNPtype == "Z": + if len(MCNPparams) == 2: + Stype = "plane" + params = (Z_vec, MCNPparams[0] * scale) + elif len(MCNPparams) == 4: + if (abs(MCNPparams[1] - MCNPparams[3])) > 1.0e-12: + Stype = "cone" dblsht = False - t = (MCNPparams[3] - MCNPparams[1])/(MCNPparams[2] - MCNPparams[0]) - z = MCNPparams[0] - MCNPparams[1]/t - if (MCNPparams[0]-z)*(MCNPparams[2]-z) > 0 : - p = FreeCAD.Vector(0.,0.,z) - if (MCNPparams[0]-z) > 0 : - v = Z_vec + t = (MCNPparams[3] - MCNPparams[1]) / ( + MCNPparams[2] - MCNPparams[0] + ) + z = MCNPparams[0] - MCNPparams[1] / t + if (MCNPparams[0] - z) * (MCNPparams[2] - z) > 0: + p = FreeCAD.Vector(0.0, 0.0, z) + if (MCNPparams[0] - z) > 0: + v = Z_vec else: - v = negZ_vec - if scale != 1.0 : p = p.multiply(scale) - params = (p,v,abs(t),dblsht) - elif abs(MCNPparams[1]) < 1.e-12 : - Stype = 'plane' - if ( abs(MCNPparams[0] - MCNPparams[2]) ) < 1.e-12 : - params = (Z_vec, MCNPparams[0]*scale ) - else: - Stype = 'cylinder' - if scale != 1.0 : - p = p.multiply(scale) - R *= scale - params = ( origin,Z_vec,MCNPparams[1] ) - else: - print('not implemented surfaces defined by point with more than 2couples of value') - - elif MCNPtype == 'BOX' : - Stype = 'box' - p = FreeCAD.Vector(MCNPparams[0:3]) + v = negZ_vec + if scale != 1.0: + p = p.multiply(scale) + params = (p, v, abs(t), dblsht) + elif abs(MCNPparams[1]) < 1.0e-12: + Stype = "plane" + if (abs(MCNPparams[0] - MCNPparams[2])) < 1.0e-12: + params = (Z_vec, MCNPparams[0] * scale) + else: + Stype = "cylinder" + if scale != 1.0: + p = p.multiply(scale) + R *= scale + params = (origin, Z_vec, MCNPparams[1]) + else: + print( + "not implemented surfaces defined by point with more than 2couples of value" + ) + + elif MCNPtype == "BOX": + Stype = "box" + p = FreeCAD.Vector(MCNPparams[0:3]) v1 = FreeCAD.Vector(MCNPparams[3:6]) v2 = FreeCAD.Vector(MCNPparams[6:9]) v3 = FreeCAD.Vector(MCNPparams[9:12]) - if scale != 1.0 : - p = p.multiply(scale) - v1 = v1.multiply(scale) - v2 = v2.multiply(scale) - v3 = v3.multiply(scale) - params = ( p,v1,v2,v3 ) - - elif MCNPtype == 'RPP' : - Stype = 'box' - xmin,xmax,ymin,ymax,zmin,zmax = MCNPparams[0:6] - lx = xmax-xmin - ly = ymax-ymin - lz = zmax-zmin - p = FreeCAD.Vector(xmin,ymin,zmin) - v1 = FreeCAD.Vector(lx,0,0) - v2 = FreeCAD.Vector(0,ly,0) - v3 = FreeCAD.Vector(0,0,lz) - if scale != 1.0 : - p = p.multiply(scale) - v1 = v1.multiply(scale) - v2 = v2.multiply(scale) - v3 = v3.multiply(scale) - params = ( p,v1,v2,v3 ) - - elif MCNPtype == 'RCC' : - Stype = 'can' - p = FreeCAD.Vector(MCNPparams[0:3]) - v = FreeCAD.Vector(MCNPparams[3:6]) + if scale != 1.0: + p = p.multiply(scale) + v1 = v1.multiply(scale) + v2 = v2.multiply(scale) + v3 = v3.multiply(scale) + params = (p, v1, v2, v3) + + elif MCNPtype == "RPP": + Stype = "box" + xmin, xmax, ymin, ymax, zmin, zmax = MCNPparams[0:6] + lx = xmax - xmin + ly = ymax - ymin + lz = zmax - zmin + p = FreeCAD.Vector(xmin, ymin, zmin) + v1 = FreeCAD.Vector(lx, 0, 0) + v2 = FreeCAD.Vector(0, ly, 0) + v3 = FreeCAD.Vector(0, 0, lz) + if scale != 1.0: + p = p.multiply(scale) + v1 = v1.multiply(scale) + v2 = v2.multiply(scale) + v3 = v3.multiply(scale) + params = (p, v1, v2, v3) + + elif MCNPtype == "RCC": + Stype = "can" + p = FreeCAD.Vector(MCNPparams[0:3]) + v = FreeCAD.Vector(MCNPparams[3:6]) R = MCNPparams[6] - if scale != 1.0 : - p = p.multiply(scale) - v = v.multiply(scale) - R *= scale - params = ( p,v,R ) - - elif MCNPtype == 'REC' : - Stype = 'ecan' - p = FreeCAD.Vector(MCNPparams[0:3]) - v = FreeCAD.Vector(MCNPparams[3:6]) + if scale != 1.0: + p = p.multiply(scale) + v = v.multiply(scale) + R *= scale + params = (p, v, R) + + elif MCNPtype == "REC": + Stype = "ecan" + p = FreeCAD.Vector(MCNPparams[0:3]) + v = FreeCAD.Vector(MCNPparams[3:6]) majAxis = FreeCAD.Vector(MCNPparams[6:9]) - majRad = majAxis.Length + majRad = majAxis.Length majAxis.normalize() - + if len(MCNPparams) == 12: - minAxis = FreeCAD.Vector(MCNPparams[9:12]) - minRad = minAxis.Length - minAxis.normalize() + minAxis = FreeCAD.Vector(MCNPparams[9:12]) + minRad = minAxis.Length + minAxis.normalize() else: - minRad = MCNPparams[9] - minAxis = v.cross(majAxis)/v.Length - - if scale != 1.0 : - p = p.multiply(scale) - v = v.multiply(scale) - majRad *= scale - minRad *= scale - - if minRad > majRad : - minRad,majRad = majRad,minRad - minAxis,majAxis = majAxis,minAxis - - params = ( p,v,[minRad,majRad],[minAxis,majAxis]) - - elif MCNPtype == 'TRC' : - Stype = 'tcone' - p = FreeCAD.Vector(MCNPparams[0:3]) - v = FreeCAD.Vector(MCNPparams[3:6]) - R1,R2 = MCNPparams[6:8] - if scale != 1.0 : - p = p.multiply(scale) - v = v.multiply(scale) - R1 *= scale - R2 *= scale - params = ( p,v,R1,R2 ) - - - if Stype == 'plane': - surfaces[Sid] = Plane(number, params, trsf) - elif Stype == 'sphere': - surfaces[Sid] = Sphere(number, params, trsf) - elif Stype == 'cylinder' or Stype == 'can': - surfaces[Sid] = Cylinder(number, params,trsf, Stype == 'can' ) - elif Stype == 'cylinder_elliptic' or Stype == 'ecan': - surfaces[Sid] = EllipticCylinder(number, params,trsf, Stype == 'ecan' ) - elif Stype == 'cylinder_hyperbolic' : - surfaces[Sid] = HyperbolicCylinder(number, params,trsf ) - elif Stype == 'cone' or Stype == 'tcone' : - surfaces[Sid] = Cone(number, params,trsf, Stype == 'tcone') - elif Stype == 'cone_elliptic' : - surfaces[Sid] = EllipticCone(number, params,trsf) - elif Stype == 'hyperboloid' : - surfaces[Sid] = Hyperboloid(number, params,trsf) - elif Stype == 'ellipsoid' : - surfaces[Sid] = Ellipsoid(number, params,trsf) - elif Stype == 'paraboloid' : - surfaces[Sid] = Paraboloid(number, params,trsf) - elif Stype == 'torus': - surfaces[Sid] = Torus(number, params,trsf) - elif Stype == 'box': - surfaces[Sid] = Box(number, params,trsf) - else : - print('Undefined',Sid,Stype) - print( MCNPtype ,number,MCNPparams) - - return surfaces + minRad = MCNPparams[9] + minAxis = v.cross(majAxis) / v.Length + + if scale != 1.0: + p = p.multiply(scale) + v = v.multiply(scale) + majRad *= scale + minRad *= scale + + if minRad > majRad: + minRad, majRad = majRad, minRad + minAxis, majAxis = majAxis, minAxis + + params = (p, v, [minRad, majRad], [minAxis, majAxis]) + + elif MCNPtype == "TRC": + Stype = "tcone" + p = FreeCAD.Vector(MCNPparams[0:3]) + v = FreeCAD.Vector(MCNPparams[3:6]) + R1, R2 = MCNPparams[6:8] + if scale != 1.0: + p = p.multiply(scale) + v = v.multiply(scale) + R1 *= scale + R2 *= scale + params = (p, v, R1, R2) + + if Stype == "plane": + surfaces[Sid] = Plane(number, params, trsf) + elif Stype == "sphere": + surfaces[Sid] = Sphere(number, params, trsf) + elif Stype == "cylinder" or Stype == "can": + surfaces[Sid] = Cylinder(number, params, trsf, Stype == "can") + elif Stype == "cylinder_elliptic" or Stype == "ecan": + surfaces[Sid] = EllipticCylinder(number, params, trsf, Stype == "ecan") + elif Stype == "cylinder_hyperbolic": + surfaces[Sid] = HyperbolicCylinder(number, params, trsf) + elif Stype == "cone" or Stype == "tcone": + surfaces[Sid] = Cone(number, params, trsf, Stype == "tcone") + elif Stype == "cone_elliptic": + surfaces[Sid] = EllipticCone(number, params, trsf) + elif Stype == "hyperboloid": + surfaces[Sid] = Hyperboloid(number, params, trsf) + elif Stype == "ellipsoid": + surfaces[Sid] = Ellipsoid(number, params, trsf) + elif Stype == "paraboloid": + surfaces[Sid] = Paraboloid(number, params, trsf) + elif Stype == "torus": + surfaces[Sid] = Torus(number, params, trsf) + elif Stype == "box": + surfaces[Sid] = Box(number, params, trsf) + else: + print("Undefined", Sid, Stype) + print(MCNPtype, number, MCNPparams) + + return surfaces + def pointsToCoeffs(scf): # mcnp implementation to convert 3 point plane to # plane parameters - tpp = [0]*4 - for i in range(1,4) : - j = i%3 + 1 - k = 6 -i -j - k -= 1 - j -= 1 - tpp[i-1] = scf[j ]*(scf[k+3]-scf[k+6]) \ - +scf[j+3]*(scf[k+6]-scf[k ]) \ - +scf[j+6]*(scf[k ]-scf[k+3]) - tpp[3] += scf[i-1]*(scf[j+3]*scf[k+6]-scf[j+6]*scf[k+3]) + tpp = [0] * 4 + for i in range(1, 4): + j = i % 3 + 1 + k = 6 - i - j + k -= 1 + j -= 1 + tpp[i - 1] = ( + scf[j] * (scf[k + 3] - scf[k + 6]) + + scf[j + 3] * (scf[k + 6] - scf[k]) + + scf[j + 6] * (scf[k] - scf[k + 3]) + ) + tpp[3] += scf[i - 1] * (scf[j + 3] * scf[k + 6] - scf[j + 6] * scf[k + 3]) xm = 0 - coeff = [0]*4 - for i in range(1,5): - if xm == 0 and tpp[4-i] != 0 : xm = 1/tpp[4-i] - coeff[4-i] = tpp[4-i]*xm + coeff = [0] * 4 + for i in range(1, 5): + if xm == 0 and tpp[4 - i] != 0: + xm = 1 / tpp[4 - i] + coeff[4 - i] = tpp[4 - i] * xm # coeff [0:3] a,b,c plane parameters # coeff [3] d plane parameter # normalization is d set to one if origin is not in the plane -def get_parabola_parameters(eVal,eVect,T,U): - iaxis,comp = U[1] - center = FreeCAD.Vector(T) - axis = FreeCAD.Vector(eVect[iaxis][0]) - e1 = eVal[(iaxis+1)%3] - focal = comp/(4*e1) - if focal < 0 : - focal = -focal - axis = -axis - return (center,axis,focal) - -def get_cylinder_parameters(eVal,eVect,T,k,iaxis): - - other1 = (iaxis+1)%3 - other2 = (iaxis+2)%3 - - eMin = eVal[other1] - eMaj = eVal[other2] - - - axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) - pos = FreeCAD.Vector(T) - if (abs(eMin-eMaj) < 1.e-5) : - radius = float(np.sqrt(k/eMaj)) - return 'cylinder',(pos,axis,radius) - else: - iMin = other1 - iMaj = other2 - if (abs(eMin) < abs(eMaj) ) : - eMin,eMaj = eMaj,eMin - iMin,iMaj = iMaj,iMin - - majorRad = float(np.sqrt(abs(k/eMaj))) - minorRad = float(np.sqrt(abs(k/eMin))) - minorAxis = FreeCAD.Vector (eVect.T[iMin]) #define axis in global geometry - majorAxis = FreeCAD.Vector (eVect.T[iMaj]) - if np.sign(eMaj) == np.sign(eMin): - return 'cylinder_elliptic',(pos,axis,[minorRad,majorRad],[minorAxis,majorAxis]) - else: - if np.sign(k) == np.sign(eMaj) : - return 'cylinder_hyperbolic',(pos,axis,[minorRad,majorRad],[minorAxis,majorAxis]) - else: - return 'cylinder_hyperbolic',(pos,axis,[majorRad,minorRad],[majorAxis,minorAxis]) - - -def get_cone_parameters(eVal,eVect,T,iaxis): - - other1 = (iaxis+1)%3 - other2 = (iaxis+2)%3 - pos = FreeCAD.Vector(T) - - if abs(eVal[other1]-eVal[other2]) < 1e-5 : - axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) - tan = float(np.sqrt(-eVal[other1] / eVal[iaxis])) - return 'cone',(pos,axis,tan,True) - else: - for i in range(3): - if np.sign(eVal[(i+1)%3]) == np.sign(eVal[(i+2)%3]) : - iaxis = i - other1 = (iaxis+1)%3 - other2 = (iaxis+2)%3 - break - - axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) - minAxis = FreeCAD.Vector(np.transpose(eVect)[other1]) - majAxis = FreeCAD.Vector(np.transpose(eVect)[other2]) - Ra = abs(1/eVal[iaxis]) - Rmin = abs(1/eVal[other1]) - Rmaj = abs(1/eVal[other2]) - - if Rmin > Rmaj : - Rmin,Rmaj = Rmaj,Rmin - minAxis,majAxis = majAxis,minAxis - - return 'cone_elliptic',(pos,axis,Ra,[Rmin,Rmaj],[minAxis,majAxis],True) - - -def get_hyperboloid_parameters(eVal,eVect,T,k,iaxis): - cylTan = 1e3 - coneRad = 0.1 - - elliposoid = False - if iaxis is None: - iaxis = np.argmin(np.abs(eVal)) - ellipsoid = True - - other1 = (iaxis+1)%3 - other2 = (iaxis+2)%3 - Rad1 = float(np.sqrt(abs(k/eVal[other1]))) - Rad2 = float(np.sqrt(abs(k/eVal[other2]))) - other = other1 if Rad1 > Rad2 else other2 - - majorRad = float(np.sqrt(abs(k/eVal[iaxis]))) - minorRad = float(np.sqrt(abs(k/eVal[other]))) - oneSheet = np.sign(k) != np.sign(eVal[iaxis]) - - axis = FreeCAD.Vector (np.transpose(eVect)[iaxis]) - pos = FreeCAD.Vector (T) - minorAxis = FreeCAD.Vector (eVect.T[other]) #define axis in global geometry - majorAxis = FreeCAD.Vector (eVect.T[iaxis] ) - - t = majorRad/minorRad - - if t > cylTan and oneSheet: - return get_cylinder_parameters(eVal,eVect,T,k,iaxis) - elif minorRad < coneRad : - return get_cone_parameters(eVal,eVect,T,iaxis) - else: - if elliposoid : - print ('ellipical hyperboloid not implemented') - print ('single radius from {} eigen Value will be used'.format(minorRad) ) - return 'hyperboloid',(pos,axis,[minorRad,majorRad],[minorAxis,majorAxis],oneSheet) - -def get_ellipsoid_parameters(eVal,eVect,T,k): - - cylTan = 1e3 - iaxis = None - for i in range(3): - if abs(eVal[i]-eVal[(i+1)%3]) < 1e-3 : - iaxis = (i+2)%3 - break - - if iaxis is None : - print(eVal) - print('cannot produce three radii Ellipsoid') - return 'ellipsoid_general',None - - other1 = (iaxis+1)%3 - iMaj = iaxis - iMin = other1 - - eMaj = eVal[iaxis] - eMin = eVal[other1] - - if eMin < eMaj : - eMin,eMaj = eMaj,eMin - iMin,iMaj = iMaj,iMin - - RMaj = float(np.sqrt(abs(k/eMaj))) - RMin = float(np.sqrt(abs(k/eMin))) - majorAxis = FreeCAD.Vector (np.transpose(eVect)[iMaj]) - minorAxis = FreeCAD.Vector (np.transpose(eVect)[iMin]) - pos = FreeCAD.Vector (T) - - t = RMaj/RMin - if t > cylTan : - return get_cylinder_parameters(eVal,eVect,T,k,iMaj) - else : - return 'ellipsoid',(pos,iaxis,[RMin,RMaj],[minorAxis,majorAxis]) - - -def getGQAxis(eVal,k): +def get_parabola_parameters(eVal, eVect, T, U): + iaxis, comp = U[1] + center = FreeCAD.Vector(T) + axis = FreeCAD.Vector(eVect[iaxis][0]) + e1 = eVal[(iaxis + 1) % 3] + focal = comp / (4 * e1) + if focal < 0: + focal = -focal + axis = -axis + return (center, axis, focal) + + +def get_cylinder_parameters(eVal, eVect, T, k, iaxis): + + other1 = (iaxis + 1) % 3 + other2 = (iaxis + 2) % 3 + + eMin = eVal[other1] + eMaj = eVal[other2] + + axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) + pos = FreeCAD.Vector(T) + if abs(eMin - eMaj) < 1.0e-5: + radius = float(np.sqrt(k / eMaj)) + return "cylinder", (pos, axis, radius) + else: + iMin = other1 + iMaj = other2 + if abs(eMin) < abs(eMaj): + eMin, eMaj = eMaj, eMin + iMin, iMaj = iMaj, iMin + + majorRad = float(np.sqrt(abs(k / eMaj))) + minorRad = float(np.sqrt(abs(k / eMin))) + minorAxis = FreeCAD.Vector(eVect.T[iMin]) # define axis in global geometry + majorAxis = FreeCAD.Vector(eVect.T[iMaj]) + if np.sign(eMaj) == np.sign(eMin): + return "cylinder_elliptic", ( + pos, + axis, + [minorRad, majorRad], + [minorAxis, majorAxis], + ) + else: + if np.sign(k) == np.sign(eMaj): + return "cylinder_hyperbolic", ( + pos, + axis, + [minorRad, majorRad], + [minorAxis, majorAxis], + ) + else: + return "cylinder_hyperbolic", ( + pos, + axis, + [majorRad, minorRad], + [majorAxis, minorAxis], + ) + + +def get_cone_parameters(eVal, eVect, T, iaxis): + + other1 = (iaxis + 1) % 3 + other2 = (iaxis + 2) % 3 + pos = FreeCAD.Vector(T) + + if abs(eVal[other1] - eVal[other2]) < 1e-5: + axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) + tan = float(np.sqrt(-eVal[other1] / eVal[iaxis])) + return "cone", (pos, axis, tan, True) + else: + for i in range(3): + if np.sign(eVal[(i + 1) % 3]) == np.sign(eVal[(i + 2) % 3]): + iaxis = i + other1 = (iaxis + 1) % 3 + other2 = (iaxis + 2) % 3 + break + + axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) + minAxis = FreeCAD.Vector(np.transpose(eVect)[other1]) + majAxis = FreeCAD.Vector(np.transpose(eVect)[other2]) + Ra = abs(1 / eVal[iaxis]) + Rmin = abs(1 / eVal[other1]) + Rmaj = abs(1 / eVal[other2]) + + if Rmin > Rmaj: + Rmin, Rmaj = Rmaj, Rmin + minAxis, majAxis = majAxis, minAxis + + return "cone_elliptic", (pos, axis, Ra, [Rmin, Rmaj], [minAxis, majAxis], True) + + +def get_hyperboloid_parameters(eVal, eVect, T, k, iaxis): + cylTan = 1e3 + coneRad = 0.1 + + elliposoid = False + if iaxis is None: + iaxis = np.argmin(np.abs(eVal)) + ellipsoid = True + + other1 = (iaxis + 1) % 3 + other2 = (iaxis + 2) % 3 + Rad1 = float(np.sqrt(abs(k / eVal[other1]))) + Rad2 = float(np.sqrt(abs(k / eVal[other2]))) + other = other1 if Rad1 > Rad2 else other2 + + majorRad = float(np.sqrt(abs(k / eVal[iaxis]))) + minorRad = float(np.sqrt(abs(k / eVal[other]))) + oneSheet = np.sign(k) != np.sign(eVal[iaxis]) + + axis = FreeCAD.Vector(np.transpose(eVect)[iaxis]) + pos = FreeCAD.Vector(T) + minorAxis = FreeCAD.Vector(eVect.T[other]) # define axis in global geometry + majorAxis = FreeCAD.Vector(eVect.T[iaxis]) + + t = majorRad / minorRad + + if t > cylTan and oneSheet: + return get_cylinder_parameters(eVal, eVect, T, k, iaxis) + elif minorRad < coneRad: + return get_cone_parameters(eVal, eVect, T, iaxis) + else: + if elliposoid: + print("ellipical hyperboloid not implemented") + print("single radius from {} eigen Value will be used".format(minorRad)) + return "hyperboloid", ( + pos, + axis, + [minorRad, majorRad], + [minorAxis, majorAxis], + oneSheet, + ) + + +def get_ellipsoid_parameters(eVal, eVect, T, k): + + cylTan = 1e3 + iaxis = None + for i in range(3): + if abs(eVal[i] - eVal[(i + 1) % 3]) < 1e-3: + iaxis = (i + 2) % 3 + break + + if iaxis is None: + print(eVal) + print("cannot produce three radii Ellipsoid") + return "ellipsoid_general", None + + other1 = (iaxis + 1) % 3 + iMaj = iaxis + iMin = other1 + + eMaj = eVal[iaxis] + eMin = eVal[other1] + + if eMin < eMaj: + eMin, eMaj = eMaj, eMin + iMin, iMaj = iMaj, iMin + + RMaj = float(np.sqrt(abs(k / eMaj))) + RMin = float(np.sqrt(abs(k / eMin))) + majorAxis = FreeCAD.Vector(np.transpose(eVect)[iMaj]) + minorAxis = FreeCAD.Vector(np.transpose(eVect)[iMin]) + pos = FreeCAD.Vector(T) + + t = RMaj / RMin + if t > cylTan: + return get_cylinder_parameters(eVal, eVect, T, k, iMaj) + else: + return "ellipsoid", (pos, iaxis, [RMin, RMaj], [minorAxis, majorAxis]) + + +def getGQAxis(eVal, k): # check if there is two equal eigenValues iaxis = None for i in range(3): - if abs(eVal[i]-eVal[(i+1)%3]) < 1e-5 : - iaxis = (i+2)%3 - break + if abs(eVal[i] - eVal[(i + 1) % 3]) < 1e-5: + iaxis = (i + 2) % 3 + break if iaxis is None: - iaxis= np.argmin(np.abs(eVal)) + iaxis = np.argmin(np.abs(eVal)) e0 = eVal[iaxis] - e1 = eVal[(iaxis+1)%3] - e2 = eVal[(iaxis+2)%3] - - if k == 0: # k == 0 - if e0 == 0 : # e1*X^2 + e2*Y^2 = 0 Intersecting planes (real or imaginary) - ek = None - elif np.sign(e0) == np.sign(e1) and \ - np.sign(e1) == np.sign(e2) : # e1*X^2 + e2*Y^2 + e0*Z^2 = 0 Imaginary ellipsoid - ek = None - else: # e1*X^2 + e2*Y^2 - e0*Z^2 = 0 Elliptic Cone - ek = (-1,0) - - elif np.sign(k) == np.sign(e1) : # e1 and k same sign (e1 > 0) - if e0 == 0 : - if np.sign(e1) == np.sign(e2) : # e1*X^2 + e2*Y^2 + |k| = 0 Imaginary Elliptic cylinder - ek = None - else: # e1*X^2 - e2*Y^2 + |k| = 0 Hyperpolic cylinder - ek = (0,-1) - elif np.sign(e0) == np.sign(e1) and \ - np.sign(e1) == np.sign(e2) : # e1*X^2 + e2*Y^2 + e0*Z^2 + |k| = 0 Imaginary ellipsoid - ek = None - else: # e1*X^2 + e2*Y^2 - e0*Z^2 + |k| = 0 Hyperboloid - ek = (-1,1) - - else: # e1 and k different sign - if e0 == 0: # e1*X^2 + e2*Y^2 - |k| = 0 Elliptic cylinder - ek = (0,-1) - elif np.sign(e0) == np.sign(e1) and \ - np.sign(e1) == np.sign(e2) : # e1*X^2 + e2*Y^2 + e0*Z^2 - |k| = 0 Elliposoid - ek = (1,-1) - else: # e1*X^2 + e2*Y^2 - e0*Z^2 - |k| = 0 Hyperbpoloid - ek =(-1,1) - - return iaxis,ek - - -def sq2params(params) : - - a,b,c,d,e,f,g = params[0:7] - x,y,z = params[7:10] + e1 = eVal[(iaxis + 1) % 3] + e2 = eVal[(iaxis + 2) % 3] + + if k == 0: # k == 0 + if ( + e0 == 0 + ): # e1*X^2 + e2*Y^2 = 0 Intersecting planes (real or imaginary) + ek = None + elif np.sign(e0) == np.sign(e1) and np.sign(e1) == np.sign( + e2 + ): # e1*X^2 + e2*Y^2 + e0*Z^2 = 0 Imaginary ellipsoid + ek = None + else: # e1*X^2 + e2*Y^2 - e0*Z^2 = 0 Elliptic Cone + ek = (-1, 0) + + elif np.sign(k) == np.sign(e1): # e1 and k same sign (e1 > 0) + if e0 == 0: + if np.sign(e1) == np.sign( + e2 + ): # e1*X^2 + e2*Y^2 + |k| = 0 Imaginary Elliptic cylinder + ek = None + else: # e1*X^2 - e2*Y^2 + |k| = 0 Hyperpolic cylinder + ek = (0, -1) + elif np.sign(e0) == np.sign(e1) and np.sign(e1) == np.sign( + e2 + ): # e1*X^2 + e2*Y^2 + e0*Z^2 + |k| = 0 Imaginary ellipsoid + ek = None + else: # e1*X^2 + e2*Y^2 - e0*Z^2 + |k| = 0 Hyperboloid + ek = (-1, 1) + + else: # e1 and k different sign + if e0 == 0: # e1*X^2 + e2*Y^2 - |k| = 0 Elliptic cylinder + ek = (0, -1) + elif np.sign(e0) == np.sign(e1) and np.sign(e1) == np.sign( + e2 + ): # e1*X^2 + e2*Y^2 + e0*Z^2 - |k| = 0 Elliposoid + ek = (1, -1) + else: # e1*X^2 + e2*Y^2 - e0*Z^2 - |k| = 0 Hyperbpoloid + ek = (-1, 1) + + return iaxis, ek + + +def sq2params(params): + + a, b, c, d, e, f, g = params[0:7] + x, y, z = params[7:10] gqa, gqb, gqc = a, b, c gqd, gqe, gqf = 0, 0, 0 - gqg = 2*(d-a*x) - gqh = 2*(e-b*y) - gqj = 2*(f-c*z) - gqk = g + a*x*x + b*y*y + c*z*z \ - - 2*d*x - 2*e*y - 2*f*z - - return gq2params( (gqa,gqb,gqc,gqd,gqe,gqf,gqg,gqh,gqj,gqk) ) - - - -def gq2params(x) : -# intial matrix: A -# a f g u -# f b h v -# g h c w -# u v w d - -# matrix displacement : D -# 1 0 0 alpha -# 0 1 0 beta -# 0 0 1 gamma -# 0 0 0 1 - -# Transpose(D) * A * D = mat3 -# matrix mat3 -# a f g 0 -# f b h 0 -# g h c 0 -# 0 0 0 (d + u*alpha + v*beta + w*gamma) - -# with vector(alpha,beta,gamma) solution of -# a f h alpha -u -# f b g * beta = -v -# h g c gamma -w - - - zeroLim = 1e-12 - mat3 = np.array( [[x[0],x[3]/2,x[5]/2], \ - [x[3]/2,x[1],x[4]/2], \ - [x[5]/2,x[4]/2,x[2]]] ) - X = np.array((x[6]/2,x[7]/2,x[8]/2)) - - #mat4 = np.array( [[x[0],x[3]/2,x[5]/2,x[6]/2], \ - # [x[3]/2,x[1],x[4]/2,x[7]/2], \ - # [x[5]/2,x[4]/2,x[2],x[8]/2], \ - # [x[6]/2,x[7]/2,x[8]/2,x[9]]] ) - - #eigenValues and Vector - eVal,vect = LA.eigh(mat3) - XD = np.matmul(X,vect) # X in diagonalised base - - Dinv = np.where(abs(eVal) < 1e-8 , eVal , 1/eVal ) # get inverse eigen value where eigen< 1e-8 - zero = (abs(eVal)<1e-8).nonzero() # index in eigen value vector where eigen < 1e-8 - TD = -XD*Dinv # Translation vector in diagonalized base - - k = np.matmul(TD,XD) + x[9] - - if len(zero) != 0 : - iz = zero[0] - comp = 2*XD[iz] - if abs(comp) > 1e-6 : # zero eigenvalue but corresponding component in XD vector is non zero => paraboloid Curve => the k/comp value is the translation in this component direction - TD[iz] = -k/comp - U = (k,(iz,comp)) - else: - U = (k,None) - else: - U = (k,None) - - T = np.matmul(TD,vect.T) - - return conicSurface(eVal,vect,T,U) - - -def conicSurface(eVal,vect,T,U) : - - #paraboloid - if U[1] is not None : - params = get_parabola_parameters(eVal,vect,T,U) - stype = 'paraboloid' - return stype,params - - # other conics - k = U[0] - iaxis,ek= getGQAxis(eVal,k) - if ek == (0,-1) : - # Cylinder - stype,params = get_cylinder_parameters(eVal,vect,T,-k,iaxis) - elif ek == (-1,0) : - # cone - stype,params = get_cone_parameters(eVal,vect,T,iaxis) - elif ek == (-1,1) : - # hyperboloid - # function can return cylinder or cone if hyperboiloid can be aproximated by such surfaces (within some criterion) - stype,params = get_hyperboloid_parameters(eVal,vect,T,-k,iaxis) - elif ek == (1,-1) : - # ellipsoid - # function can return cylinder or cone if hyperboiloid can be aproximated by such surfaces (within some criterion) - stype,params = get_ellipsoid_parameters(eVal,vect,T,-k) - else: - stype = 'unknown' - params = None - print('No 2nd order or real surfaces') - return stype,params - + gqg = 2 * (d - a * x) + gqh = 2 * (e - b * y) + gqj = 2 * (f - c * z) + gqk = g + a * x * x + b * y * y + c * z * z - 2 * d * x - 2 * e * y - 2 * f * z + + return gq2params((gqa, gqb, gqc, gqd, gqe, gqf, gqg, gqh, gqj, gqk)) + + +def gq2params(x): + # intial matrix: A + # a f g u + # f b h v + # g h c w + # u v w d + + # matrix displacement : D + # 1 0 0 alpha + # 0 1 0 beta + # 0 0 1 gamma + # 0 0 0 1 + + # Transpose(D) * A * D = mat3 + # matrix mat3 + # a f g 0 + # f b h 0 + # g h c 0 + # 0 0 0 (d + u*alpha + v*beta + w*gamma) + + # with vector(alpha,beta,gamma) solution of + # a f h alpha -u + # f b g * beta = -v + # h g c gamma -w + + zeroLim = 1e-12 + mat3 = np.array( + [ + [x[0], x[3] / 2, x[5] / 2], + [x[3] / 2, x[1], x[4] / 2], + [x[5] / 2, x[4] / 2, x[2]], + ] + ) + X = np.array((x[6] / 2, x[7] / 2, x[8] / 2)) + + # mat4 = np.array( [[x[0],x[3]/2,x[5]/2,x[6]/2], \ + # [x[3]/2,x[1],x[4]/2,x[7]/2], \ + # [x[5]/2,x[4]/2,x[2],x[8]/2], \ + # [x[6]/2,x[7]/2,x[8]/2,x[9]]] ) + + # eigenValues and Vector + eVal, vect = LA.eigh(mat3) + XD = np.matmul(X, vect) # X in diagonalised base + + Dinv = np.where( + abs(eVal) < 1e-8, eVal, 1 / eVal + ) # get inverse eigen value where eigen< 1e-8 + zero = ( + abs(eVal) < 1e-8 + ).nonzero() # index in eigen value vector where eigen < 1e-8 + TD = -XD * Dinv # Translation vector in diagonalized base + + k = np.matmul(TD, XD) + x[9] + + if len(zero) != 0: + iz = zero[0] + comp = 2 * XD[iz] + if ( + abs(comp) > 1e-6 + ): # zero eigenvalue but corresponding component in XD vector is non zero => paraboloid Curve => the k/comp value is the translation in this component direction + TD[iz] = -k / comp + U = (k, (iz, comp)) + else: + U = (k, None) + else: + U = (k, None) + + T = np.matmul(TD, vect.T) + + return conicSurface(eVal, vect, T, U) + + +def conicSurface(eVal, vect, T, U): + + # paraboloid + if U[1] is not None: + params = get_parabola_parameters(eVal, vect, T, U) + stype = "paraboloid" + return stype, params + + # other conics + k = U[0] + iaxis, ek = getGQAxis(eVal, k) + if ek == (0, -1): + # Cylinder + stype, params = get_cylinder_parameters(eVal, vect, T, -k, iaxis) + elif ek == (-1, 0): + # cone + stype, params = get_cone_parameters(eVal, vect, T, iaxis) + elif ek == (-1, 1): + # hyperboloid + # function can return cylinder or cone if hyperboiloid can be aproximated by such surfaces (within some criterion) + stype, params = get_hyperboloid_parameters(eVal, vect, T, -k, iaxis) + elif ek == (1, -1): + # ellipsoid + # function can return cylinder or cone if hyperboiloid can be aproximated by such surfaces (within some criterion) + stype, params = get_ellipsoid_parameters(eVal, vect, T, -k) + else: + stype = "unknown" + params = None + print("No 2nd order or real surfaces") + return stype, params diff --git a/src/geouned/GEOReverse/Modules/Objects.py b/src/geouned/GEOReverse/Modules/Objects.py index 3bf72afb..f7b843ab 100644 --- a/src/geouned/GEOReverse/Modules/Objects.py +++ b/src/geouned/GEOReverse/Modules/Objects.py @@ -10,619 +10,642 @@ class CADCell: - def __init__(self,stringCell=None): + def __init__(self, stringCell=None): - if not stringCell : + if not stringCell: self.surfaces = {} self.surfaceList = [] - self.shape = None - #self.likeCell = None + self.shape = None + # self.likeCell = None self.definition = None - self.name = 0 - #self.TRCL = None # cell transformacion "like-but" cells - self.TRFL = None # Universe transformation in fill Universe - self.U = -1 # Cell Universe number - self.FILL = 0 # Fill Universe number - self.MAT = 0 # material number + self.name = 0 + # self.TRCL = None # cell transformacion "like-but" cells + self.TRFL = None # Universe transformation in fill Universe + self.U = -1 # Cell Universe number + self.FILL = 0 # Fill Universe number + self.MAT = 0 # material number self.CurrentTR = None - self.level = None + self.level = None self.__defTerms__ = None self.__operator__ = None else: self.surfaces = None - self.shape = None - self.name = stringCell.name - self.TRFL = stringCell.TR # Universe transformation in fill Universe - self.U = stringCell.U # Cell Universe number - self.FILL = stringCell.FILL # Fill Universe number - self.MAT = stringCell.MAT # material number + self.shape = None + self.name = stringCell.name + self.TRFL = stringCell.TR # Universe transformation in fill Universe + self.U = stringCell.U # Cell Universe number + self.FILL = stringCell.FILL # Fill Universe number + self.MAT = stringCell.MAT # material number self.CurrentTR = self.TRFL - self.level = None - + self.level = None + self.__defTerms__ = None - self.__operator__ = None + self.__operator__ = None self.__setDefinition__(stringCell) - + def copy(self): - cpCell = CADCell() + cpCell = CADCell() cpCell.surfaceList = self.surfaceList[:] cpCell.surfaces = {} - for name,s in self.surfaces.items(): + for name, s in self.surfaces.items(): cpCell.surfaces[name] = s.copy() - - if type(self.definition) is cline : - cpCell.definition = cline(self.definition.str) + + if type(self.definition) is cline: + cpCell.definition = cline(self.definition.str) elif type(self.definition) is BoolSequence: - cpCell.definition = self.definition.copy() - - cpCell.name = self.name - cpCell.TRFL = self.TRFL - cpCell.U = self.U - cpCell.FILL = self.FILL - cpCell.MAT = self.MAT - cpCell.level = self.level + cpCell.definition = self.definition.copy() - if self.CurrentTR is not None : - cpCell.CurrentTR = self.CurrentTR.submatrix(4) + cpCell.name = self.name + cpCell.TRFL = self.TRFL + cpCell.U = self.U + cpCell.FILL = self.FILL + cpCell.MAT = self.MAT + cpCell.level = self.level - if self.shape is not None : - cpCell.shape = self.shape.copy() + if self.CurrentTR is not None: + cpCell.CurrentTR = self.CurrentTR.submatrix(4) - return cpCell + if self.shape is not None: + cpCell.shape = self.shape.copy() + return cpCell - def getSubCell(self,seq): + def getSubCell(self, seq): subCell = self.copy() subCell.definition = seq.copy() subCell.shape = None - subCell.surfaceList = subCell.definition.getSurfacesNumbers() - for s in tuple(subCell.surfaces.keys()) : - if s not in subCell.surfaceList: del(subCell.surfaces[s]) - - return subCell - -# not used -# -# def split(self,nparts=2): -# -# if nparts == 1: -# return (self,None) -# terms,operador = self.getOuterTerms() -# nelemts = int(len(terms)/nparts) -# subDefList = [] -# -# if operador == 'AND': -# for i in range(nparts-1): -# newdef = ') ('.join(terms[i*nelemts:(i+1)*nelemts]) -# newdef = '({})'.format(newdef) -# subDefList.append(newdef) -# newdef = ') ('.join(terms[(nparts-1)*nelemts:]) -# newdef = '({})'.format(newdef) -# subDefList.append(newdef) -# -# else: -# for i in range(nparts-1): -# newdef = '):('.join(terms[i*nelemts:(i+1)*nelemts]) -# newdef = '({})'.format(newdef) -# subDefList.append(newdef) -# newdef = '):('.join(terms[(nparts-1)*nelemts:]) -# newdef = '({})'.format(newdef) -# subDefList.append(newdef) -# -# -# subCellList=[] -# for df in subDefList: -# subCell = self.copy() -# subCell.definition= cline(df) -# subCell.shape = None -# subCell.surfaceList = subCell.definition.getSurfacesNumbers() -# for s in tuple(subCell.surfaces.keys()) : -# if s not in subCell.surfaceList: del(subCell.surfaces[s]) -# -# subCellList.append(subCell) -# -# return subCellList,operador + subCell.surfaceList = subCell.definition.getSurfacesNumbers() + for s in tuple(subCell.surfaces.keys()): + if s not in subCell.surfaceList: + del subCell.surfaces[s] + + return subCell + + # not used + # + # def split(self,nparts=2): + # + # if nparts == 1: + # return (self,None) + # terms,operador = self.getOuterTerms() + # nelemts = int(len(terms)/nparts) + # subDefList = [] + # + # if operador == 'AND': + # for i in range(nparts-1): + # newdef = ') ('.join(terms[i*nelemts:(i+1)*nelemts]) + # newdef = '({})'.format(newdef) + # subDefList.append(newdef) + # newdef = ') ('.join(terms[(nparts-1)*nelemts:]) + # newdef = '({})'.format(newdef) + # subDefList.append(newdef) + # + # else: + # for i in range(nparts-1): + # newdef = '):('.join(terms[i*nelemts:(i+1)*nelemts]) + # newdef = '({})'.format(newdef) + # subDefList.append(newdef) + # newdef = '):('.join(terms[(nparts-1)*nelemts:]) + # newdef = '({})'.format(newdef) + # subDefList.append(newdef) + # + # + # subCellList=[] + # for df in subDefList: + # subCell = self.copy() + # subCell.definition= cline(df) + # subCell.shape = None + # subCell.surfaceList = subCell.definition.getSurfacesNumbers() + # for s in tuple(subCell.surfaces.keys()) : + # if s not in subCell.surfaceList: del(subCell.surfaces[s]) + # + # subCellList.append(subCell) + # + # return subCellList,operador def getOuterTerms(self): - if not self.__defTerms__ : - self.__defTerms__,self.__operator__ = outterTerms(self.definition.str) + if not self.__defTerms__: + self.__defTerms__, self.__operator__ = outterTerms(self.definition.str) return self.__defTerms__, self.__operator__ - - def makeBox(self,boundBox): - box_origin = FreeCAD.Vector(boundBox.XMin,boundBox.YMin,boundBox.ZMin) - return Part.makeBox(boundBox.XLength,boundBox.YLength,boundBox.ZLength,box_origin ) - - def buildShape(self,boundBox,force=False,surfTR=None,simplify=False,fuse=False): - - if self.shape is not None and not force: return - if surfTR : self.transformSurfaces(surfTR) - - cutShape = BuildSolid(self,boundBox,simplify=simplify) - + + def makeBox(self, boundBox): + box_origin = FreeCAD.Vector(boundBox.XMin, boundBox.YMin, boundBox.ZMin) + return Part.makeBox( + boundBox.XLength, boundBox.YLength, boundBox.ZLength, box_origin + ) + + def buildShape( + self, boundBox, force=False, surfTR=None, simplify=False, fuse=False + ): + + if self.shape is not None and not force: + return + if surfTR: + self.transformSurfaces(surfTR) + + cutShape = BuildSolid(self, boundBox, simplify=simplify) + if fuse or True: - self.shape = FuseSolid(cutShape) + self.shape = FuseSolid(cutShape) else: - self.shape = Part.makeCompound(cutShape) + self.shape = Part.makeCompound(cutShape) - def buildSurfaceShape(self,boundBox): + def buildSurfaceShape(self, boundBox): for s in self.surfaces.values(): - s.buildShape(boundBox) - - def transformSolid(self,matrix,reverse=False): - if not self.shape : return - if reverse : - self.shape = self.shape.transformGeometry(matrix.inverse()) - else: - self.shape = self.shape.transformGeometry(matrix) - - def transformSurfaces(self,matrix): + s.buildShape(boundBox) + + def transformSolid(self, matrix, reverse=False): + if not self.shape: + return + if reverse: + self.shape = self.shape.transformGeometry(matrix.inverse()) + else: + self.shape = self.shape.transformGeometry(matrix) + + def transformSurfaces(self, matrix): for s in self.surfaces.values(): s.transform(matrix) - - def setSurfaces(self,Surfaces): - if self.surfaces is not None : return + + def setSurfaces(self, Surfaces): + if self.surfaces is not None: + return self.surfaces = {} - for s in self.surfaceList : + for s in self.surfaceList: self.surfaces[s] = Surfaces[s] def cleanUndefined(self): - undefined = [] - for s in self.definition.getSurfacesNumbers() : - if self.surfaces[s].params is None: - undefined.append(s) - if undefined: - self.definition.removeSurface(undefined) - - for s in undefined: - del (self.surfaces[s]) - - def __setDefinition__(self,stringCell) : - - self.definition = stringCell.geom - self.definition.remove_comments(full=True) - self.definition.remove_cr() - self.definition.remove_multispace() - self.definition.remove_redundant() - self.surfaceList = self.definition.getSurfacesNumbers() - + undefined = [] + for s in self.definition.getSurfacesNumbers(): + if self.surfaces[s].params is None: + undefined.append(s) + if undefined: + self.definition.removeSurface(undefined) + + for s in undefined: + del self.surfaces[s] + + def __setDefinition__(self, stringCell): + + self.definition = stringCell.geom + self.definition.remove_comments(full=True) + self.definition.remove_cr() + self.definition.remove_multispace() + self.definition.remove_redundant() + self.surfaceList = self.definition.getSurfacesNumbers() + class Plane: - def __init__(self,Id,params,tr=None): - self.type = 'plane' + def __init__(self, Id, params, tr=None): + self.type = "plane" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def __str__(self): - return 'plane : {}\nParameters : {}'.format(self.id,self.params) + return "plane : {}\nParameters : {}".format(self.id, self.params) def copy(self): - return Plane(self.id,self.params) - - def transform(self,matrix): - v,d = self.params - p = d*v # vector p is d*plane normal + return Plane(self.id, self.params) + + def transform(self, matrix): + v, d = self.params + p = d * v # vector p is d*plane normal v = matrix.submatrix(3).multVec(v) v.normalize() - d = matrix.multVec(p)*v - self.params = (v,d) + d = matrix.multVec(p) * v + self.params = (v, d) - def buildShape(self,boundBox): + def buildShape(self, boundBox): normal, p0 = self.params Box = FreeCAD.BoundBox(boundBox) Box.enlarge(10) - pointEdge=[] + pointEdge = [] for i in range(12): - edge = Box.getEdge(i) - p1 = normal.dot(edge[0]) - p2 = normal.dot(edge[1]) - d0 = p0 - p1 - d1 = p2 - p1 - if d1 != 0 : - a = d0/d1 - if (a >= 0 and a <= 1): - pointEdge.append(edge[0]+a*(edge[1]-edge[0])) - - if len(pointEdge) == 0 : return - s = FreeCAD.Vector((0,0,0)) - for v in pointEdge : - s = s + v - s = s / len(pointEdge) - + edge = Box.getEdge(i) + p1 = normal.dot(edge[0]) + p2 = normal.dot(edge[1]) + d0 = p0 - p1 + d1 = p2 - p1 + if d1 != 0: + a = d0 / d1 + if a >= 0 and a <= 1: + pointEdge.append(edge[0] + a * (edge[1] - edge[0])) + + if len(pointEdge) == 0: + return + s = FreeCAD.Vector((0, 0, 0)) + for v in pointEdge: + s = s + v + s = s / len(pointEdge) + vtxvec = [] - for v in pointEdge : - vtxvec.append(v-s) + for v in pointEdge: + vtxvec.append(v - s) X0 = vtxvec[0] Y0 = normal.cross(X0) - orden=[] - for i,v in enumerate(vtxvec): - phi = np.arctan2(v.dot(Y0),v.dot(X0)) - orden.append((phi,i)) + orden = [] + for i, v in enumerate(vtxvec): + phi = np.arctan2(v.dot(Y0), v.dot(X0)) + orden.append((phi, i)) orden.sort() - - self.shape = Part.Face( Part.makePolygon([ pointEdge[p[1]] for p in orden ], True)) - + + self.shape = Part.Face(Part.makePolygon([pointEdge[p[1]] for p in orden], True)) + class Sphere: - def __init__(self,Id,params,tr=None): - self.type = 'sphere' + def __init__(self, Id, params, tr=None): + self.type = "sphere" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Sphere(self.id,self.params) - - def transform(self,matrix): - p,R = self.params + return Sphere(self.id, self.params) + + def transform(self, matrix): + p, R = self.params p = matrix.multVec(p) - self.params = (p,R) + self.params = (p, R) - def buildShape(self,boundBox): - origin,R = self.params - self.shape = Part.makeSphere(R,origin) + def buildShape(self, boundBox): + origin, R = self.params + self.shape = Part.makeSphere(R, origin) class Cylinder: - def __init__(self,Id,params,tr=None,truncated=False): - self.type = 'cylinder' + def __init__(self, Id, params, tr=None, truncated=False): + self.type = "cylinder" self.id = Id self.shape = None self.params = params self.truncated = truncated - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Cylinder(self.id,self.params,truncated=self.truncated) + return Cylinder(self.id, self.params, truncated=self.truncated) - def transform(self,matrix): - p,v,R = self.params + def transform(self, matrix): + p, v, R = self.params v = matrix.submatrix(3).multVec(v) p = matrix.multVec(p) - self.params = (p,v,R) - - def buildShape(self,boundBox): + self.params = (p, v, R) + + def buildShape(self, boundBox): p, vec, r = self.params - - if not self.truncated : - dmin = vec.dot(boundBox.getPoint(0)-p) - dmax = dmin - for i in range(1,8) : - d = vec.dot(boundBox.getPoint(i)-p) - dmin = min(d,dmin) - dmax = max(d,dmax) - - height = dmax-dmin - dmin -= 0.1*height - dmax += 0.1*height - height = dmax-dmin - - point = p + dmin * vec - self.shape = Part.makeCylinder( r,height,point,vec,360) - #self.shape = makeCylinder2( r,height,point,vec) + + if not self.truncated: + dmin = vec.dot(boundBox.getPoint(0) - p) + dmax = dmin + for i in range(1, 8): + d = vec.dot(boundBox.getPoint(i) - p) + dmin = min(d, dmin) + dmax = max(d, dmax) + + height = dmax - dmin + dmin -= 0.1 * height + dmax += 0.1 * height + height = dmax - dmin + + point = p + dmin * vec + self.shape = Part.makeCylinder(r, height, point, vec, 360) + # self.shape = makeCylinder2( r,height,point,vec) else: - self.shape = Part.makeCylinder( r,vec.Length,p,vec,360) - #self.shape = Part.makeCylinder2( r,vec.Length,p,vec) + self.shape = Part.makeCylinder(r, vec.Length, p, vec, 360) + # self.shape = Part.makeCylinder2( r,vec.Length,p,vec) return + class Cone: - def __init__(self,Id,params,tr=None,truncated=False): - self.type = 'cone' + def __init__(self, Id, params, tr=None, truncated=False): + self.type = "cone" self.id = Id self.shape = None self.params = params self.truncated = truncated - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Cone(self.id,self.params,truncated=self.truncated) - - def transform(self,matrix): - if not self.truncated : - p,v,t,dbl = self.params - v = matrix.submatrix(3).multVec(v) - p = matrix.multVec(p) - self.params = (p,v,t,dbl) + return Cone(self.id, self.params, truncated=self.truncated) + + def transform(self, matrix): + if not self.truncated: + p, v, t, dbl = self.params + v = matrix.submatrix(3).multVec(v) + p = matrix.multVec(p) + self.params = (p, v, t, dbl) else: - p,v,r1,r2 = self.params - v = matrix.submatrix(3).multVec(v) - p = matrix.multVec(p) - self.params = (p,v,r1,r2) - - def buildShape(self,boundBox): - if not self.truncated : - apex, axis, t, dblsht = self.params - - dmin = axis.dot(boundBox.getPoint(0)-apex) - dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-apex) - dmin = min(d,dmin) - dmax = max(d,dmax) - - length = max(abs(dmin),abs(dmax)) - R = length * t - OneSheetCone = Part.makeCone( 0,R,length,apex,axis,360) - if not dblsht : - self.shape = OneSheetCone - else: - OtherSheet = Part.makeCone( 0,R,length,apex,-axis,360) - DoubleSheetCone = OneSheetCone.fuse([OtherSheet]) - DoubleSheetCone.removeSplitter() - self.shape = DoubleSheetCone + p, v, r1, r2 = self.params + v = matrix.submatrix(3).multVec(v) + p = matrix.multVec(p) + self.params = (p, v, r1, r2) + + def buildShape(self, boundBox): + if not self.truncated: + apex, axis, t, dblsht = self.params + + dmin = axis.dot(boundBox.getPoint(0) - apex) + dmax = dmin + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - apex) + dmin = min(d, dmin) + dmax = max(d, dmax) + + length = max(abs(dmin), abs(dmax)) + R = length * t + OneSheetCone = Part.makeCone(0, R, length, apex, axis, 360) + if not dblsht: + self.shape = OneSheetCone + else: + OtherSheet = Part.makeCone(0, R, length, apex, -axis, 360) + DoubleSheetCone = OneSheetCone.fuse([OtherSheet]) + DoubleSheetCone.removeSplitter() + self.shape = DoubleSheetCone else: - center, axis, r1, r2= self.params - self.shape = Part.makeCone( r1,r2,axis.Length,center,axis,360) + center, axis, r1, r2 = self.params + self.shape = Part.makeCone(r1, r2, axis.Length, center, axis, 360) + class EllipticCone: - def __init__(self,Id,params,tr=None): - self.type = 'cone_elliptic' + def __init__(self, Id, params, tr=None): + self.type = "cone_elliptic" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return EllipticCone(self.id,self.params) + return EllipticCone(self.id, self.params) - def transform(self,matrix): - p,v,ra,radii,raxes,dbl = self.params + def transform(self, matrix): + p, v, ra, radii, raxes, dbl = self.params v = matrix.submatrix(3).multVec(v) raxes[0] = matrix.submatrix(3).multVec(raxes[0]) raxes[1] = matrix.submatrix(3).multVec(raxes[1]) p = matrix.multVec(p) - self.params = (p,v,ra,radii,raxes,dbl) - - def buildShape(self,boundBox): - apex, axis, ra,radii,raxes, dblsht = self.params - - dmin = axis.dot(boundBox.getPoint(0)-apex) + self.params = (p, v, ra, radii, raxes, dbl) + + def buildShape(self, boundBox): + apex, axis, ra, radii, raxes, dblsht = self.params + + dmin = axis.dot(boundBox.getPoint(0) - apex) dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-apex) - dmin = min(d,dmin) - dmax = max(d,dmax) - - length = max(abs(dmin),abs(dmax)) - OneSheetCone = makeEllipticCone( apex,axis,ra,radii,raxes,length) - if not dblsht : - self.shape = OneSheetCone + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - apex) + dmin = min(d, dmin) + dmax = max(d, dmax) + + length = max(abs(dmin), abs(dmax)) + OneSheetCone = makeEllipticCone(apex, axis, ra, radii, raxes, length) + if not dblsht: + self.shape = OneSheetCone else: - OtherSheet = makeEllipticCone( apex,-axis,ra,radii,raxes,length) - DoubleSheetCone = OneSheetCone.fuse([OtherSheet]) - DoubleSheetCone.removeSplitter() - self.shape = DoubleSheetCone + OtherSheet = makeEllipticCone(apex, -axis, ra, radii, raxes, length) + DoubleSheetCone = OneSheetCone.fuse([OtherSheet]) + DoubleSheetCone.removeSplitter() + self.shape = DoubleSheetCone + class Hyperboloid: - def __init__(self,Id,params,tr=None): - self.type = 'hyperboloid' + def __init__(self, Id, params, tr=None): + self.type = "hyperboloid" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Hyperboloid(self.id,self.params) - - def transform(self,matrix): - p,v,radii,raxes,onesht = self.params - v = matrix.submatrix(3).multVec(v) - raxes[0] = matrix.submatrix(3).multVec(raxes[0]) - raxes[1] = matrix.submatrix(3).multVec(raxes[1]) - p = matrix.multVec(p) - self.params = (p,v,radii,raxes,onesht) - - def buildShape(self,boundBox): + return Hyperboloid(self.id, self.params) + + def transform(self, matrix): + p, v, radii, raxes, onesht = self.params + v = matrix.submatrix(3).multVec(v) + raxes[0] = matrix.submatrix(3).multVec(raxes[0]) + raxes[1] = matrix.submatrix(3).multVec(raxes[1]) + p = matrix.multVec(p) + self.params = (p, v, radii, raxes, onesht) + + def buildShape(self, boundBox): center, axis, radii, rAxes, onesht = self.params - - dmin = axis.dot(boundBox.getPoint(0)-center) + + dmin = axis.dot(boundBox.getPoint(0) - center) dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-center) - dmin = min(d,dmin) - dmax = max(d,dmax) + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - center) + dmin = min(d, dmin) + dmax = max(d, dmax) + + length = max(abs(dmin), abs(dmax)) + self.shape = makeHyperboloid(center, radii, rAxes, axis, onesht, length) - length = max(abs(dmin),abs(dmax)) - self.shape = makeHyperboloid(center,radii,rAxes,axis,onesht,length) class Ellipsoid: - def __init__(self,Id,params,tr=None): - self.type = 'ellipsoid' + def __init__(self, Id, params, tr=None): + self.type = "ellipsoid" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Ellipsoid(self.id,self.params) - - def transform(self,matrix): - p,v,radii,raxes = self.params - v = matrix.submatrix(3).multVec(v) - raxes[0] = matrix.submatrix(3).multVec(raxes[0]) - raxes[1] = matrix.submatrix(3).multVec(raxes[1]) - p = matrix.multVec(p) - self.params = (p,v,radii,raxes) - - def buildShape(self,boundBox): + return Ellipsoid(self.id, self.params) + + def transform(self, matrix): + p, v, radii, raxes = self.params + v = matrix.submatrix(3).multVec(v) + raxes[0] = matrix.submatrix(3).multVec(raxes[0]) + raxes[1] = matrix.submatrix(3).multVec(raxes[1]) + p = matrix.multVec(p) + self.params = (p, v, radii, raxes) + + def buildShape(self, boundBox): center, axis, radii, rAxes = self.params - self.shape = makeEllipsoid(center,radii,rAxes,axis) + self.shape = makeEllipsoid(center, radii, rAxes, axis) + class EllipticCylinder: - def __init__(self,Id,params,tr=None,truncated=False): - self.type = 'cylinder_elliptic' + def __init__(self, Id, params, tr=None, truncated=False): + self.type = "cylinder_elliptic" self.id = Id self.shape = None self.params = params self.truncated = truncated - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return EllipticCylinder(self.id,self.params,truncated=self.truncated) - - def transform(self,matrix): - p,v,radii,raxes = self.params - v = matrix.submatrix(3).multVec(v) - raxes[0] = matrix.submatrix(3).multVec(raxes[0]) - raxes[1] = matrix.submatrix(3).multVec(raxes[1]) - p = matrix.multVec(p) - self.params = (p,v,radii,raxes) - - def buildShape(self,boundBox): + return EllipticCylinder(self.id, self.params, truncated=self.truncated) + + def transform(self, matrix): + p, v, radii, raxes = self.params + v = matrix.submatrix(3).multVec(v) + raxes[0] = matrix.submatrix(3).multVec(raxes[0]) + raxes[1] = matrix.submatrix(3).multVec(raxes[1]) + p = matrix.multVec(p) + self.params = (p, v, radii, raxes) + + def buildShape(self, boundBox): center, axis, radii, rAxes = self.params - if not self.truncated : - dmin = axis.dot(boundBox.getPoint(0)-center) - dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-center) - dmin = min(d,dmin) - dmax = max(d,dmax) - - height = dmax-dmin - dmin -= 0.1*height - dmax += 0.1*height - height = dmax-dmin - point = center + dmin * axis - - self.shape = makeEllipticCylinder(point,radii,rAxes,axis,height) + if not self.truncated: + dmin = axis.dot(boundBox.getPoint(0) - center) + dmax = dmin + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - center) + dmin = min(d, dmin) + dmax = max(d, dmax) + + height = dmax - dmin + dmin -= 0.1 * height + dmax += 0.1 * height + height = dmax - dmin + point = center + dmin * axis + + self.shape = makeEllipticCylinder(point, radii, rAxes, axis, height) else: - height = axis.Length - self.shape = makeEllipticCylinder(center,radii,rAxes,axis/height,height) + height = axis.Length + self.shape = makeEllipticCylinder( + center, radii, rAxes, axis / height, height + ) + class HyperbolicCylinder: - def __init__(self,Id,params,tr=None): - self.type = 'cylinder_hyperbolic' + def __init__(self, Id, params, tr=None): + self.type = "cylinder_hyperbolic" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return HyperbolicCylinder(self.id,self.params) - - def transform(self,matrix): - p,v,radii,raxes = self.params - v = matrix.submatrix(3).multVec(v) - raxes[0] = matrix.submatrix(3).multVec(raxes[0]) - raxes[1] = matrix.submatrix(3).multVec(raxes[1]) - p = matrix.multVec(p) - self.params = (p,v,radii,raxes) - - def buildShape(self,boundBox): + return HyperbolicCylinder(self.id, self.params) + + def transform(self, matrix): + p, v, radii, raxes = self.params + v = matrix.submatrix(3).multVec(v) + raxes[0] = matrix.submatrix(3).multVec(raxes[0]) + raxes[1] = matrix.submatrix(3).multVec(raxes[1]) + p = matrix.multVec(p) + self.params = (p, v, radii, raxes) + + def buildShape(self, boundBox): center, axis, radii, rAxes = self.params - dmin = axis.dot(boundBox.getPoint(0)-center) + dmin = axis.dot(boundBox.getPoint(0) - center) dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-center) - dmin = min(d,dmin) - dmax = max(d,dmax) - - height = dmax-dmin - dmin -= 0.1*height - dmax += 0.1*height - height = dmax-dmin + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - center) + dmin = min(d, dmin) + dmax = max(d, dmax) + + height = dmax - dmin + dmin -= 0.1 * height + dmax += 0.1 * height + height = dmax - dmin point = center + dmin * axis - self.shape = makeHyperbolicCylinder(point,radii,rAxes,axis,height) - + self.shape = makeHyperbolicCylinder(point, radii, rAxes, axis, height) + + class Paraboloid: - def __init__(self,Id,params,tr=None): - self.type = 'paraboloid' + def __init__(self, Id, params, tr=None): + self.type = "paraboloid" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Paraboloid(self.id,self.params) - - def transform(self,matrix): - p,v,focal = self.params - v = matrix.submatrix(3).multVec(v) - p = matrix.multVec(p) - self.params = (p,v,focal) - - def buildShape(self,boundBox): - center, axis, focal = self.params - - dmin = axis.dot(boundBox.getPoint(0)-center) + return Paraboloid(self.id, self.params) + + def transform(self, matrix): + p, v, focal = self.params + v = matrix.submatrix(3).multVec(v) + p = matrix.multVec(p) + self.params = (p, v, focal) + + def buildShape(self, boundBox): + center, axis, focal = self.params + + dmin = axis.dot(boundBox.getPoint(0) - center) dmax = dmin - for i in range(1,8) : - d = axis.dot(boundBox.getPoint(i)-center) - dmin = min(d,dmin) - dmax = max(d,dmax) + for i in range(1, 8): + d = axis.dot(boundBox.getPoint(i) - center) + dmin = min(d, dmin) + dmax = max(d, dmax) + + length = max(abs(dmin), abs(dmax)) + self.shape = makeParaboloid(center, axis, focal, length) - length = max(abs(dmin),abs(dmax)) - self.shape = makeParaboloid(center,axis,focal,length) class Torus: - def __init__(self,Id,params,tr=None): - self.type = 'torus' + def __init__(self, Id, params, tr=None): + self.type = "torus" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) - + if tr: + self.transform(tr) + def copy(self): - return Torus(self.id,self.params) + return Torus(self.id, self.params) - def transform(self,matrix): - p,v,Ra,Rb,Rc = self.params + def transform(self, matrix): + p, v, Ra, Rb, Rc = self.params v = matrix.submatrix(3).multVec(v) p = matrix.multVec(p) - self.params = (p,v,Ra,Rb,Rc) - - def buildShape(self,boundBox): - center, axis, Ra, Rb, Rc = self.params #Ra distance from torus axis; R radius of toroidal-cylinder - if (abs(Rb-Rc)< 1e-5) and Ra > 0: - self.shape = Part.makeTorus(Ra,Rb,center,axis) # FreeCAD circular Torus + self.params = (p, v, Ra, Rb, Rc) + + def buildShape(self, boundBox): + center, axis, Ra, Rb, Rc = ( + self.params + ) # Ra distance from torus axis; R radius of toroidal-cylinder + if (abs(Rb - Rc) < 1e-5) and Ra > 0: + self.shape = Part.makeTorus(Ra, Rb, center, axis) # FreeCAD circular Torus else: - self.shape = makeEllipticTorus(Ra,Rb,Rc,center,axis) # Home made elliptic Torus - + self.shape = makeEllipticTorus( + Ra, Rb, Rc, center, axis + ) # Home made elliptic Torus + class Box: - def __init__(self,Id,params,tr=None): - self.type = 'box' + def __init__(self, Id, params, tr=None): + self.type = "box" self.id = Id self.shape = None self.params = params - if tr : - self.transform(tr) + if tr: + self.transform(tr) def copy(self): - return Box(self.id,self.params) - - def transform(self,matrix): - p,v1,v2,v3 = self.params + return Box(self.id, self.params) + + def transform(self, matrix): + p, v1, v2, v3 = self.params p = matrix.multVec(p) - v1= matrix.multVec(v1) - v2= matrix.multVec(v2) - v3= matrix.multVec(v3) - self.params = (p,v1,v2,v3) + v1 = matrix.multVec(v1) + v2 = matrix.multVec(v2) + v3 = matrix.multVec(v3) + self.params = (p, v1, v2, v3) - def buildShape(self,boundBox): - p,v1,v2,v3 = self.params + def buildShape(self, boundBox): + p, v1, v2, v3 = self.params a1 = FreeCAD.Vector(v1) a2 = FreeCAD.Vector(v2) a3 = FreeCAD.Vector(v3) @@ -630,18 +653,31 @@ def buildShape(self,boundBox): a2.normalize() a3.normalize() - m=FreeCAD.Matrix(a1.x, a2.x, a3.x, p.x, - a1.y, a2.y, a3.y, p.y, - a1.z, a2.z, a3.z, p.z, - 0, 0, 0, 1) - box = Part.makeBox(v1.Length,v2.Length,v3.Length) + m = FreeCAD.Matrix( + a1.x, + a2.x, + a3.x, + p.x, + a1.y, + a2.y, + a3.y, + p.y, + a1.z, + a2.z, + a3.z, + p.z, + 0, + 0, + 0, + 1, + ) + box = Part.makeBox(v1.Length, v2.Length, v3.Length) self.shape = box.transformGeometry(m) - class Undefined: - def __init__(self,Id): - self.type = 'Undefined' + def __init__(self, Id): + self.type = "Undefined" self.id = Id self.shape = None self.params = None @@ -649,182 +685,195 @@ def __init__(self,Id): def copy(self): return Undefined(self.id) - def buildShape(self,boundBox): + def buildShape(self, boundBox): return - - def transform(self,matrix): + + def transform(self, matrix): return + def FuseSolid(parts): if (len(parts)) <= 1: - if parts : - solid = parts[0] - else: - return None + if parts: + solid = parts[0] + else: + return None else: - try: - fused = parts[0].fuse(parts[1:]) - except: - fused = None - - if fused is not None: - try : - refinedfused = fused.removeSplitter() - except : - refinedfused = fused - - if refinedfused.isValid() : - solid = refinedfused - else : - if fused.isValid(): - solid = fused - else: - solid = Part.makeCompound(parts) - else: - solid = Part.makeCompound(parts) - - if solid.Volume < 0 : solid.reverse() - return solid + try: + fused = parts[0].fuse(parts[1:]) + except: + fused = None + + if fused is not None: + try: + refinedfused = fused.removeSplitter() + except: + refinedfused = fused + + if refinedfused.isValid(): + solid = refinedfused + else: + if fused.isValid(): + solid = fused + else: + solid = Part.makeCompound(parts) + else: + solid = Part.makeCompound(parts) -def makeHyperboloid(center,radii,rAxes,axis,onesht,length): - - S1 = center + rAxes[1] * radii[1] # major axis - S2 = center + rAxes[0] * radii[0] # minor axis - hyperbola = Part.Hyperbola(S1,S2,center) - - Y = length - X = radii[1] * math.sqrt((Y/radii[0])**2 +1 ) - point = center + X*radii[1] + Y*radii[0] # point in taken as length is always counted on minor axis - parameter = abs(hyperbola.parameter(point)) + if solid.Volume < 0: + solid.reverse() + return solid - if onesht : - shape = hyperbola.toBSpline(-parameter,parameter).toShape(-parameter,parameter) - hyperFace = shape.revolve(center,axis,360) - StartPoint = hyperFace.Surface.BasisCurve.StartPoint - center - EndPoint = hyperFace.Surface.BasisCurve.EndPoint - center +def makeHyperboloid(center, radii, rAxes, axis, onesht, length): - rad1 = StartPoint.dot(hyperbola.XAxis) - hgt1 = StartPoint.dot(hyperbola.YAxis) - cc1 = center + hyperbola.YAxis*hgt1 - circle1 = Part.Circle(cc1,-hyperbola.YAxis,rad1).toShape() - cFace1 = Part.makeFace(circle1,"Part::FaceMakerSimple") + S1 = center + rAxes[1] * radii[1] # major axis + S2 = center + rAxes[0] * radii[0] # minor axis + hyperbola = Part.Hyperbola(S1, S2, center) - rad2 = EndPoint.dot(hyperbola.XAxis) - hgt2 = EndPoint.dot(hyperbola.YAxis) - cc2 = center + hyperbola.YAxis*hgt2 - circle2 = Part.Circle(cc2,hyperbola.YAxis,rad2).toShape() - cFace2 = Part.makeFace(circle2,"Part::FaceMakerSimple") + Y = length + X = radii[1] * math.sqrt((Y / radii[0]) ** 2 + 1) + point = ( + center + X * radii[1] + Y * radii[0] + ) # point in taken as length is always counted on minor axis + parameter = abs(hyperbola.parameter(point)) - shell = Part.makeShell((cFace1,hyperFace,cFace2)) - hyperboloid = Part.makeSolid(shell) + if onesht: + shape = hyperbola.toBSpline(-parameter, parameter).toShape( + -parameter, parameter + ) + hyperFace = shape.revolve(center, axis, 360) + + StartPoint = hyperFace.Surface.BasisCurve.StartPoint - center + EndPoint = hyperFace.Surface.BasisCurve.EndPoint - center + + rad1 = StartPoint.dot(hyperbola.XAxis) + hgt1 = StartPoint.dot(hyperbola.YAxis) + cc1 = center + hyperbola.YAxis * hgt1 + circle1 = Part.Circle(cc1, -hyperbola.YAxis, rad1).toShape() + cFace1 = Part.makeFace(circle1, "Part::FaceMakerSimple") + + rad2 = EndPoint.dot(hyperbola.XAxis) + hgt2 = EndPoint.dot(hyperbola.YAxis) + cc2 = center + hyperbola.YAxis * hgt2 + circle2 = Part.Circle(cc2, hyperbola.YAxis, rad2).toShape() + cFace2 = Part.makeFace(circle2, "Part::FaceMakerSimple") + + shell = Part.makeShell((cFace1, hyperFace, cFace2)) + hyperboloid = Part.makeSolid(shell) else: - shape = hyperbola.toBSpline(0,parameter).toShape(0,parameter) - hyperFace = shape.revolve(center,axis,360) + shape = hyperbola.toBSpline(0, parameter).toShape(0, parameter) + hyperFace = shape.revolve(center, axis, 360) - rad = EndPoint.dot(hyperbola.YAxis) - hgt = EndPoint.dot(hyperbola.XAxis) - cc = center + hyperbola.XAxis*hgt - circle = Part.Circle(cc,-hyperbola.XAxis,rad).toShape() - cFace = Part.makeFace(circle,"Part::FaceMakerSimple") + rad = EndPoint.dot(hyperbola.YAxis) + hgt = EndPoint.dot(hyperbola.XAxis) + cc = center + hyperbola.XAxis * hgt + circle = Part.Circle(cc, -hyperbola.XAxis, rad).toShape() + cFace = Part.makeFace(circle, "Part::FaceMakerSimple") - shell = Part.makeShell((cFace,hyperFace)) - hyper1 = Part.makeSolid(shell) - hyper2 = hyper1.rotated(center,hyperbola.YAxis,180) - hyperboloid = Part.makeCompound((hyper1,hyper2)) + shell = Part.makeShell((cFace, hyperFace)) + hyper1 = Part.makeSolid(shell) + hyper2 = hyper1.rotated(center, hyperbola.YAxis, 180) + hyperboloid = Part.makeCompound((hyper1, hyper2)) return hyperboloid -def makeHyperbolicCylinder(center,radii,rAxes,axis,length): +def makeHyperbolicCylinder(center, radii, rAxes, axis, length): + + S11 = center + rAxes[1] * radii[1] # major axis + S12 = center + rAxes[0] * radii[0] # minor axis + S21 = center - rAxes[1] * radii[1] # major axis + S22 = center - rAxes[0] * radii[0] # minor axis - S11 = center + rAxes[1] * radii[1] # major axis - S12 = center + rAxes[0] * radii[0] # minor axis - S21 = center - rAxes[1] * radii[1] # major axis - S22 = center - rAxes[0] * radii[0] # minor axis - - hyperbola1 = Part.Hyperbola(S11,S12,center) - hyperbola2 = Part.Hyperbola(S21,S22,center) - d = axis*length + hyperbola1 = Part.Hyperbola(S11, S12, center) + hyperbola2 = Part.Hyperbola(S21, S22, center) + d = axis * length - Y = length - X = radii[1] * math.sqrt((Y/radii[0])**2 +1 ) - point = center + X*rAxes[1] + Y*rAxes[0] # point in taken as length is always counted on minor axis + Y = length + X = radii[1] * math.sqrt((Y / radii[0]) ** 2 + 1) + point = ( + center + X * rAxes[1] + Y * rAxes[0] + ) # point in taken as length is always counted on minor axis parameter = abs(hyperbola1.parameter(point)) - shape1 = hyperbola1.toBSpline(-parameter,parameter).toShape(-parameter,parameter) - shape2 = hyperbola2.toBSpline(-parameter,parameter).toShape(-parameter,parameter) - surf1 = shape1.extrude(d) - surf2 = shape2.extrude(d) - - return Part.makeCompound((surf1,surf2)) + shape1 = hyperbola1.toBSpline(-parameter, parameter).toShape(-parameter, parameter) + shape2 = hyperbola2.toBSpline(-parameter, parameter).toShape(-parameter, parameter) + surf1 = shape1.extrude(d) + surf2 = shape2.extrude(d) + + return Part.makeCompound((surf1, surf2)) -def makeEllipticCylinder(center,radii,rAxes,axis,length): +def makeEllipticCylinder(center, radii, rAxes, axis, length): - S1 = center + rAxes[1] * radii[1] # major axis - S2 = center + rAxes[0] * radii[0] # minor axis - d = axis*length + S1 = center + rAxes[1] * radii[1] # major axis + S2 = center + rAxes[0] * radii[0] # minor axis + d = axis * length - ellipse = Part.Ellipse(S1,S2,center) - ellipse2 = Part.Ellipse(S1+d,S2+d,center+d) - - shape = ellipse.toBSpline().toShape() - shape2 = ellipse2.toBSpline().toShape() - shell = Part.makeLoft((shape,shape2),True) + ellipse = Part.Ellipse(S1, S2, center) + ellipse2 = Part.Ellipse(S1 + d, S2 + d, center + d) + + shape = ellipse.toBSpline().toShape() + shape2 = ellipse2.toBSpline().toShape() + shell = Part.makeLoft((shape, shape2), True) return Part.makeSolid(shell) -def makeEllipsoid(center,radii,rAxes,axis): +def makeEllipsoid(center, radii, rAxes, axis): - S1 = center + rAxes[1] * radii[1] # major axis - S2 = center + rAxes[0] * radii[0] # minor axis + S1 = center + rAxes[1] * radii[1] # major axis + S2 = center + rAxes[0] * radii[0] # minor axis - ellipse = Part.Ellipse(S1,S2,center) + ellipse = Part.Ellipse(S1, S2, center) - if axis.add(-rAxes[0]).Length < 1e-5 : - shape = ellipse.toBSpline().toShape() - shell = shape.revolve(center,axis,180) + if axis.add(-rAxes[0]).Length < 1e-5: + shape = ellipse.toBSpline().toShape() + shell = shape.revolve(center, axis, 180) else: - shape = ellipse.toBSpline(0,math.pi).toShape(0,math.pi) - shell = shape.revolve(center,axis,360) + shape = ellipse.toBSpline(0, math.pi).toShape(0, math.pi) + shell = shape.revolve(center, axis, 360) return Part.makeSolid(shell) -def makeEllipticTorus(R,RZ,RX,center,ZAxis): - + +def makeEllipticTorus(R, RZ, RX, center, ZAxis): + rMaj = RZ rMin = RX XAxis = ortoVect(ZAxis) - majorAxis = ZAxis minorAxis = XAxis - if (rMaj < rMin): - rMaj,rMin = rMin,rMaj - majorAxis,minorAxis = minorAxis,majorAxis + if rMaj < rMin: + rMaj, rMin = rMin, rMaj + majorAxis, minorAxis = minorAxis, majorAxis - eCenter= center+R*XAxis - S1 = eCenter + majorAxis * rMaj # major axis - S2 = eCenter + minorAxis * rMin # minor axis + eCenter = center + R * XAxis + S1 = eCenter + majorAxis * rMaj # major axis + S2 = eCenter + minorAxis * rMin # minor axis ellipse = Part.Ellipse(S1, S2, eCenter) - if abs(R) < RX : # degenerated Torus - pz = RZ*math.sqrt(1-(R/RX)**2) - pz1 = center - pz*ZAxis - pz2 = center + pz*ZAxis - - p1 = ellipse.parameter(pz1) - p2 = ellipse.parameter(pz2) - if p2 < p1 : p2 += 2*math.pi - shape = ellipse.toBSpline(p1,p2).toShape(p1,p2) #revolution around Major axis - rev = shape.revolve(center,ZAxis,360) + if abs(R) < RX: # degenerated Torus + pz = RZ * math.sqrt(1 - (R / RX) ** 2) + pz1 = center - pz * ZAxis + pz2 = center + pz * ZAxis + + p1 = ellipse.parameter(pz1) + p2 = ellipse.parameter(pz2) + if p2 < p1: + p2 += 2 * math.pi + shape = ellipse.toBSpline(p1, p2).toShape( + p1, p2 + ) # revolution around Major axis + rev = shape.revolve(center, ZAxis, 360) else: - shape = ellipse.toBSpline().toShape() #revolution around Minor axis - rev = shape.revolve(center,ZAxis,360) - shell = Part.makeShell((rev,)) + shape = ellipse.toBSpline().toShape() # revolution around Minor axis + rev = shape.revolve(center, ZAxis, 360) + shell = Part.makeShell((rev,)) return Part.makeSolid(shell) -def makeParaboloid(center,axis,focal,length): + +def makeParaboloid(center, axis, focal, length): parabola = Part.Parabola() parabola.Center = center @@ -832,49 +881,50 @@ def makeParaboloid(center,axis,focal,length): parabola.XAxis = axis parabola.Focal = focal - R = math.sqrt(4*focal*length) - point = center + length*parabola.XAxis + R * parabola.YAxis + R = math.sqrt(4 * focal * length) + point = center + length * parabola.XAxis + R * parabola.YAxis parameter = abs(parabola.parameter(point)) - shape = parabola.toBSpline(0,parameter).toShape(0,parameter) - paraFace = shape.revolve(center,axis,360) - - cc = center + length*parabola.XAxis - circle = Part.Circle(cc,-axis,R).toShape() - cFace = Part.makeFace(circle,"Part::FaceMakerSimple") + shape = parabola.toBSpline(0, parameter).toShape(0, parameter) + paraFace = shape.revolve(center, axis, 360) + + cc = center + length * parabola.XAxis + circle = Part.Circle(cc, -axis, R).toShape() + cFace = Part.makeFace(circle, "Part::FaceMakerSimple") - shell = Part.makeShell((cFace,paraFace)) + shell = Part.makeShell((cFace, paraFace)) return Part.makeSolid(shell) -def makeEllipticCone(apex,axis,Ra,radii,rAxes,length): - S1 = apex + rAxes[1] * radii[1]/Ra*length # major axis - S2 = apex + rAxes[0] * radii[0]/Ra*length # minor axis - d = axis*length +def makeEllipticCone(apex, axis, Ra, radii, rAxes, length): + + S1 = apex + rAxes[1] * radii[1] / Ra * length # major axis + S2 = apex + rAxes[0] * radii[0] / Ra * length # minor axis + d = axis * length + + point = Part.Point(apex).toShape() + ellipse = Part.Ellipse(S1 + d, S2 + d, apex + d) - point = Part.Point(apex).toShape() - ellipse = Part.Ellipse(S1+d,S2+d,apex+d) - - shape = ellipse.toBSpline().toShape() - shell = Part.makeLoft((point,shape),True) + shape = ellipse.toBSpline().toShape() + shell = Part.makeLoft((point, shape), True) return Part.makeSolid(shell) def ortoVect(v): vmax = 0 vOrto = None - if abs(v.x) > vmax : - vOrto = (0,1,0) - vmax = abs(v.x) - if abs(v.y) > vmax : - vOrto = (0,0,1) - vmax = abs(v.y) - if abs(v.z) > vmax : - vOrto = (1,0,0) - vmax = abs(v.z) - - if vOrto is None : - return None + if abs(v.x) > vmax: + vOrto = (0, 1, 0) + vmax = abs(v.x) + if abs(v.y) > vmax: + vOrto = (0, 0, 1) + vmax = abs(v.y) + if abs(v.z) > vmax: + vOrto = (1, 0, 0) + vmax = abs(v.z) + + if vOrto is None: + return None vOrto = v.cross(FreeCAD.Vector(vOrto)) vOrto.normalize() diff --git a/src/geouned/GEOReverse/Modules/Parser/PartialFormatter.py b/src/geouned/GEOReverse/Modules/Parser/PartialFormatter.py index 2b08e050..a087d009 100644 --- a/src/geouned/GEOReverse/Modules/Parser/PartialFormatter.py +++ b/src/geouned/GEOReverse/Modules/Parser/PartialFormatter.py @@ -1,10 +1,11 @@ import string -version = '3.6' +version = "3.6" + def make_label(item): if 0 < len(item): - return '{' + item + '}' + return "{" + item + "}" else: return item @@ -12,7 +13,7 @@ def make_label(item): class SafeDict(dict): def __getitem__(self, item): - return super(SafeDict, self).__getitem__(item) or '' + return super(SafeDict, self).__getitem__(item) or "" def __missing__(self, key): return make_label(key) @@ -23,26 +24,35 @@ class PartialFormatter(string.Formatter): def format(*args, **kwargs): if not args: - raise TypeError("descriptor 'format' of 'Formatter' object " - "needs an argument") + raise TypeError( + "descriptor 'format' of 'Formatter' object " "needs an argument" + ) self, args = args[0], args[1:] # allow the "self" keyword be passed try: - format_string, args = args[0], args[1:] # allow the "format_string" keyword be passed + format_string, args = ( + args[0], + args[1:], + ) # allow the "format_string" keyword be passed except IndexError: - if 'format_string' in kwargs: - format_string = kwargs.pop('format_string') + if "format_string" in kwargs: + format_string = kwargs.pop("format_string") else: - raise TypeError("format() missing 1 required positional " - "argument: 'format_string'") + raise TypeError( + "format() missing 1 required positional " + "argument: 'format_string'" + ) return string.Formatter.vformat(self, format_string, args, SafeDict(kwargs)) - def _vformat(self, format_string, args, kwargs, used_args, recursion_depth, auto_arg_index=0): + def _vformat( + self, format_string, args, kwargs, used_args, recursion_depth, auto_arg_index=0 + ): """Clone from Python3 version to fix Python2 mess with unnamed {} format specifiers""" if recursion_depth < 0: - raise ValueError('Max string recursion exceeded') + raise ValueError("Max string recursion exceeded") result = [] - for literal_text, field_name, format_spec, conversion in \ - self.parse(format_string): + for literal_text, field_name, format_spec, conversion in self.parse( + format_string + ): # output the literal text if literal_text: @@ -54,18 +64,22 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth, auto # the formatting # handle arg indexing when empty field_names are given. - if field_name == '': + if field_name == "": if auto_arg_index is False: - raise ValueError('cannot switch from manual field ' - 'specification to automatic field ' - 'numbering') + raise ValueError( + "cannot switch from manual field " + "specification to automatic field " + "numbering" + ) field_name = str(auto_arg_index) auto_arg_index += 1 elif field_name.isdigit(): if auto_arg_index: - raise ValueError('cannot switch from manual field ' - 'specification to automatic field ' - 'numbering') + raise ValueError( + "cannot switch from manual field " + "specification to automatic field " + "numbering" + ) # disable auto arg incrementing, if it gets # used later on, then an exception will be raised auto_arg_index = False @@ -79,22 +93,30 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth, auto obj = self.convert_field(obj, conversion) # expand the format spec, if needed - if version == '2.7': + if version == "2.7": format_spec = self._vformat( - format_spec, args, kwargs, - used_args, recursion_depth-1, - auto_arg_index=auto_arg_index) + format_spec, + args, + kwargs, + used_args, + recursion_depth - 1, + auto_arg_index=auto_arg_index, + ) else: format_spec, auto_arg_index = self._vformat( - format_spec, args, kwargs, - used_args, recursion_depth-1, - auto_arg_index=auto_arg_index) + format_spec, + args, + kwargs, + used_args, + recursion_depth - 1, + auto_arg_index=auto_arg_index, + ) # format the object and append to the result result.append(self.format_field(obj, format_spec)) - result = ''.join(result) + result = "".join(result) - if version == '2.7': + if version == "2.7": return result else: return result, auto_arg_index diff --git a/src/geouned/GEOReverse/Modules/Parser/parser.py b/src/geouned/GEOReverse/Modules/Parser/parser.py index 914e6379..5431690a 100644 --- a/src/geouned/GEOReverse/Modules/Parser/parser.py +++ b/src/geouned/GEOReverse/Modules/Parser/parser.py @@ -10,7 +10,7 @@ from .PartialFormatter import PartialFormatter -version = '3.6' +version = "3.6" try: # This clause define the fallback for cPickle, which is an accelerated @@ -22,26 +22,28 @@ import pickle as cPickle # integer with one prefix character -re_int = re.compile(r'\D{0,1}\d+') +re_int = re.compile(r"\D{0,1}\d+") # interior of square brackets for tally in lattices -re_ind = re.compile(r'\[.+\]', flags=re.DOTALL) +re_ind = re.compile(r"\[.+\]", flags=re.DOTALL) # repitition syntax of MCNP input file -re_rpt = re.compile(r'\d+[ri]', flags=re.IGNORECASE) +re_rpt = re.compile(r"\d+[ri]", flags=re.IGNORECASE) # imp or tmp parameters in cell card -re_prm = re.compile(r'((imp:n|imp:p|tmp)\s+\S+)') -re_prm = re.compile(r'[it]mp:*[npe]*[=\s]+\S+', flags=re.IGNORECASE) -re_prm = re.compile(r'([it]mp:*[npe]*[=\s]+)(\S+)', flags=re.IGNORECASE) +re_prm = re.compile(r"((imp:n|imp:p|tmp)\s+\S+)") +re_prm = re.compile(r"[it]mp:*[npe]*[=\s]+\S+", flags=re.IGNORECASE) +re_prm = re.compile(r"([it]mp:*[npe]*[=\s]+)(\S+)", flags=re.IGNORECASE) # fill keyword -re_fll = re.compile(r'\*{0,1}fill[=\s]+', flags=re.IGNORECASE) # TODO: this will also match fill=== +re_fll = re.compile( + r"\*{0,1}fill[=\s]+", flags=re.IGNORECASE +) # TODO: this will also match fill=== # If type specifier not given, any data type can be formatted: def fmt_gen(s): - return '{' + ':<{}'.format(len(s)) + '}' + return "{" + ":<{}".format(len(s)) + "}" fmt_d = fmt_gen @@ -69,6 +71,7 @@ class __CIDClass(object): This class is to describe the 1-st level of card types. """ + # no-information cards comment = -1 blankline = -2 @@ -85,10 +88,10 @@ def get_name(cls, cid): Return the name of the card type by its index. """ for k, v in list(cls.__dict__.items()): - if '__' not in k and v == cid: + if "__" not in k and v == cid: return k else: - print('No attribute with name', cid) + print("No attribute with name", cid) raise ValueError() @@ -99,6 +102,7 @@ class Card(object): """ Representation of a card. """ + def __init__(self, lines, ctype, pos, debug=None): # Original lines, as read from the input file @@ -125,7 +129,7 @@ def __init__(self, lines, ctype, pos, debug=None): # template string. Represents the general structure of the card. It is # a copy of lines, but meaningful parts are replaced by format # specifiers, {} - self.template = '' + self.template = "" # List of strings represenging meaningful parts of the card. The # original multi-line string card is obtained as @@ -149,11 +153,11 @@ def __init__(self, lines, ctype, pos, debug=None): self.__u = -1 # -1 means undefined. None -- not specified in input self.__f = -1 # fill self.__m = -1 # material - self.__d = '' # density + self.__d = "" # density self.__i = -1 # importances self.__cr = -1 # set of reference cells. # surface properties - self.__st = '' # '' means undefined. + self.__st = "" # '' means undefined. # Split card to template and meaningful part is always needed. Other # operations are optional. @@ -182,66 +186,69 @@ def _set_value_by_type(self, t, v): @property def geom_prefix(self): - return self._get_value_by_type('#gpr') + return self._get_value_by_type("#gpr") @geom_prefix.setter def geom_prefix(self, value): - return self._set_value_by_type('#gpr', value) + return self._set_value_by_type("#gpr", value) @property def geom_suffix(self): - return self._get_value_by_type('#gsu') + return self._get_value_by_type("#gsu") @geom_suffix.setter def geom_suffix(self, value): - return self._set_value_by_type('#gsu', value) + return self._set_value_by_type("#gsu", value) - def print_debug(self, comment, key='tihv'): + def print_debug(self, comment, key="tihv"): d = self.debug if d: - print('Line {}, {} card. {}'.format(self.pos, - CID.get_name(self.ctype), - comment), file=d) - if 't' in key: - print(' template:', repr(self.template), file=d) - if 'i' in key: - print(' input: ', self.input, file=d) - if 'h' in key: - print(' hidden: ', self.hidden, file=d) - if 'v' in key: - print(' values: ', self.values, file=d) + print( + "Line {}, {} card. {}".format( + self.pos, CID.get_name(self.ctype), comment + ), + file=d, + ) + if "t" in key: + print(" template:", repr(self.template), file=d) + if "i" in key: + print(" input: ", self.input, file=d) + if "h" in key: + print(" hidden: ", self.hidden, file=d) + if "v" in key: + print(" values: ", self.values, file=d) def get_input(self, check_bad_chars=False): """ Recompute template, input and hidden attributes from lines """ - mline = ''.join(self.lines) + mline = "".join(self.lines) if check_bad_chars: - bad_chars = '\t' + bad_chars = "\t" for c in bad_chars: if c in mline: if self.debug: - self.print_debug('get_input: bad char in input cards', - '') + self.print_debug("get_input: bad char in input cards", "") else: - raise ValueError('Bad character in input file. ' + - 'Run with --debug option.') + raise ValueError( + "Bad character in input file. " + "Run with --debug option." + ) if self.ctype in (CID.comment, CID.blankline): # nothing to do for comments or blanklines: - self.input = '' + self.input = "" self.template = mline else: # TODO: protect { and } in comment parts of the card. tmpl = [] # part of template inpt = [] # input, meaningful parts of the card. - if mline.split()[0][:2] == 'fc': + if mline.split()[0][:2] == "fc": # this is tally comment. It always in one line and is not # delimited by & or $ i = mline[:80] - t = mline.replace(i, '{}', 1) + t = mline.replace(i, "{}", 1) inpt = [i] tmpl = [t] else: @@ -251,7 +258,7 @@ def get_input(self, check_bad_chars=False): else: # entries optionally delimited from comments by $ or & # requires that delimiters prefixed with space - d = index_(l, '$&') + d = index_(l, "$&") # d1 = l.find(' $') # d2 = l.find(' &') # if -1 < d1 and -1 < d2: @@ -269,11 +276,11 @@ def get_input(self, check_bad_chars=False): inpt.append(i) tmpl.append(fmt_s(i) + t) self.input = inpt - self.template = ''.join(tmpl) + self.template = "".join(tmpl) # TODO: dtype and name of the card can be defined already here. - self.print_debug('get_input', 'ti') + self.print_debug("get_input", "ti") return def _protect_nums(self): @@ -282,53 +289,55 @@ def _protect_nums(self): represent cell, surface or a cell parameter with some unused char. """ - inpt = '\n'.join(self.input) + inpt = "\n".join(self.input) d = {} # in cell card: if self.ctype == CID.cell: # and 'like' not in inpt: - d['~'] = [] # float values in cells + d["~"] = [] # float values in cells # Replace material density - if 'like' not in inpt: - tokens = inpt.replace('=', ' ').split() + if "like" not in inpt: + tokens = inpt.replace("=", " ").split() cell, mat, rho = tokens[:3] if int(mat) != 0: for s in (cell, mat, rho): - inpt = inpt.replace(s, '~', 1) - inpt = inpt.replace('~', cell, 1) - inpt = inpt.replace('~', mat, 1) - d['~'].append(rho) + inpt = inpt.replace(s, "~", 1) + inpt = inpt.replace("~", cell, 1) + inpt = inpt.replace("~", mat, 1) + d["~"].append(rho) # imp and tmp parameters: # print 're_prm: inp', repr(inpt) for s1, s2 in re_prm.findall(inpt): # print 're_prm: fnd', repr(s) - d['~'].append(s2) - inpt = inpt.replace(s1 + s2, s1 + '~', 1) + d["~"].append(s2) + inpt = inpt.replace(s1 + s2, s1 + "~", 1) # replace repitition syntax in junks: sbl = re_rpt.findall(inpt) if sbl: for s in sbl: - inpt = inpt.replace(s, '!', 1) - d['!'] = sbl - - if (self.ctype == CID.data and - inpt.lstrip().lower()[0] == 'f' and - inpt.lstrip()[1].isdigit()): + inpt = inpt.replace(s, "!", 1) + d["!"] = sbl + + if ( + self.ctype == CID.data + and inpt.lstrip().lower()[0] == "f" + and inpt.lstrip()[1].isdigit() + ): # this is tally card. Hide indexes in square brackets sbl = re_ind.findall(inpt) if sbl: for s in sbl: - inpt = inpt.replace(s, '|', 1) - d['|'] = sbl + inpt = inpt.replace(s, "|", 1) + d["|"] = sbl - self.input = inpt.split('\n') + self.input = inpt.split("\n") self.hidden = d - self.print_debug('_protect_nums', 'ih') + self.print_debug("_protect_nums", "ih") return def get_values(self): @@ -344,16 +353,16 @@ def get_values(self): inpt, vt, stype, scoef = _split_surface(self.input) self.TR = None if len(vt) > 1: - if vt[1][1] == 'tr': - self.TR = vt[1][0] + if vt[1][1] == "tr": + self.TR = vt[1][0] self.stype = stype.lower() self.scoefs = scoef self.name = vt[0][0] elif self.ctype == CID.data: inpt, vt, dtype = _split_data(self.input) self.dtype = dtype - if dtype == 'TRn': - #print(vt,inpt) + if dtype == "TRn": + # print(vt,inpt) unit, inpt, fvals = _parse_tr(inpt) self.unit = unit vt += fvals @@ -366,7 +375,7 @@ def get_values(self): self.input = inpt self.values = vt - self.print_debug('get_values', 'iv') + self.print_debug("get_values", "iv") return def get_refcells(self): @@ -380,7 +389,7 @@ def get_refcells(self): else: s = set() for v, t in self.values: - if t == 'cel': + if t == "cel": s.add(v) self.__cr = s return self.__cr @@ -391,9 +400,9 @@ def get_geom(self): string. """ p, s = self.geom_prefix, self.geom_suffix - self.geom_prefix = '§' - self.geom_suffix = '§' - geom = self.card().split('§')[1] + self.geom_prefix = "§" + self.geom_suffix = "§" + geom = self.card().split("§")[1] self.geom_prefix = p self.geom_suffix = s return geom @@ -409,7 +418,7 @@ def get_u(self): else: # get it only once: for v, t in self.values: - if t == 'u': + if t == "u": self.__u = v break else: @@ -426,11 +435,11 @@ def get_m(self): if self.__m != -1: return self.__m else: - if 'like' in ''.join(self.input).lower(): + if "like" in "".join(self.input).lower(): # material name should be given in another cell. pass for v, t in self.values: - if t == 'mat': + if t == "mat": self.__m = v break else: @@ -442,7 +451,7 @@ def get_d(self): """ For cell card return density """ - if self.__d != '': + if self.__d != "": return self.__d if self.get_m() == 0: @@ -450,12 +459,12 @@ def get_d(self): return self.__d elif self.get_m() == -2: # this is like-but cell - self.__d = -100. + self.__d = -100.0 return self.__d else: # density entry is hidden in the input and available as the 1-st # entry in self.hidden dictionary. - self.__d = float(self.hidden['~'][0]) + self.__d = float(self.hidden["~"][0]) return self.__d def set_d(self, v): @@ -465,7 +474,7 @@ def set_d(self, v): It is assumed that get_values() method is called before this. """ if self.get_m() > 0: - self.hidden['~'][0] = v + self.hidden["~"][0] = v self.__d = float(v) def get_f(self, newv=None, trsf=False): @@ -477,45 +486,45 @@ def get_f(self, newv=None, trsf=False): if self.__f != -1 and newv is None: if trsf: - params = [] - for v,t in self.values: - if t == '#tunit': - unit = v - elif t == 'tr': - params = [v] - break - elif t == '#tparam': - params.append(float(v)) - return self.__f,(unit,params) + params = [] + for v, t in self.values: + if t == "#tunit": + unit = v + elif t == "tr": + params = [v] + break + elif t == "#tparam": + params.append(float(v)) + return self.__f, (unit, params) else: - return self.__f + return self.__f else: # get it only once: - unit = '' + unit = "" params = [] for i in range(len(self.values)): v, t = self.values[i] - if t == 'fill': + if t == "fill": if newv is not None: v = newv self.values[i] = (v, t) self.__f = v - if trsf : - unit = self.values[i-1][0] - for v,t in self.values[i+1:]: - if t == 'tr': - params = [v] - break - elif t == '#tparam': - params.append(float(v)) - break + if trsf: + unit = self.values[i - 1][0] + for v, t in self.values[i + 1 :]: + if t == "tr": + params = [v] + break + elif t == "#tparam": + params.append(float(v)) + break else: self.__f = None - - if trsf : - return self.__f,(unit,params) - else: - return self.__f + + if trsf: + return self.__f, (unit, params) + else: + return self.__f def get_imp(self, vals={}): """ @@ -528,22 +537,22 @@ def get_imp(self, vals={}): return self.__i else: res = {} - inpt = ' '.join(self.input).lower() - for p in 'npe': - key = 'imp:' + p + inpt = " ".join(self.input).lower() + for p in "npe": + key = "imp:" + p s = inpt.split(key) if len(s) == 1: # there is no key in the input line. continue else: - n = s[0].count('~') - res[key] = float(self.hidden['~'][n]) + n = s[0].count("~") + res[key] = float(self.hidden["~"][n]) if p in vals: # change value only if necessary if res[key] != vals[p]: res[key] = vals[p] - self.hidden['~'][n] = str(vals[p]) + self.hidden["~"][n] = str(vals[p]) # for s in self.hidden.get('~', []): # sl = s.lower() @@ -551,7 +560,7 @@ def get_imp(self, vals={}): # val = float(sl.replace(key, '').replace('=', '')) # res[key] = val if not res: - res['imp:n'] = 1 + res["imp:n"] = 1 self.__i = res return self.__i @@ -579,32 +588,32 @@ def remove_fill(self): # replace with spaces all FILL-related tokens vals = [] # new values list. oldv = self.values[:] - state = 'before' + state = "before" while oldv: v, t = oldv.pop(0) - if state == 'before' and t == 'fill': - v = ' ' - state = 'afterU' - elif state == 'afterU' and '(' in t: - v = ' ' - state = 'after(' - elif state == 'after(': - v = ' ' - if ')' in t: - state = 'after' + if state == "before" and t == "fill": + v = " " + state = "afterU" + elif state == "afterU" and "(" in t: + v = " " + state = "after(" + elif state == "after(": + v = " " + if ")" in t: + state = "after" vals.append((v, t)) self.values = vals # Remove FILL from the input for n, i in enumerate(self.input): - if 'fill' in i.lower(): + if "fill" in i.lower(): # This part of input contains the fill keyword. This keyword is # optionally prepended with an asterix and followed by a sign - i = re_fll.sub(' ', i) + i = re_fll.sub(" ", i) self.input[n] = i break - self.print_debug('remove_fill', 'iv') + self.print_debug("remove_fill", "iv") return def card(self, wrap=False, comment=True): @@ -613,7 +622,7 @@ def card(self, wrap=False, comment=True): """ if self.input: # put values back to meaningful parts: - inpt = '\n'.join(self.input) + inpt = "\n".join(self.input) inpt = inpt.format(*[t[0] for t in self.values]) # put back hidden parts: @@ -621,48 +630,48 @@ def card(self, wrap=False, comment=True): for v in vl: inpt = inpt.replace(k, v, 1) - inpt = inpt.split('\n') + inpt = inpt.split("\n") if not comment: - return ' '.join(inpt) + return " ".join(inpt) if wrap: # and self.ctype != CID.title: - indent = ' '*5 + indent = " " * 5 if self.ctype == CID.title: - indent = 'c' + indent - tparts = re.split(r'\{.*?\}', self.template)[1:] + indent = "c" + indent + tparts = re.split(r"\{.*?\}", self.template)[1:] # print 'wrapped inp', repr(self.template) # print 'wrapped spl', repr(tparts) - newt = [''] # new template parts - newi = [] # new input parts - self.print_debug('card wrap=True', '') + newt = [""] # new template parts + newi = [] # new input parts + self.print_debug("card wrap=True", "") for i, t in zip(inpt, tparts): - self.print_debug(' ' + repr(i) + repr(t), '') + self.print_debug(" " + repr(i) + repr(t), "") il = [] tl = [t] # while len(i.rstrip()) > 79: while len(i.rstrip()) > 80: # first try to shift to left - if i[:5] == ' '*5: - i = ' '*5 + i.lstrip() + if i[:5] == " " * 5: + i = " " * 5 + i.lstrip() if len(i.rstrip()) > 79: # input i must be wrapped. Find proper place: - for dc in ' :': + for dc in " :": k = i.rstrip().rfind(dc, 0, 75) if k > 6: il.append(i[:k]) - tl.append('\n') + tl.append("\n") i = indent + i[k:] - self.print_debug('card wrap=True' + - repr(il[-1]) + - repr(i), '') + self.print_debug( + "card wrap=True" + repr(il[-1]) + repr(i), "" + ) break else: # there is no proper place to wrap. - self.print_debug('Cannot wrap line ' + - repr(i), '') - warnings.warn('Cannot wrap card' - ' on line {}'.format(self.pos)) + self.print_debug("Cannot wrap line " + repr(i), "") + warnings.warn( + "Cannot wrap card" " on line {}".format(self.pos) + ) break else: # input i fits to one line. Do nothing. @@ -670,7 +679,7 @@ def card(self, wrap=False, comment=True): newt += tl newi += il + [i] - tmpl = '{}'.join(newt) + tmpl = "{}".join(newt) inpt = newi else: tmpl = self.template @@ -685,40 +694,40 @@ def remove_spaces(self): """ Remove extra spaces from meaningful parts. """ - self.print_debug('before remove_spaces', 'i') + self.print_debug("before remove_spaces", "i") if self.ctype in (CID.cell, CID.surface, CID.data): inpt = [] for i in self.input: - indented = i[:5] == ' '*5 + indented = i[:5] == " " * 5 # leave only one sep. space - i = ' '.join(i.split()) + i = " ".join(i.split()) i = i.strip() # spaces before/after some characters are not needed: - for c in '):': - i = i.replace(' ' + c, c) - for c in '(:': - i = i.replace(c + ' ', c) + for c in "):": + i = i.replace(" " + c, c) + for c in "(:": + i = i.replace(c + " ", c) if indented: - i = ' '*5 + i + i = " " * 5 + i inpt.append(i) - self.print_debug(i, '') + self.print_debug(i, "") self.input = inpt - self.print_debug('after remove_spaces', 'i') + self.print_debug("after remove_spaces", "i") return def apply_map(self, f): """ Replace Ni in self.values by Mi = f(Ni, Ti). """ - self.print_debug('before apply_map', 'vi') + self.print_debug("before apply_map", "vi") # u and fill should be renumberd in the same way, but types # must remain different, to let explicit u=0 # self.values = map(lambda t: (f(t[0], t[1]), t[1]), self.values) newvals = [] for t in self.values: - if t[1] == 'fill': - t1 = 'u' + if t[1] == "fill": + t1 = "u" else: t1 = t[1] # newvals.append((f(t[0], t1), t[1])) @@ -728,7 +737,7 @@ def apply_map(self, f): newval = t[0] newvals.append((newval, t[1])) self.values = newvals - self.print_debug('after apply_map', 'vi') + self.print_debug("after apply_map", "vi") return @@ -778,30 +787,30 @@ def _split_cell(input_, self): # all of them should land to the card template, therefore, after all # entries are replaced with format specifiers, it can be split back to a # list easily at \n positions. - inpt = '\n'.join(input_) + inpt = "\n".join(input_) vals = [] # list of values fmts = [] # value format. It has digits, thus inserted into inpt later. - tp = '_' # temporary placeholder for format specifiers + tp = "_" # temporary placeholder for format specifiers # Parse part before parameters. This is different for usual and like-but # syntax. As result, all entries are replaced in inpt and i, the index # where parameter's part starts in inpt, is computed. - if 'like ' in inpt.lower(): + if "like " in inpt.lower(): # Get cell name t = inpt.split() js = t.pop(0) inpt = inpt.replace(js, tp, 1) - vals.append((int(js), 'cel')) + vals.append((int(js), "cel")) fmts.append(fmt_d(js)) # Get reference cell name: t.pop(0) # like js = t.pop(0) inpt = inpt.replace(js, tp, 1) - vals.append((int(js), 'cel')) + vals.append((int(js), "cel")) fmts.append(fmt_d(js)) # compute i -- where first param token starts @@ -818,23 +827,23 @@ def _split_cell(input_, self): # Get cell name js = t.pop(0) inpt = inpt.replace(js, tp, 1) - vals.append((int(js), 'cel')) + vals.append((int(js), "cel")) fmts.append(fmt_d(js)) # get material and density. # Density, if specified in cells card, should be allready hidden ms = t.pop(0) if int(ms) == 0: - inpt = inpt.replace(ms, tp+tp, 1) + inpt = inpt.replace(ms, tp + tp, 1) else: inpt = inpt.replace(ms, tp, 1) - inpt = inpt.replace('~', '~'+tp, 1) - vals.append((int(ms), 'mat')) + inpt = inpt.replace("~", "~" + tp, 1) + vals.append((int(ms), "mat")) fmts.append(fmt_d(ms)) # placeholder for geometry prefix - vals.append(('', '#gpr')) - fmts.append('{}') + vals.append(("", "#gpr")) + fmts.append("{}") # Get geometry and parameters blocks. I assume that geom and param # blocks are separated by at least one space, so there will be an @@ -844,7 +853,7 @@ def _split_cell(input_, self): parm = [] while t: e = t.pop(0) - if e[0].isalpha() or e[0] == '*': + if e[0].isalpha() or e[0] == "*": parm = [e] + t break else: @@ -852,10 +861,10 @@ def _split_cell(input_, self): # print '_split_cell geom', geom, parm # replace integer entries in geom block: - for s in re_int.findall(' '.join(geom)): + for s in re_int.findall(" ".join(geom)): # print 's from re_int', repr(s) # s is a surface or a cell (later only if prefixed by #) - t = 'cel' if s[0] == '#' else 'sur' + t = "cel" if s[0] == "#" else "sur" s = s if s[0].isdigit() else s[1:] f = fmt_d(s) inpt = inpt.replace(s, tp, 1) @@ -867,11 +876,11 @@ def _split_cell(input_, self): fmts.append(f) # geometry suffix - vals.append(('', '#gsu')) - fmts.append('{}') + vals.append(("", "#gsu")) + fmts.append("{}") # insert placeholder for geometry suffix if parm: - inpt = inpt.replace(parm[0], '_' + parm[0], 1) + inpt = inpt.replace(parm[0], "_" + parm[0], 1) # At this point all geom entries are replaced in inpt. The rest should # work only with the parm part of inpt. To ensure this, inpt is splitted @@ -893,103 +902,105 @@ def _split_cell(input_, self): # replace values in parameters block. Values are prefixed with = or space(s) # Note that tmp and imp values must be hidden - t = ' '.join(parm).replace('=', ' ').split() # get rid of =. + t = " ".join(parm).replace("=", " ").split() # get rid of =. while t: s = t.pop(0) # print '_split_cell s: ', repr(s) - if s.lower() == 'u': + if s.lower() == "u": vs = t.pop(0) vv = int(vs) vf = fmt_d(vs) - vt = 'u' + vt = "u" inpt_parm = inpt_parm.replace(vs, tp, 1) vals.append((vv, vt)) fmts.append(vf) - elif 'fill' in s.lower(): + elif "fill" in s.lower(): # print '_split_cell: has fill!' # assume that only one integer follows the fill keyword, optionally # with transformation in parentheses. # set transformation dimension deg if *FILL or cos if FILL - if '*' in s : - vv = '*' + if "*" in s: + vv = "*" else: - vv = '' + vv = "" vf = fmt_s(vv) - vt = '#tunit' - vals.append((vv,vt)) + vt = "#tunit" + vals.append((vv, vt)) fmts.append(vf) - + vs = t.pop(0) # if transformation in parentheses follows the universe number # immediately, split this manually: - if '(' in vs: - i = vs.index('(') + if "(" in vs: + i = vs.index("(") ttt = vs[i:] vs = vs[:i] # vs, ttt = vs.split('(') - t.insert(0, ttt) + t.insert(0, ttt) vv = int(vs) vf = fmt_d(vs) - vt = 'fill' + vt = "fill" inpt_parm = inpt_parm.replace(vs, tp, 1) vals.append((vv, vt)) fmts.append(vf) # fill value can be followed by transformation in parentheses # Fill value can be optionally followed by transformation number of # transformation parameters in parentheses - if t and '(' in t[0]: + if t and "(" in t[0]: vsl = [] # lists of strings, values, formats and types vvl = [] vfl = [] vtl = [] # add opening parenthesis - vsl.append('(') - vvl.append('(') - vfl.append(fmt_s('(')) - vtl.append('#(') # #-types are internal, don't output in --mode info. - t[0] = t[0].replace('(', '', 1) + vsl.append("(") + vvl.append("(") + vfl.append(fmt_s("(")) + vtl.append("#(") # #-types are internal, don't output in --mode info. + t[0] = t[0].replace("(", "", 1) # add entries in parentheses and the closing parenthis - while vsl[-1] != ')': + while vsl[-1] != ")": vs = t.pop(0) - if ')' in vs: - vs = vs.replace(')', '', 1) + if ")" in vs: + vs = vs.replace(")", "", 1) if vs: vsl.append(vs) vvl.append(vs) vfl.append(fmt_s(vs)) - vtl.append('#tparam') - vsl.append(')') - vvl.append(')') - vfl.append(fmt_s(')')) - vtl.append('#)') + vtl.append("#tparam") + vsl.append(")") + vvl.append(")") + vfl.append(fmt_s(")")) + vtl.append("#)") elif vs: vsl.append(vs) vvl.append(vs) vfl.append(fmt_s(vs)) - vtl.append('#tparam') + vtl.append("#tparam") # check if only one parameter in parenthethes -- it is tr # number, not tr parameter if len(vsl) == 3: vvl[1] = int(vvl[1]) vfl[1] = fmt_d(vsl[1]) - vtl[1] = 'tr' + vtl[1] = "tr" # add all strings, values, formats and types: for vs, vv, vf, vt in zip(vsl, vvl, vfl, vtl): - inpt_parm = inpt_parm.replace(vs, tp, 1) # TODO: here only parm part of inpt should be modified. + inpt_parm = inpt_parm.replace( + vs, tp, 1 + ) # TODO: here only parm part of inpt should be modified. vals.append((vv, vt)) fmts.append(vf) # warn if there is possibility for an array following the fill # keyword: # TODO fill value can be an array - if 'fill' == s.lower() and 'lat' in ''.join(parm).lower(): - print('WARNING: fill keyword followed by an array', end=' ') - print('cannot be parsed') + if "fill" == s.lower() and "lat" in "".join(parm).lower(): + print("WARNING: fill keyword followed by an array", end=" ") + print("cannot be parsed") inpt = inpt_geom + inpt_parm @@ -997,26 +1008,26 @@ def _split_cell(input_, self): for f in fmts: inpt = inpt.replace(tp, f, 1) - return inpt.split('\n'), vals + return inpt.split("\n"), vals def _split_surface(input_): """ Similar to _split_cell(), but for surface cards. """ - inpt = '\n'.join(input_) + inpt = "\n".join(input_) t = inpt.split() vals = [] # like in split_cell() fmts = [] - tp = '_' + tp = "_" # get surface name: js = t.pop(0) if not js[0].isdigit(): js = js[1:] inpt = inpt.replace(js, tp, 1) - vals.append((int(js), 'sur')) + vals.append((int(js), "sur")) fmts.append(fmt_d(js)) # get TR or periodic surface: @@ -1024,14 +1035,14 @@ def _split_surface(input_): if ns[0].isdigit(): # TR is given inpt = inpt.replace(ns, tp, 1) - vals.append((int(ns), 'tr')) + vals.append((int(ns), "tr")) fmts.append(fmt_d(ns)) st = t.pop(0) - elif ns[0] == '-': + elif ns[0] == "-": # periodic surface ns = ns[1:] inpt = inpt.replace(ns, tp, 1) - vals.append((int(ns), 'sur')) + vals.append((int(ns), "sur")) fmts.append(fmt_d(ns)) st = t.pop(0) elif ns[0].isalpha(): @@ -1046,11 +1057,11 @@ def _split_surface(input_): for f in fmts: inpt = inpt.replace(tp, f, 1) - return inpt.split('\n'), vals, st, scoef + return inpt.split("\n"), vals, st, scoef def _get_int(s): - r = '' + r = "" for c in s: if r and c.isalpha(): break @@ -1063,79 +1074,81 @@ def _parse_tr(input_): """ input_ should be already passed through _split_data() """ - inpt = '\n'.join(input_) + inpt = "\n".join(input_) inp1, inp2 = inpt.split(None, 1) - if '*' in inp1: - unit = '*' + if "*" in inp1: + unit = "*" else: - unit = '' + unit = "" svals = inp2.split() for s in svals: - inp2 = inp2.replace(s, '{}', 1) + inp2 = inp2.replace(s, "{}", 1) - fvals = [(float(s), 'float') for s in svals] - return unit, (inp1 + ' ' + inp2).split('\n'), fvals + fvals = [(float(s), "float") for s in svals] + return unit, (inp1 + " " + inp2).split("\n"), fvals def _split_data(input_): - inpt = '\n'.join(input_) + inpt = "\n".join(input_) t = inpt.split() vals = [] fmts = [] - tp = '_' + tp = "_" - if 'tr' in t[0][:3].lower(): + if "tr" in t[0][:3].lower(): # TRn card - dtype = 'TRn' + dtype = "TRn" ns = _get_int(t[0]) inpt = inpt.replace(ns, tp, 1) - vals.append((int(ns), 'tr')) + vals.append((int(ns), "tr")) fmts.append(fmt_d(ns)) - elif (t[0][0].lower() == 'm' and - 'mode' not in t[0].lower() and - 'mesh' not in t[0].lower() and - 'mphys' not in t[0].lower()): + elif ( + t[0][0].lower() == "m" + and "mode" not in t[0].lower() + and "mesh" not in t[0].lower() + and "mphys" not in t[0].lower() + ): # This is the Mn, MTn or MPNn card ms = _get_int(t[0]) inpt = inpt.replace(ms, tp, 1) - vals.append((int(ms), 'mat')) + vals.append((int(ms), "mat")) fmts.append(fmt_d(ms)) # additional tests to define data card type: if t[0][1].isdigit(): - dtype = 'Mn' - elif t[0][1].lower() == 't': - dtype = 'MTn' - elif t[0][1].lower() == 'p': - dtype = 'MPNn' - elif t[0][1].lower() == 'x': - dtype = 'MXn' + dtype = "Mn" + elif t[0][1].lower() == "t": + dtype = "MTn" + elif t[0][1].lower() == "p": + dtype = "MPNn" + elif t[0][1].lower() == "x": + dtype = "MXn" else: dtype = None - elif t[0][0].lower() == 'f' and t[0][1].isdigit(): + elif t[0][0].lower() == "f" and t[0][1].isdigit(): # FN card - dtype = 'Fn' + dtype = "Fn" ns = _get_int(t[0]) # tally number inpt = inpt.replace(ns, tp, 1) - vals.append((int(ns), 'tal')) + vals.append((int(ns), "tal")) fmts.append(fmt_d(ns)) # define type of integers by tally type: nv = int(ns[-1]) if nv in [1, 2]: - typ = 'sur' + typ = "sur" elif nv in [4, 6, 7, 8]: - typ = 'cel' + typ = "cel" else: - typ = '' + typ = "" if typ: # Lattice indices, surrounded by square brakets must allready be # hidden # Special treatment, if tally has 'u=' syntax. - hasu = 'u' in inpt.lower() and '=' in inpt.lower() + hasu = "u" in inpt.lower() and "=" in inpt.lower() # find all integers -- they are cells or surfaces for s in re_int.findall(inpt): ss = s[1:] @@ -1146,19 +1159,19 @@ def _split_data(input_): i1 = inpt.rfind(tp) i2 = inpt.find(ss) part = inpt[i1:i2] - while ' ' in part: - part = part.replace(' ', '') - if part[-2:].lower() == 'u=': - tpe = 'u' + while " " in part: + part = part.replace(" ", "") + if part[-2:].lower() == "u=": + tpe = "u" inpt = inpt.replace(ss, tp, 1) vals.append((int(ss), tpe)) fmts.append(fmt_d(ss)) - elif 'fmesh' == t[0][:5].lower() and t[0][5].isdigit(): + elif "fmesh" == t[0][:5].lower() and t[0][5].isdigit(): # fmesh card - dtype = 'fmesh' + dtype = "fmesh" ns = _get_int(t[0]) # tally number inpt = inpt.replace(ns, tp, 1) - vals.append((int(ns), 'tal')) + vals.append((int(ns), "tal")) fmts.append(fmt_d(ns)) else: dtype = None @@ -1166,7 +1179,7 @@ def _split_data(input_): for f in fmts: inpt = inpt.replace(tp, f, 1) - return inpt.split('\n'), vals, dtype + return inpt.split("\n"), vals, dtype def is_commented(l): @@ -1178,10 +1191,10 @@ def is_commented(l): # remove newline chars at the end of l: l = l.splitlines()[0] ls = l[0:6].lstrip().lower() - if 'c ' == ls[0:2] : + if "c " == ls[0:2]: res = True # print 'is_com "c "', - elif 'c' == l.lower(): + elif "c" == l.lower(): res = True # print 'is_com "c"', # print 'is_com', res @@ -1192,16 +1205,18 @@ def is_fc_card(l): """ Return true, if line l is tally comment cards, fcN """ - return l.lstrip().lower()[:2] == 'fc' + return l.lstrip().lower()[:2] == "fc" def is_blankline(l): """ Return True, if l is the delimiter blank line. """ - return l.strip() == '' + return l.strip() == "" + + +if version == "2.7": -if version == '2.7': def get_cards(inp, debug=None, preservetabs=False): """ Check first existence of a dump file @@ -1209,8 +1224,9 @@ def get_cards(inp, debug=None, preservetabs=False): If dump exists and it is newwer than the input file, read the dump file """ from os import stat + iname = inp - dname = '.{}.~'.format(os.path.basename(inp)) + dname = ".{}.~".format(os.path.basename(inp)) try: it = stat(iname).st_mtime except OSError as e: @@ -1224,7 +1240,7 @@ def get_cards(inp, debug=None, preservetabs=False): if it < dt and debug is None: # print('Reading from dump') # dump is youger - dfile = open(dname, 'r') + dfile = open(dname, "r") cl = cPickle.load(dfile) for c in cl: yield c @@ -1237,9 +1253,11 @@ def get_cards(inp, debug=None, preservetabs=False): if debug is None: # otherwise the instances of c contain the file object, which # cannot be dumped. - dfile = open(dname, 'w') + dfile = open(dname, "w") cPickle.dump(cl, dfile) + else: + def get_cards(inp, debug=None, preservetabs=False): """ Check first existence of a dump file @@ -1251,11 +1269,11 @@ def get_cards(inp, debug=None, preservetabs=False): yield c -def index_(line, chars='$&'): +def index_(line, chars="$&"): """ Find the first index of one of the chars in line. """ - r = re.compile('[{}]'.format(chars)) + r = re.compile("[{}]".format(chars)) m = r.search(line) if m: i = m.end() - 1 @@ -1263,6 +1281,7 @@ def index_(line, chars='$&'): i = len(line) - 1 return i + def get_cards_from_input(inp, debug=None, preservetabs=False): """ Iterable, return instances of the Card() class representing @@ -1282,15 +1301,15 @@ def replace_tab(l, cln, preserve=False, ts=8): if preserve: return l[:] else: - while '\t' in l: - i = l.index('\t') + while "\t" in l: + i = l.index("\t") ii = (i // ts + 1) * ts - i print("c Line {}: tab replaced with {} spaces".format(cln + 1, ii)) - l = l[:i] + ' '*ii + l[i+1:] + l = l[:i] + " " * ii + l[i + 1 :] return l[:] cln = 0 # current line number. Used only for debug - with open(inp, 'r') as f: + with open(inp, "r") as f: # define the first block: # ----------------------- @@ -1302,19 +1321,19 @@ def replace_tab(l, cln, preserve=False, ts=8): cln += 1 # kw = l.lower().split()[0] kw = l.lstrip() - if 'message:' == kw[:8].lower(): + if "message:" == kw[:8].lower(): # read message block right here res = [] while not is_blankline(l): res.append(l) l = replace_tab(next(f), cln, preserve=preservetabs) cln += 1 - yield _yield(res, CID.message, cln-1) # message card - yield _yield(l, CID.blankline, cln) # blank line + yield _yield(res, CID.message, cln - 1) # message card + yield _yield(l, CID.blankline, cln) # blank line l = replace_tab(next(f), cln, preserve=preservetabs) cln += 1 ncid = CID.title - elif 'continue' == kw[:8].lower(): + elif "continue" == kw[:8].lower(): # input file for continue job. Contains only data block. ncid = CID.data else: @@ -1365,13 +1384,13 @@ def replace_tab(l, cln, preserve=False, ts=8): card = [] if ncid == 6: break - elif l[0:5] == ' ' or cf: + elif l[0:5] == " " or cf: # l is continuation line. if cmnt: card += cmnt # prev. comment lines belong to this card. cmnt = [] card.append(l) - cf = l[:index_(l)].find('&', 0, 81) > -1 + cf = l[: index_(l)].find("&", 0, 81) > -1 elif is_commented(l): # l is a line comment. Where it belongs (to the current card or # to the next one), depends on the next line, therefore, just @@ -1388,7 +1407,7 @@ def replace_tab(l, cln, preserve=False, ts=8): card = [l] # if tally comment card, i.e. started with fc, the & character # does not mean continuation. - cf = not is_fc_card(l) and l[:index_(l)].find('&', 0, 81) > -1 + cf = not is_fc_card(l) and l[: index_(l)].find("&", 0, 81) > -1 if card: yield _yield(card, ncid, cln - len(card) - len(cmnt)) if cmnt: @@ -1402,7 +1421,7 @@ def get_blocks(cards): d = {} cbt = None # current block type - cbc = [] # current block cards + cbc = [] # current block cards for c in cards: if c.ctype == CID.blankline: d[cbt] = cbc @@ -1419,17 +1438,17 @@ def get_blocks(cards): return d -def are_close_vals(x, y, re=1e-6, ra=0.): +def are_close_vals(x, y, re=1e-6, ra=0.0): """ Return True if x and y are closer then re or ra. """ if abs(x - y) <= ra: r = True elif x != 0: - r = abs((x - y)/x) <= re + r = abs((x - y) / x) <= re else: # y is not equal to x and x is 0 -> y is not 0. - r = abs((x - y)/y) <= re + r = abs((x - y) / y) <= re return r @@ -1439,7 +1458,7 @@ def are_close_lists(x, y, re=1e-6, pci=[]): """ if len(x) != len(y): res = False - msg = 'Different length' + msg = "Different length" if x == y: return True @@ -1456,7 +1475,7 @@ def are_close_lists(x, y, re=1e-6, pci=[]): else: if len(pci) % 2 == 1: # augment with len(x) +1 - pci = tuple(pci) + (len(x) + 1, ) + pci = tuple(pci) + (len(x) + 1,) xe = [] ye = [] xp = [] @@ -1473,7 +1492,7 @@ def are_close_lists(x, y, re=1e-6, pci=[]): xpn = sum([e**2 for e in xp]) ypn = sum([e**2 for e in yp]) if xpn > 0 and ypn > 0: - yp = [e*xpn/ypn for e in yp] + yp = [e * xpn / ypn for e in yp] msg = [] res = [] @@ -1481,16 +1500,16 @@ def are_close_lists(x, y, re=1e-6, pci=[]): # compare xl and yl without normalization if xl == yl: res.append(True) - msg.append('exact match') + msg.append("exact match") else: n = 0 for xx, yy in zip(xl, yl): r = are_close_vals(xx, yy, re) if not r: - m = 'diff at {}'.format(n) + m = "diff at {}".format(n) break else: - m = 'all elements are close or equal' + m = "all elements are close or equal" r = True res.append(r) msg.append(m) @@ -1504,5 +1523,5 @@ def are_close_lists(x, y, re=1e-6, pci=[]): return result -if __name__ == '__main__': +if __name__ == "__main__": pass diff --git a/src/geouned/GEOReverse/Modules/Utils/BooleanSolids.py b/src/geouned/GEOReverse/Modules/Utils/BooleanSolids.py index 2fcf28f2..49c0761a 100644 --- a/src/geouned/GEOReverse/Modules/Utils/BooleanSolids.py +++ b/src/geouned/GEOReverse/Modules/Utils/BooleanSolids.py @@ -1,5 +1,5 @@ # -# Conversion to MCNP v0.0 +# Conversion to MCNP v0.0 # Only one solid and planar surfaces # import math @@ -9,497 +9,546 @@ from .booleanFunction import BoolSequence -BoolVals = (None,True,False) +BoolVals = (None, True, False) + class CTelement: - def __init__(self,val=None,S1=None,S2=None): - self.diagonal = False - self.S1 = S1 - self.S2 = S2 - if val is None : - self.val = None - else: - if type(val) is int : - self.diagonal = True - self.type = None - else: - self.type = val.count(0) - self.val = val - - def getTranspose(self): - if self.diagonal : return self.val - return CTelement((self.val[0],self.val[3],self.val[2],self.val[1]),self.S2,self.S1) - - def getDependence(self): - if self.diagonal : - if self.val == 0 : return True,False - elif self.val == -1 : return 'Null',False - else : return True,'Null' - - Ones = sum(self.val) - if Ones == 4 : return None,None - elif Ones == 3 : - ind = self.val.index(0) - if ind == 0 : return False,None - elif ind == 1 : return True ,None - elif ind == 2 : return None ,True - else : return None ,False - elif Ones == 2 : - ind1 = self.val.index(0) - ind2 = self.val.index(0,ind1+1) - if ind1 == 0 and ind2 == 1 : return 'Null',None - elif ind1 == 2 and ind2 == 3 : return None ,'Null' - elif ind1 == 0 and ind2 == 3 : return False,False - else : return True ,True - elif Ones == 1 : - ind = self.val.index(1) - if ind == 0 : return True ,'Null' - elif ind == 1 : return False,'Null' - elif ind == 2 : return 'Null',False - else : return 'Null',True - else: - return 'Null','Null' - + def __init__(self, val=None, S1=None, S2=None): + self.diagonal = False + self.S1 = S1 + self.S2 = S2 + if val is None: + self.val = None + else: + if type(val) is int: + self.diagonal = True + self.type = None + else: + self.type = val.count(0) + self.val = val + + def getTranspose(self): + if self.diagonal: + return self.val + return CTelement( + (self.val[0], self.val[3], self.val[2], self.val[1]), self.S2, self.S1 + ) + + def getDependence(self): + if self.diagonal: + if self.val == 0: + return True, False + elif self.val == -1: + return "Null", False + else: + return True, "Null" + + Ones = sum(self.val) + if Ones == 4: + return None, None + elif Ones == 3: + ind = self.val.index(0) + if ind == 0: + return False, None + elif ind == 1: + return True, None + elif ind == 2: + return None, True + else: + return None, False + elif Ones == 2: + ind1 = self.val.index(0) + ind2 = self.val.index(0, ind1 + 1) + if ind1 == 0 and ind2 == 1: + return "Null", None + elif ind1 == 2 and ind2 == 3: + return None, "Null" + elif ind1 == 0 and ind2 == 3: + return False, False + else: + return True, True + elif Ones == 1: + ind = self.val.index(1) + if ind == 0: + return True, "Null" + elif ind == 1: + return False, "Null" + elif ind == 2: + return "Null", False + else: + return "Null", True + else: + return "Null", "Null" + class ConstraintTable(dict): - def __init__(self): - self.diagonal = None - - def __str__(self): - - varName = list(self.keys()) - - # Constraint Table only diagonal terms - if len(self[varName[0]]) == 1 : - line = '' - for name in varName : - element = self[name][name] - line += ' {:4d} : {}\n'.format(name,element.val) - return line - - outstr = ' ' - for name in varName : - outstr = outstr + ' {:3d}'.format(name) - outstr = outstr + '\n' - - for name1 in varName : - line = ' {:3d} '.format(name1) - linenot = '~{:3d} '.format(name1) - for name2 in varName: - elmt = self[name1][name2] - if elmt.diagonal : - line += ' {:>2d} '.format(elmt.val) - linenot += ' ' - else: - line += ' {}{} '.format(elmt.val[0],elmt.val[1]) - linenot += ' {}{} '.format(elmt.val[3],elmt.val[2]) - outstr += line +'\n' - outstr += linenot+'\n' - return outstr - - def addElement(self,k1,k2,val): - - if k1 in self.keys(): - self[k1][k2] = val - else: - self[k1] = {k2:val} - - def fillMissingElements(self): - keys = list(self.keys()) - missing = [] - for i,k1 in enumerate(keys): - for k2 in keys[i+1:]: - if k2 in self[k1].keys(): - elmt = self[k1][k2] - self[k2][k1] = elmt.getTranspose() - else: - missing.append((k1,k2)) - - - for k1,k2 in missing: - diag1 = self[k1][k1] - diag2 = self[k2][k2] - new = combineDiagElements (diag1,diag2) - new.S1 = k1 - new.S2 = k2 - self[k1][k2] = new - self[k2][k1] = new.getTranspose() - - def getOutSurfaces(self): - out = [] - for k in self.keys(): - if self[k][k].val != 0 : out.append(k) - return out - - def getConstraintSet(self,valname): - trueSet = {} - falseSet = {} - TNull = False - FNull = False - for k in self.keys(): - TValue,FValue = self[valname][k].getDependence() - if TValue == 'Null' : - TNull = True - TValue = None - if FValue == 'Null' : - FNull = True - FValue = None - if TValue is not None : trueSet[k] = TValue - if FValue is not None : falseSet[k] = FValue - - if TNull : trueSet = None - if FNull : falseSet = None - return trueSet,falseSet - - def solidInBox(self,Seq): # Sequence of the cell - surfs = Seq.getSurfacesNumbers() - if self.diagonal : - seqValues = dict() - for s in surfs : - seqValues[s] = BoolVals[self[s][s].val] - # if evaluate None : Box intersection Cell != 0 Part of the cell in the box - # True : Box intersection Cell == Box Cell cover the full region of the box. Void cell doesn't exist - # False : Box intersection Cell == 0 Cell out of the box - return Seq.evaluate(seqValues) - - else: - trueSet,falseSet = self.getConstraintSet(surfs[0]) - if trueSet is not None: - trueVal = Seq.evaluate(trueSet) - if trueVal is None : return None - if falseSet is not None: - falseVal = Seq.evaluate(falseSet) - if falseVal is None : return None # Part of the cell in the box - if trueVal == falseVal : return trueVal # True Cover full cell, False not in the box - else : return None # Part of the cell in the box - else: - return trueVal - elif falseSet is not None: - falseVal = Seq.evaluate(falseSet) - return falseVal - else: - print('Bad trouble surfaces {} is on none side of the box!!') - return False - - -def combineDiagElements(d1,d2): - - if d1.val == 0 and d2.val == 0 : return CTelement((1,1,1,1)) - elif d1.val == 1 and d2.val == 0 : return CTelement((1,1,0,0)) - elif d1.val ==-1 and d2.val == 0 : return CTelement((0,0,1,1)) - elif d1.val == 0 and d2.val == 1 : return CTelement((1,0,0,1)) - elif d1.val == 0 and d2.val ==-1 : return CTelement((0,1,1,0)) - elif d1.val == 1 and d2.val == 1 : return CTelement((1,0,0,0)) - elif d1.val == 1 and d2.val ==-1 : return CTelement((0,1,0,0)) - elif d1.val ==-1 and d2.val == 1 : return CTelement((0,0,0,1)) - elif d1.val ==-1 and d2.val ==-1 : return CTelement((0,0,1,0)) - -def buildCTableFromSolids(Box,SurfInfo,option='diag'): - - if type(SurfInfo) is dict : - surfaces = SurfInfo - surfaceList = tuple(surfaces.keys()) - elif type(SurfInfo) is tuple : - surfaceList,surfaces = SurfInfo - else: - surfaces = SurfInfo.surfaces - surfaceList = SurfInfo.surfaceList - - outSurfaces=[] - for s in surfaceList: surfaces[s].buildShape(Box.BoundBox) - - CTable = ConstraintTable() - if option == 'diag': + def __init__(self): + self.diagonal = None + + def __str__(self): + + varName = list(self.keys()) + + # Constraint Table only diagonal terms + if len(self[varName[0]]) == 1: + line = "" + for name in varName: + element = self[name][name] + line += " {:4d} : {}\n".format(name, element.val) + return line + + outstr = " " + for name in varName: + outstr = outstr + " {:3d}".format(name) + outstr = outstr + "\n" + + for name1 in varName: + line = " {:3d} ".format(name1) + linenot = "~{:3d} ".format(name1) + for name2 in varName: + elmt = self[name1][name2] + if elmt.diagonal: + line += " {:>2d} ".format(elmt.val) + linenot += " " + else: + line += " {}{} ".format(elmt.val[0], elmt.val[1]) + linenot += " {}{} ".format(elmt.val[3], elmt.val[2]) + outstr += line + "\n" + outstr += linenot + "\n" + return outstr + + def addElement(self, k1, k2, val): + + if k1 in self.keys(): + self[k1][k2] = val + else: + self[k1] = {k2: val} + + def fillMissingElements(self): + keys = list(self.keys()) + missing = [] + for i, k1 in enumerate(keys): + for k2 in keys[i + 1 :]: + if k2 in self[k1].keys(): + elmt = self[k1][k2] + self[k2][k1] = elmt.getTranspose() + else: + missing.append((k1, k2)) + + for k1, k2 in missing: + diag1 = self[k1][k1] + diag2 = self[k2][k2] + new = combineDiagElements(diag1, diag2) + new.S1 = k1 + new.S2 = k2 + self[k1][k2] = new + self[k2][k1] = new.getTranspose() + + def getOutSurfaces(self): + out = [] + for k in self.keys(): + if self[k][k].val != 0: + out.append(k) + return out + + def getConstraintSet(self, valname): + trueSet = {} + falseSet = {} + TNull = False + FNull = False + for k in self.keys(): + TValue, FValue = self[valname][k].getDependence() + if TValue == "Null": + TNull = True + TValue = None + if FValue == "Null": + FNull = True + FValue = None + if TValue is not None: + trueSet[k] = TValue + if FValue is not None: + falseSet[k] = FValue + + if TNull: + trueSet = None + if FNull: + falseSet = None + return trueSet, falseSet + + def solidInBox(self, Seq): # Sequence of the cell + surfs = Seq.getSurfacesNumbers() + if self.diagonal: + seqValues = dict() + for s in surfs: + seqValues[s] = BoolVals[self[s][s].val] + # if evaluate None : Box intersection Cell != 0 Part of the cell in the box + # True : Box intersection Cell == Box Cell cover the full region of the box. Void cell doesn't exist + # False : Box intersection Cell == 0 Cell out of the box + return Seq.evaluate(seqValues) + + else: + trueSet, falseSet = self.getConstraintSet(surfs[0]) + if trueSet is not None: + trueVal = Seq.evaluate(trueSet) + if trueVal is None: + return None + if falseSet is not None: + falseVal = Seq.evaluate(falseSet) + if falseVal is None: + return None # Part of the cell in the box + if trueVal == falseVal: + return trueVal # True Cover full cell, False not in the box + else: + return None # Part of the cell in the box + else: + return trueVal + elif falseSet is not None: + falseVal = Seq.evaluate(falseSet) + return falseVal + else: + print("Bad trouble surfaces {} is on none side of the box!!") + return False + + +def combineDiagElements(d1, d2): + + if d1.val == 0 and d2.val == 0: + return CTelement((1, 1, 1, 1)) + elif d1.val == 1 and d2.val == 0: + return CTelement((1, 1, 0, 0)) + elif d1.val == -1 and d2.val == 0: + return CTelement((0, 0, 1, 1)) + elif d1.val == 0 and d2.val == 1: + return CTelement((1, 0, 0, 1)) + elif d1.val == 0 and d2.val == -1: + return CTelement((0, 1, 1, 0)) + elif d1.val == 1 and d2.val == 1: + return CTelement((1, 0, 0, 0)) + elif d1.val == 1 and d2.val == -1: + return CTelement((0, 1, 0, 0)) + elif d1.val == -1 and d2.val == 1: + return CTelement((0, 0, 0, 1)) + elif d1.val == -1 and d2.val == -1: + return CTelement((0, 0, 1, 0)) + + +def buildCTableFromSolids(Box, SurfInfo, option="diag"): + + if type(SurfInfo) is dict: + surfaces = SurfInfo + surfaceList = tuple(surfaces.keys()) + elif type(SurfInfo) is tuple: + surfaceList, surfaces = SurfInfo + else: + surfaces = SurfInfo.surfaces + surfaceList = SurfInfo.surfaceList + + outSurfaces = [] + for s in surfaceList: + surfaces[s].buildShape(Box.BoundBox) + + CTable = ConstraintTable() + if option == "diag": CTable.diagonal = True - else: + else: CTable.diagonal = False - for i,s1 in enumerate(surfaceList): - res,splitRegions = splitSolid_fast(Box,surfaces[s1],True) - #res,splitRegions = splitSolid_fast(Box,Surfaces.getSurface(s1),True) - - CTable.addElement(s1,s1,CTelement(res,s1,s1)) - if option == 'diag' :continue - if splitRegions is None : continue # loop, no region to be split by s2 - for j,s2 in enumerate(surfaceList[i+1:]) : - posS1,negS1 = splitRegions + for i, s1 in enumerate(surfaceList): + res, splitRegions = splitSolid_fast(Box, surfaces[s1], True) + # res,splitRegions = splitSolid_fast(Box,Surfaces.getSurface(s1),True) + + CTable.addElement(s1, s1, CTelement(res, s1, s1)) + if option == "diag": + continue + if splitRegions is None: + continue # loop, no region to be split by s2 + for j, s2 in enumerate(surfaceList[i + 1 :]): + posS1, negS1 = splitRegions pos0 = None - for solid in posS1 : - - pos = splitSolid_fast(solid,surfaces[s2],False) - - #pos = splitSolid_fast(solid,Surfaces.getSurface(s2),False) - if pos == (1,1) : break # s2 intersect S1 Region - if pos0 is None : - pos0 = pos + for solid in posS1: + + pos = splitSolid_fast(solid, surfaces[s2], False) + + # pos = splitSolid_fast(solid,Surfaces.getSurface(s2),False) + if pos == (1, 1): + break # s2 intersect S1 Region + if pos0 is None: + pos0 = pos else: - if pos != pos0 : # s1 regions are on both side of s2 - pos = (1,1) - break - + if pos != pos0: # s1 regions are on both side of s2 + pos = (1, 1) + break + neg0 = None - for solid in negS1 : - #neg = splitSolid_fast(solid,Surfaces.getSurface(s2),False) - neg = splitSolid_fast(solid,surfaces[s2],False) - if neg == (1,1) : break # s2 intersect S1 Region - if neg0 is None : - neg0 = neg + for solid in negS1: + # neg = splitSolid_fast(solid,Surfaces.getSurface(s2),False) + neg = splitSolid_fast(solid, surfaces[s2], False) + if neg == (1, 1): + break # s2 intersect S1 Region + if neg0 is None: + neg0 = neg else: - if neg != neg0 : # s1 regions are on both side of s2 - neg = (1,1) - break - - val = (pos[0],pos[1],neg[1],neg[0]) - CTable.addElement(s1,s2,CTelement(val,s1,s2)) + if neg != neg0: # s1 regions are on both side of s2 + neg = (1, 1) + break + val = (pos[0], pos[1], neg[1], neg[0]) + CTable.addElement(s1, s2, CTelement(val, s1, s2)) - # if some surfaces don't cross the box some elements in Constraint table are not filled - if option != 'diag' : CTable.fillMissingElements() - return CTable + # if some surfaces don't cross the box some elements in Constraint table are not filled + if option != "diag": + CTable.fillMissingElements() + return CTable -def removeExtraSurfaces(CellSeq,CTable): +def removeExtraSurfaces(CellSeq, CTable): # checking is make on solid cell definition to be removed from void cell outSurfaces = set(CTable.getOutSurfaces()) changed = False - newDef = BoolSequence(operator='OR') - - #Loop over all compound solids of the metaSolid - if CellSeq.level == 0 : - newSeq = BoolSequence(operator='AND') + newDef = BoolSequence(operator="OR") + + # Loop over all compound solids of the metaSolid + if CellSeq.level == 0: + newSeq = BoolSequence(operator="AND") newSeq.append(CellSeq.copy()) CellSeq.assign(newSeq) for subCell in CellSeq.elements: - nullcell = False + nullcell = False chk = subCell.check() - if chk == False : # the cell doesn't exist - nullcell = True - elif chk == True : # the cell describe the full universe - newDef.elements = True - newDef.level = 0 - return newDef - - #if subcell has finite volume check it intersection with the box - if not nullcell : - res = CTable.solidInBox(subCell) - if res == None : + if chk == False: # the cell doesn't exist + nullcell = True + elif chk == True: # the cell describe the full universe + newDef.elements = True + newDef.level = 0 + return newDef + + # if subcell has finite volume check it intersection with the box + if not nullcell: + res = CTable.solidInBox(subCell) + if res == None: # subcell intersect the box # get the surfaces of the solids out of the box # get reduced definition removeSurf = outSurfaces & set(subCell.getSurfacesNumbers()) for s in removeSurf: - val = True if CTable[s][s].val > 0 else False - subCell.substitute(s,val) - if type(subCell.elements) is bool : - if subCell.elements == False : # cell does not intersect void box - continue - else: # cell cover fully void box - newDef.elements = True - newDef.level = 0 - return newDef + val = True if CTable[s][s].val > 0 else False + subCell.substitute(s, val) + if type(subCell.elements) is bool: + if subCell.elements == False: # cell does not intersect void box + continue + else: # cell cover fully void box + newDef.elements = True + newDef.level = 0 + return newDef else: - newDef.append(subCell) + newDef.append(subCell) - elif res == True : - # subcell cover the full box region Void cell doesn't exist - newDef.elements = True - newDef.level = 0 - return newDef + elif res == True: + # subcell cover the full box region Void cell doesn't exist + newDef.elements = True + newDef.level = 0 + return newDef newDef.clean() - return newDef - - -def splitSolid_fast(solid,surf,box): - - if box : - if surf.shape : - comsolid = BOPTools.SplitAPI.slice(solid,[surf.shape],'Split', tolerance = 0) - else: - return checkSign(solid,surf),None - - if len(comsolid.Solids) <= 1 : - return checkSign(solid,surf),None - # sgn = checkSign(solid,surf) # if "box" and single object => the box is not split, surface s1 out of the box. - # if sgn == 1 : # The sign is the side of surface s1 where the box is located - # # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 - # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 - # else: - # return ((0,0),(0,1)),None - - else: - posSol = [] - negSol = [] - for s in comsolid.Solids: - sgn = checkSign(s,surf) - if sgn == 1: - posSol.append(s) - else: - negSol.append(s) - return 0, (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 - #return ((1,0),(0,1)), (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 + return newDef + + +def splitSolid_fast(solid, surf, box): + + if box: + if surf.shape: + comsolid = BOPTools.SplitAPI.slice( + solid, [surf.shape], "Split", tolerance=0 + ) + else: + return checkSign(solid, surf), None + + if len(comsolid.Solids) <= 1: + return checkSign(solid, surf), None + # sgn = checkSign(solid,surf) # if "box" and single object => the box is not split, surface s1 out of the box. + # if sgn == 1 : # The sign is the side of surface s1 where the box is located + # # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 + # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 + # else: + # return ((0,0),(0,1)),None + + else: + posSol = [] + negSol = [] + for s in comsolid.Solids: + sgn = checkSign(s, surf) + if sgn == 1: + posSol.append(s) + else: + negSol.append(s) + return 0, ( + posSol, + negSol, + ) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 + # return ((1,0),(0,1)), (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 else: - # "not box" => return the position of the +/- region of s1 (the solid) with respect s2 - if surf.shape : - dist = solid.distToShape(surf.shape)[0] - else: - dist = 1. - if dist > 1e-6 : # face doesn't intersect solid - sgn = checkSign(solid,surf) - if sgn == 1: - return (1,0) # values of s2 and -s2 "0" means this region doesn't exist - else: - return (0,1) - else: - return (1,1) # values of s2 and -s2 - - - - + # "not box" => return the position of the +/- region of s1 (the solid) with respect s2 + if surf.shape: + dist = solid.distToShape(surf.shape)[0] + else: + dist = 1.0 + if dist > 1e-6: # face doesn't intersect solid + sgn = checkSign(solid, surf) + if sgn == 1: + return ( + 1, + 0, + ) # values of s2 and -s2 "0" means this region doesn't exist + else: + return (0, 1) + else: + return (1, 1) # values of s2 and -s2 + + # find one point inside a solid (region) def point_inside(solid): - point = solid.CenterOfMass - if solid.isInside(point,0.0,False) : return point + point = solid.CenterOfMass + if solid.isInside(point, 0.0, False): + return point + + cut_line = 32 + cut_box = 4 - cut_line = 32 - cut_box = 4 + v1 = solid.Vertexes[0].Point + for vi in range(len(solid.Vertexes) - 1, 0, -1): + v2 = solid.Vertexes[vi].Point + dv = (v2 - v1) * 0.5 - v1=solid.Vertexes[0].Point - for vi in range(len(solid.Vertexes)-1,0,-1): - v2=solid.Vertexes[vi].Point - dv= (v2-v1)*0.5 - - n=1 + n = 1 while True: - for i in range(n): - point = v1 + dv *(1 + 0.5*i) - if solid.isInside(point,0.0,False) : return point - n=n*2 - dv=dv*0.5 - if (n > cut_line ) : - break - - BBox = solid.optimalBoundingBox(False) - box = [BBox.XMin,BBox.XMax, - BBox.YMin,BBox.YMax, - BBox.ZMin,BBox.ZMax ] - - boxes,centers = CutBox(box) - n = 0 - - while True : - for p in centers : - pp = FreeCAD.Vector(p[0],p[1],p[2]) - if solid.isInside(pp,0.0,False) : return pp - - subbox = [] - centers = [] - for b in boxes : - btab,ctab = CutBox(b) + for i in range(n): + point = v1 + dv * (1 + 0.5 * i) + if solid.isInside(point, 0.0, False): + return point + n = n * 2 + dv = dv * 0.5 + if n > cut_line: + break + + BBox = solid.optimalBoundingBox(False) + box = [BBox.XMin, BBox.XMax, BBox.YMin, BBox.YMax, BBox.ZMin, BBox.ZMax] + + boxes, centers = CutBox(box) + n = 0 + + while True: + for p in centers: + pp = FreeCAD.Vector(p[0], p[1], p[2]) + if solid.isInside(pp, 0.0, False): + return pp + + subbox = [] + centers = [] + for b in boxes: + btab, ctab = CutBox(b) subbox.extend(btab) centers.extend(ctab) - boxes = subbox - n = n + 1 + boxes = subbox + n = n + 1 + + if n == cut_box: + print("Solid not found in bounding Box (Volume : {})".format(solid.Volume)) + return None - if (n == cut_box ) : - print('Solid not found in bounding Box (Volume : {})'.format(solid.Volume)) - return None # divide a box into 8 smaller boxes def CutBox(Box): - xmid = (Box[1]+Box[0])*0.5 - ymid = (Box[3]+Box[2])*0.5 - zmid = (Box[5]+Box[4])*0.5 - - - b1 = (Box[0],xmid,Box[2],ymid,Box[4],zmid) - p1 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b2 = (xmid,Box[1],Box[2],ymid,Box[4],zmid) - p2 = (0.5*(xmid+Box[1]), 0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b3 = (Box[0],xmid,ymid,Box[3],Box[4],zmid) - p3 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b4 = (xmid,Box[1],ymid,Box[3],Box[4],zmid) - p4 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b5 = (Box[0],xmid,Box[2],ymid,zmid,Box[5]) - p5 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b6 = (xmid,Box[1],Box[2],ymid,zmid,Box[5]) - p6 = (0.5*(xmid+Box[1]),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b7 = (Box[0],xmid,ymid,Box[3],zmid,Box[5]) - p7 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - b8 = (xmid,Box[1],ymid,Box[3],zmid,Box[5]) - p8 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - return (b1,b2,b3,b4,b5,b6,b7,b8),(p1,p2,p3,p4,p5,p6,p7,p8) - - -def checkSign(solid,surf): - - point = point_inside(solid) - - if surf.type == 'plane': - normal,d = surf.params - r = point - d*normal - if normal.dot(r) > 0 : - return 1 - else: - return -1 - - elif surf.type == 'cylinder': - center,axis,radius = surf.params - r = point - center - L2 = r.Length*r.Length - z = axis.dot(r) - z2 = z*z - R2 = radius*radius - if L2-z2 > R2 : - return 1 - else: - return -1 - - elif surf.type == 'sphere': - center,radius = surf.params - r = point - center - if r.Length > radius : - return 1 - else: - return -1 - - elif surf.type == 'cone': - apex,axis,t,dbl = surf.params - r = point - apex - r.normalize() - z = round(axis.dot(r),15) - alpha = math.acos(z) - - if alpha > math.atan(t) : - return 1 - else: - return -1 - - elif surf.type == 'torus': - center,axis,Ra,R = surf.params - r = point - center - v = axis.cross(r) - if v.Length > 1e-8 : - v.normalize() - t = v.cross(axis) - r = r + t * Ra - if r.Length > R: - return 1 - else: - return -1 - + xmid = (Box[1] + Box[0]) * 0.5 + ymid = (Box[3] + Box[2]) * 0.5 + zmid = (Box[5] + Box[4]) * 0.5 + + b1 = (Box[0], xmid, Box[2], ymid, Box[4], zmid) + p1 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b2 = (xmid, Box[1], Box[2], ymid, Box[4], zmid) + p2 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b3 = (Box[0], xmid, ymid, Box[3], Box[4], zmid) + p3 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b4 = (xmid, Box[1], ymid, Box[3], Box[4], zmid) + p4 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b5 = (Box[0], xmid, Box[2], ymid, zmid, Box[5]) + p5 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b6 = (xmid, Box[1], Box[2], ymid, zmid, Box[5]) + p6 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b7 = (Box[0], xmid, ymid, Box[3], zmid, Box[5]) + p7 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + + b8 = (xmid, Box[1], ymid, Box[3], zmid, Box[5]) + p8 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + + return (b1, b2, b3, b4, b5, b6, b7, b8), (p1, p2, p3, p4, p5, p6, p7, p8) + + +def checkSign(solid, surf): + + point = point_inside(solid) + + if surf.type == "plane": + normal, d = surf.params + r = point - d * normal + if normal.dot(r) > 0: + return 1 + else: + return -1 + + elif surf.type == "cylinder": + center, axis, radius = surf.params + r = point - center + L2 = r.Length * r.Length + z = axis.dot(r) + z2 = z * z + R2 = radius * radius + if L2 - z2 > R2: + return 1 + else: + return -1 + + elif surf.type == "sphere": + center, radius = surf.params + r = point - center + if r.Length > radius: + return 1 + else: + return -1 + + elif surf.type == "cone": + apex, axis, t, dbl = surf.params + r = point - apex + r.normalize() + z = round(axis.dot(r), 15) + alpha = math.acos(z) + + if alpha > math.atan(t): + return 1 + else: + return -1 + + elif surf.type == "torus": + center, axis, Ra, R = surf.params + r = point - center + v = axis.cross(r) + if v.Length > 1e-8: + v.normalize() + t = v.cross(axis) + r = r + t * Ra + if r.Length > R: + return 1 + else: + return -1 diff --git a/src/geouned/GEOReverse/Modules/Utils/booleanFunction.py b/src/geouned/GEOReverse/Modules/Utils/booleanFunction.py index fd2d944b..e9382230 100644 --- a/src/geouned/GEOReverse/Modules/Utils/booleanFunction.py +++ b/src/geouned/GEOReverse/Modules/Utils/booleanFunction.py @@ -1,601 +1,652 @@ import re -mostinner=re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses -number =re.compile(r"(?P[-+]?\d+)") -mix =re.compile(r"(?P([-+]?\d+|\[0+\]))") -TFX =re.compile(r"(?P[FTXo]+)") -PValue =re.compile(r"P\d+") -NValue =re.compile(r"N\d+") -conversion = {'T':True,'F':False,'X':None} +mostinner = re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses +number = re.compile(r"(?P[-+]?\d+)") +mix = re.compile(r"(?P([-+]?\d+|\[0+\]))") +TFX = re.compile(r"(?P[FTXo]+)") +PValue = re.compile(r"P\d+") +NValue = re.compile(r"N\d+") +conversion = {"T": True, "F": False, "X": None} + class BoolSequence: - def __init__(self,definition=None,operator=None) : - if definition : + def __init__(self, definition=None, operator=None): + if definition: self.elements = [] self.setDef(definition) - else: + else: self.elements = [] self.operator = operator - self.level = 0 + self.level = 0 def __str__(self): - out='{}['.format(self.operator) - if type(self.elements) is bool : return ' True ' if self.elements else ' False ' - for e in self.elements: - if type(e) is int or type(e) is bool or type(e) is str : - out += ' {} '.format(e) - else : - out += e.__str__() - - out += '] ' - return out - - def append(self,*seq): - for s in seq: - if type(s) is int : - level = -1 - else: - level = s.level - if type(s.elements) is bool: - if self.operator == 'AND' and s.elements == False or\ - self.operator == 'OR' and s.elements == True : - self.level = 0 - self.elements = s.elements - return - else: - continue - - self.elements.append(s) - self.level = max(self.level,level+1) - - def assign(self,Seq): + out = "{}[".format(self.operator) + if type(self.elements) is bool: + return " True " if self.elements else " False " + for e in self.elements: + if type(e) is int or type(e) is bool or type(e) is str: + out += " {} ".format(e) + else: + out += e.__str__() + + out += "] " + return out + + def append(self, *seq): + for s in seq: + if type(s) is int: + level = -1 + else: + level = s.level + if type(s.elements) is bool: + if ( + self.operator == "AND" + and s.elements == False + or self.operator == "OR" + and s.elements == True + ): + self.level = 0 + self.elements = s.elements + return + else: + continue + + self.elements.append(s) + self.level = max(self.level, level + 1) + + def assign(self, Seq): self.operator = Seq.operator self.elements = Seq.elements - self.level = Seq.level + self.level = Seq.level def copy(self): cp = BoolSequence() - cp.operator= self.operator + cp.operator = self.operator cp.level = self.level if type(self.elements) is bool: - cp.elements = self.elements + cp.elements = self.elements else: - for e in self.elements: - if type(e) is int : - cp.elements.append(e) - else: - cp.elements.append(e.copy()) - return cp - + for e in self.elements: + if type(e) is int: + cp.elements.append(e) + else: + cp.elements.append(e.copy()) + return cp + def getComplementary(self): - c = BoolSequence(operator=self.compOperator()) - c.level = self.level + c = BoolSequence(operator=self.compOperator()) + c.level = self.level - if self.level == 0: - for e in self.elements: - c.elements.append(-e) - return c - else: - self.groupSingle() - for e in self.elements: - c.elements.append( e.getComplementary() ) - return c + if self.level == 0: + for e in self.elements: + c.elements.append(-e) + return c + else: + self.groupSingle() + for e in self.elements: + c.elements.append(e.getComplementary()) + return c - def compOperator(self): - if self.operator == 'AND': - return 'OR' - else: - return 'AND' - - - def simplify(self,CT,loop=0): - surfNames = self.getSurfacesNumbers() - if not surfNames : return - # print(CT) - # print('start',self) - newNames = surfNames - simplified = False - for valname in surfNames: - # print('factorise',valname) - if valname in newNames: - chg = self.factorize(valname,CT) - simplified = simplified or chg - newNames = self.getSurfacesNumbers() - self.joinOperators() - - if self.level == 0 or (self.elements) is bool : return - - # new temp para ver como va - #for e in self.elements: - # if type(e) is not int: - # e.simplify(CT) - #return - # end new - - - if loop == 0: - ANDSeq = BoolSequence(operator=self.operator) - ORSeq = BoolSequence(operator=self.operator) - for e in self.elements: - if e.operator == 'AND': - ANDSeq.append(e) - else: - ORSeq.append(e) - - ANDSeq.simplify(CT,loop=1) - ORSeq.simplify(CT,loop=1) - newSeq = BoolSequence(operator=self.operator) - if ANDSeq.elements: newSeq.append(ANDSeq) - if ORSeq.elements : newSeq.append(ORSeq) - newSeq.joinOperators() - self.assign(newSeq) - else: - for e in reversed(self.elements): - e.simplify(CT,loop=0) - if type(e.elements) is bool: - if self.operator == 'AND' and e.elements == False or \ - self.operator == 'OR' and e.elements == True : - self.elements = e.elements - self.level = 0 - break - else: - self.elements.remove(e) - - if self.elements == []: - self.level = 0 - if self.operator == 'AND' : - self.elements = True - else: - self.elements = False + if self.operator == "AND": + return "OR" + else: + return "AND" + + def simplify(self, CT, loop=0): + surfNames = self.getSurfacesNumbers() + if not surfNames: + return + # print(CT) + # print('start',self) + newNames = surfNames + simplified = False + for valname in surfNames: + # print('factorise',valname) + if valname in newNames: + chg = self.factorize(valname, CT) + simplified = simplified or chg + newNames = self.getSurfacesNumbers() + self.joinOperators() + + if self.level == 0 or (self.elements) is bool: + return + + # new temp para ver como va + # for e in self.elements: + # if type(e) is not int: + # e.simplify(CT) + # return + # end new + + if loop == 0: + ANDSeq = BoolSequence(operator=self.operator) + ORSeq = BoolSequence(operator=self.operator) + for e in self.elements: + if e.operator == "AND": + ANDSeq.append(e) + else: + ORSeq.append(e) + + ANDSeq.simplify(CT, loop=1) + ORSeq.simplify(CT, loop=1) + newSeq = BoolSequence(operator=self.operator) + if ANDSeq.elements: + newSeq.append(ANDSeq) + if ORSeq.elements: + newSeq.append(ORSeq) + newSeq.joinOperators() + self.assign(newSeq) + else: + for e in reversed(self.elements): + e.simplify(CT, loop=0) + if type(e.elements) is bool: + if ( + self.operator == "AND" + and e.elements == False + or self.operator == "OR" + and e.elements == True + ): + self.elements = e.elements + self.level = 0 + break + else: + self.elements.remove(e) - # check if level 0 sequence have oposite value a & -a = 0 , a|-a = 1 - # return the value of the sequence None(unknown), True, False + if self.elements == []: + self.level = 0 + if self.operator == "AND": + self.elements = True + else: + self.elements = False + + # check if level 0 sequence have oposite value a & -a = 0 , a|-a = 1 + # return the value of the sequence None(unknown), True, False def check(self): - if self.level == 0: - if type(self.elements) is bool : return self.elements - - signedSurf = set(self.elements) - surfname = self.getSurfacesNumbers() - if len(signedSurf) == len(surfname) : return None # means same surface has not positive and negative value - elif self.operator == 'AND' : return False - else: return True - else: - if type(self.elements) is bool : return self.elements - - self.groupSingle() - noneVal = False - for e in self.elements: - res = e.check() - if res is None : noneVal = True - elif self.operator == 'AND' and res == False : return False - elif self.operator == 'OR' and res == True : return True - - if noneVal : return None - elif self.operator == 'AND' : return True - else: return False - - - def substitute(self,var,val): - if type(self.elements) is bool: return - name = abs(var) - ic = len(self.elements) - for e in reversed(self.elements): - ic -= 1 - if type(e) is int: - if abs(e) == name : - if type(val) is int : - if name == e : self.elements[ic] = val - else : self.elements[ic] = -val - - else : - if name == e : boolValue = val - else : boolValue = not val - - if self.operator == 'AND' and not boolValue : - self.elements = False - self.level = 0 - return - elif self.operator == 'OR' and boolValue : + if self.level == 0: + if type(self.elements) is bool: + return self.elements + + signedSurf = set(self.elements) + surfname = self.getSurfacesNumbers() + if len(signedSurf) == len(surfname): + return None # means same surface has not positive and negative value + elif self.operator == "AND": + return False + else: + return True + else: + if type(self.elements) is bool: + return self.elements + + self.groupSingle() + noneVal = False + for e in self.elements: + res = e.check() + if res is None: + noneVal = True + elif self.operator == "AND" and res == False: + return False + elif self.operator == "OR" and res == True: + return True + + if noneVal: + return None + elif self.operator == "AND": + return True + else: + return False + + def substitute(self, var, val): + if type(self.elements) is bool: + return + name = abs(var) + ic = len(self.elements) + for e in reversed(self.elements): + ic -= 1 + if type(e) is int: + if abs(e) == name: + if type(val) is int: + if name == e: + self.elements[ic] = val + else: + self.elements[ic] = -val + + else: + if name == e: + boolValue = val + else: + boolValue = not val + + if self.operator == "AND" and not boolValue: + self.elements = False + self.level = 0 + return + elif self.operator == "OR" and boolValue: + self.elements = True + self.level = 0 + return + else: + self.elements.remove(e) + else: + e.substitute(var, val) + + self.clean() + self.levelUpdate() + + def removeSurf(self, name): + if type(self.elements) is bool: + return + ic = len(self.elements) + for e in reversed(self.elements): + ic -= 1 + if type(e) is int: + if e == name: + if self.operator == "AND": + self.elements.remove(e) + elif self.operator == "OR": self.elements = True - self.level = 0 + self.level = 0 return - else: - self.elements.remove(e) - else: - e.substitute(var,val) - - self.clean() - self.levelUpdate() - - def removeSurf(self,name): - if type(self.elements) is bool: return - ic = len(self.elements) - for e in reversed(self.elements): - ic -= 1 - if type(e) is int: - if e == name : - if self.operator == 'AND' : - self.elements.remove(e) - elif self.operator == 'OR' : - self.elements = True - self.level = 0 - return - else: - e.removeSurf(name) - - self.clean() - self.levelUpdate() - + else: + e.removeSurf(name) + self.clean() + self.levelUpdate() # remove sequence whom elements are boolean values instead of list - def clean(self): - if type(self.elements) is bool : return self.elements - for e in reversed(self.elements) : - if type(e) is int : continue - eVal = e.clean() - if type(eVal) is bool: - if eVal and self.operator == 'OR' : - self.elements = True - self.level = 0 - return True - elif not eVal and self.operator == 'AND' : - self.elements = False - self.level = 0 - return False - self.elements.remove(e) - - if self.elements == [] : - if self.operator == 'OR' : self.elements = False - else : self.elements = True - self.level = 0 - return self.elements - else: - return None + def clean(self): + if type(self.elements) is bool: + return self.elements + for e in reversed(self.elements): + if type(e) is int: + continue + eVal = e.clean() + if type(eVal) is bool: + if eVal and self.operator == "OR": + self.elements = True + self.level = 0 + return True + elif not eVal and self.operator == "AND": + self.elements = False + self.level = 0 + return False + self.elements.remove(e) + if self.elements == []: + if self.operator == "OR": + self.elements = False + else: + self.elements = True + self.level = 0 + return self.elements + else: + return None # join redundant operators in sequence def joinOperators(self): - if self.level == 0 : return - if type(self.elements) is bool: return + if self.level == 0: + return + if type(self.elements) is bool: + return self.groupSingle() ANDop = [] - ORop = [] - + ORop = [] + for e in self.elements: - if e.operator == 'AND': ANDop.append(e) - else : ORop.append(e) - - if len(ANDop) > 1 and self.operator == 'AND': - newSeq = BoolSequence(operator='AND') - for s in ANDop : - newSeq.elements.extend(s.elements) - self.elements.remove(s) - newSeq.levelUpdate() - self.append(newSeq) - - - elif len(ORop) > 1 and self.operator == 'OR': - newSeq = BoolSequence(operator='OR') - for s in ORop : - newSeq.elements.extend(s.elements) - self.elements.remove(s) - newSeq.levelUpdate() - self.append(newSeq) - - if self.level > 0 and len(self.elements)==1 : - self.operator = self.elements[0].operator - self.elements = self.elements[0].elements - self.level -= 1 - self.joinOperators() - - if self.level == 0 : return + if e.operator == "AND": + ANDop.append(e) + else: + ORop.append(e) + + if len(ANDop) > 1 and self.operator == "AND": + newSeq = BoolSequence(operator="AND") + for s in ANDop: + newSeq.elements.extend(s.elements) + self.elements.remove(s) + newSeq.levelUpdate() + self.append(newSeq) + + elif len(ORop) > 1 and self.operator == "OR": + newSeq = BoolSequence(operator="OR") + for s in ORop: + newSeq.elements.extend(s.elements) + self.elements.remove(s) + newSeq.levelUpdate() + self.append(newSeq) + + if self.level > 0 and len(self.elements) == 1: + self.operator = self.elements[0].operator + self.elements = self.elements[0].elements + self.level -= 1 + self.joinOperators() + + if self.level == 0: + return for e in self.elements: - e.joinOperators() + e.joinOperators() + def factorize(self, valname, CT=None): + if CT is None: + trueSet = {abs(valname): True} + falseSet = {abs(valname): False} + else: + trueSet, falseSet = CT.getConstraintSet(valname) - def factorize(self,valname,CT=None): + if trueSet is None: + self.substitute(valname, False) + return True - if CT is None : - trueSet = {abs(valname) : True } - falseSet = {abs(valname) : False } - else: - trueSet,falseSet = CT.getConstraintSet(valname) - - if trueSet is None: - self.substitute(valname,False) - return True - - if falseSet is None: - self.substitute(valname,True) - return True - - funcVal = self.evaluate(trueSet,CT) - if funcVal == False : - newSeq = BoolSequence(operator='AND') - #self.substitute(valname,False) - for name,value in falseSet.items(): - self.substitute(name,value) - newSeq.append(-valname,self.copy()) + if falseSet is None: + self.substitute(valname, True) + return True + + funcVal = self.evaluate(trueSet, CT) + if funcVal == False: + newSeq = BoolSequence(operator="AND") + # self.substitute(valname,False) + for name, value in falseSet.items(): + self.substitute(name, value) + newSeq.append(-valname, self.copy()) self.assign(newSeq) return True elif funcVal == True: - newSeq = BoolSequence(operator='OR') - #self.substitute(valname,False) - for name,value in falseSet.items(): - self.substitute(name,value) - newSeq.append(valname,self.copy()) + newSeq = BoolSequence(operator="OR") + # self.substitute(valname,False) + for name, value in falseSet.items(): + self.substitute(name, value) + newSeq.append(valname, self.copy()) self.assign(newSeq) return True - - funcVal = self.evaluate(falseSet,CT) - if funcVal == False : - newSeq = BoolSequence(operator='AND') - #self.substitute(valname,True) - for name,value in trueSet.items(): - self.substitute(name,value) - newSeq.append(valname,self.copy()) + funcVal = self.evaluate(falseSet, CT) + if funcVal == False: + newSeq = BoolSequence(operator="AND") + # self.substitute(valname,True) + for name, value in trueSet.items(): + self.substitute(name, value) + newSeq.append(valname, self.copy()) self.assign(newSeq) return True elif funcVal == True: - newSeq = BoolSequence(operator='OR') - #self.substitute(valname,True) - for name,value in trueSet.items(): - self.substitute(name,value) - newSeq.append(-valname,self.copy()) + newSeq = BoolSequence(operator="OR") + # self.substitute(valname,True) + for name, value in trueSet.items(): + self.substitute(name, value) + newSeq.append(-valname, self.copy()) self.assign(newSeq) return True return False - - def evaluate_newbad(self,valueSet,CT=None): + def evaluate_newbad(self, valueSet, CT=None): - if type(self.elements) is bool : return self.elements + if type(self.elements) is bool: + return self.elements self.groupSingle() newSeq = self.copy() - for name,value in valueSet.items(): - newSeq.substitute(name,value) - - if type(newSeq.elements) is bool : + for name, value in valueSet.items(): + newSeq.substitute(name, value) + + if type(newSeq.elements) is bool: return newSeq.elements - else : - surfNames = newSeq.getSurfacesNumbers() + else: + surfNames = newSeq.getSurfacesNumbers() valname = surfNames[0] - if CT is None : - trueSet = {abs(valname) : True } - falseSet = {abs(valname) : False } + if CT is None: + trueSet = {abs(valname): True} + falseSet = {abs(valname): False} else: - trueSet,falseSet = CT.getConstraintSet(valname) - + trueSet, falseSet = CT.getConstraintSet(valname) + if trueSet is None: trueVal = True - else: - trueVal = newSeq.evaluate(trueSet,CT) - if trueVal is None : return None - + else: + trueVal = newSeq.evaluate(trueSet, CT) + if trueVal is None: + return None + if falseSet is None: falseVal = False - else: - falseVal = newSeq.evaluate(falseSet,CT) - if falseVal is None : return None - - if trueVal != falseVal : - return None else: - return trueVal + falseVal = newSeq.evaluate(falseSet, CT) + if falseVal is None: + return None + if trueVal != falseVal: + return None + else: + return trueVal - def evaluate(self,valueSet,CT=None): - if type(self.elements) is bool : return self.elements + def evaluate(self, valueSet, CT=None): + if type(self.elements) is bool: + return self.elements self.groupSingle() op = self.operator noneVal = False for e in self.elements: if type(e) is int: - key = abs(e) - if key in valueSet.keys(): + key = abs(e) + if key in valueSet.keys(): val = valueSet[key] - else: + else: val = None - - if val is not None : - if e < 0 : val = not val - else: - noneVal = True + + if val is not None: + if e < 0: + val = not val + else: + noneVal = True + else: + val = e.evaluate(valueSet) + + if val is None: + noneVal = True + elif op == "AND" and val == False: + return False + elif op == "OR" and val == True: + return True + + if noneVal: + return None + if op == "AND": + return True + else: + return False + + def setDef(self, expression): + terms, operator = outterTerms(expression) + self.operator = operator + self.level = 0 + for t in terms: + if isInteger(t): + self.elements.append(int(t.strip("(").strip(")"))) else: - val = e.evaluate(valueSet) - - if val is None : noneVal = True - elif op == 'AND' and val == False : return False - elif op == 'OR' and val == True : return True - - if noneVal : - return None - if op == 'AND' : - return True - else: - return False - - def setDef(self,expression): - terms,operator = outterTerms(expression) - self.operator = operator - self.level = 0 - for t in terms : - if isInteger(t) : - self.elements.append(int(t.strip('(').strip(')'))) - else: - x = BoolSequence(t) - self.level = max(x.level+1,self.level) - self.elements.append(x) - self.groupSingle() + x = BoolSequence(t) + self.level = max(x.level + 1, self.level) + self.elements.append(x) + self.groupSingle() def groupSingle(self): - if self.level == 0 : return - if type(self.elements) is bool : return - group = [] - for e in reversed(self.elements): - if type(e) is int : - group.append(e) - self.elements.remove(e) - elif e.level==0 and len(e.elements) == 1 : - group.append(e.elements[0]) - self.elements.remove(e) - - - if not group : return - seq = BoolSequence() - seq.elements.extend(group) - seq.operator = self.operator - seq.level = 0 - self.elements.insert(0,seq) + if self.level == 0: + return + if type(self.elements) is bool: + return + group = [] + for e in reversed(self.elements): + if type(e) is int: + group.append(e) + self.elements.remove(e) + elif e.level == 0 and len(e.elements) == 1: + group.append(e.elements[0]) + self.elements.remove(e) + + if not group: + return + seq = BoolSequence() + seq.elements.extend(group) + seq.operator = self.operator + seq.level = 0 + self.elements.insert(0, seq) def sameOperator(self): - if self.level == 0 : return - if type(self.elements) is bool : return - - changed = [] - new = [] - for i,e in enumerate(self.elements): - if e.operator == self.operator: - changed.append(i) - for s in e.elements: - if type(s) is int: - new.append(BoolSequence(str(s))) - else: - new.append(s) - - for i in reversed(changed): - del(self.elements[i]) - self.append(*new) - self.levelUpdate() - - return + if self.level == 0: + return + if type(self.elements) is bool: + return + + changed = [] + new = [] + for i, e in enumerate(self.elements): + if e.operator == self.operator: + changed.append(i) + for s in e.elements: + if type(s) is int: + new.append(BoolSequence(str(s))) + else: + new.append(s) + + for i in reversed(changed): + del self.elements[i] + self.append(*new) + self.levelUpdate() + + return def getSurfacesNumbers(self): - if type(self.elements) is bool : return tuple() + if type(self.elements) is bool: + return tuple() surf = set() for e in self.elements: - if type(e) is int : + if type(e) is int: surf.add(abs(e)) - else: + else: surf.update(e.getSurfacesNumbers()) - return tuple(surf) + return tuple(surf) def levelUpdate(self): - if type(self.elements) is bool : - self.level = 0 - return - - newlev = 0 - for e in self.elements: - if type(e) is int : - lev=0 - else: - lev=e.level+1 - newlev = max(lev,newlev) - self.level = newlev - - -def outterTerms(expression,value='number'): - if value == 'number' : - #reValue = number - reValue = mix - nullVal = '0' - else: - reValue = TFX - nullVal = 'o' - - expr = expression - - - # Loop until no redundant parentheses are found - cont = True - - while cont: + if type(self.elements) is bool: + self.level = 0 + return + + newlev = 0 + for e in self.elements: + if type(e) is int: + lev = 0 + else: + lev = e.level + 1 + newlev = max(lev, newlev) + self.level = newlev + + +def outterTerms(expression, value="number"): + if value == "number": + # reValue = number + reValue = mix + nullVal = "0" + else: + reValue = TFX + nullVal = "o" + + expr = expression + + # Loop until no redundant parentheses are found + cont = True + + while cont: # Loop over most inner parentheses pos = 0 cont = False - while True : - m = mostinner.search(expr,pos) - if not m : break - cont = True - if redundant(m,expr): - # remove redundant parentheses - expr = expr[:m.start()]+ ' ' + expr[m.start()+1:m.end()-1]+ ' ' + expr[m.end():] - else: - # replace no redundant parentheses by 0 and : by ; - zeros = '[' + nullVal* (m.end()-m.start()-2) + ']' - expr = expr[:m.start()] + zeros + expr[m.end():] - - pos = m.end() - - if ':' in expr : - terms = [] - pos = 0 - while True : - newpos = expr.find(':',pos) - if newpos == -1 : - terms.append(expression[pos:].strip()) - break - terms.append(expression[pos:newpos].strip()) - pos = newpos + 1 - return (terms,'OR') - else: - terms = [] - pos = 0 - while True: - m = reValue.search(expr,pos) - if not m : break - terms.append(expression[m.start():m.end()]) - pos = m.end() - return (terms,'AND') - - -def redundant(m,geom): - """ check if the inner parentheses are redundant """ - term = m.group() - - # Find first valid character at the left of the parenthese - leftOK= True - left = m.start()-1 - while left > -1: - if geom[left] in ('\n','C','$',' '): - left -= 1 - else: - if geom[left] not in ('(',':') : leftOK = False - break - - # check if no ':' (or) are inside the parenthese - # if not, parentheses are redundants - if (term.find(':') == -1) : return True - - # Find first valid character at the right of the parenthese - rightOK= True - right = m.end() - while right < len(geom) : - if geom[right] in ('\n','C','$',' '): - right += 1 - else: - if geom[right] not in (')',':') : rightOK = False - break - - # if parentheses are like: - # {( or : } ( ....... ) {) or :} - # parentheses are redundants - - if leftOK and rightOK : - return True - else: - return False + while True: + m = mostinner.search(expr, pos) + if not m: + break + cont = True + if redundant(m, expr): + # remove redundant parentheses + expr = ( + expr[: m.start()] + + " " + + expr[m.start() + 1 : m.end() - 1] + + " " + + expr[m.end() :] + ) + else: + # replace no redundant parentheses by 0 and : by ; + zeros = "[" + nullVal * (m.end() - m.start() - 2) + "]" + expr = expr[: m.start()] + zeros + expr[m.end() :] + + pos = m.end() + + if ":" in expr: + terms = [] + pos = 0 + while True: + newpos = expr.find(":", pos) + if newpos == -1: + terms.append(expression[pos:].strip()) + break + terms.append(expression[pos:newpos].strip()) + pos = newpos + 1 + return (terms, "OR") + else: + terms = [] + pos = 0 + while True: + m = reValue.search(expr, pos) + if not m: + break + terms.append(expression[m.start() : m.end()]) + pos = m.end() + return (terms, "AND") + + +def redundant(m, geom): + """check if the inner parentheses are redundant""" + term = m.group() + + # Find first valid character at the left of the parenthese + leftOK = True + left = m.start() - 1 + while left > -1: + if geom[left] in ("\n", "C", "$", " "): + left -= 1 + else: + if geom[left] not in ("(", ":"): + leftOK = False + break + + # check if no ':' (or) are inside the parenthese + # if not, parentheses are redundants + if term.find(":") == -1: + return True + + # Find first valid character at the right of the parenthese + rightOK = True + right = m.end() + while right < len(geom): + if geom[right] in ("\n", "C", "$", " "): + right += 1 + else: + if geom[right] not in (")", ":"): + rightOK = False + break + + # if parentheses are like: + # {( or : } ( ....... ) {) or :} + # parentheses are redundants + + if leftOK and rightOK: + return True + else: + return False + def isInteger(x): - try : - int(x.strip('(').strip(')')) - return True + try: + int(x.strip("(").strip(")")) + return True except: - return False + return False diff --git a/src/geouned/GEOReverse/Modules/XMLParser.py b/src/geouned/GEOReverse/Modules/XMLParser.py index 55f7c0af..e2b9e7f5 100644 --- a/src/geouned/GEOReverse/Modules/XMLParser.py +++ b/src/geouned/GEOReverse/Modules/XMLParser.py @@ -2,55 +2,55 @@ class cellCARD: - - def __init__(self,data): - self.type = 'cell' - self.TR = None - self.processData(data) + def __init__(self, data): + self.type = "cell" + self.TR = None + self.processData(data) - def processData(self,data): - self.name = int(data['id']) - self.level = None + def processData(self, data): + self.name = int(data["id"]) + self.level = None - if 'material' in data.keys(): - self.MAT = 0 if data['material'] == 'void' else int(data['material']) - else: - self.MAT = None + if "material" in data.keys(): + self.MAT = 0 if data["material"] == "void" else int(data["material"]) + else: + self.MAT = None - if 'universe' in data.keys(): - self.U = 0 if int(data['universe']) == 1 else int(data['universe']) - else: - self.U = 0 + if "universe" in data.keys(): + self.U = 0 if int(data["universe"]) == 1 else int(data["universe"]) + else: + self.U = 0 - if 'fill' in data.keys(): - self.FILL = int(data['fill']) - else: - self.FILL = None + if "fill" in data.keys(): + self.FILL = int(data["fill"]) + else: + self.FILL = None + + self.geom = cline(data["region"].replace("|", ":")) - self.geom = cline(data['region'].replace('|',':')) - class surfCARD: - def __init__(self,data): - - self.type = 'surface' - self.processData(data) + def __init__(self, data): + + self.type = "surface" + self.processData(data) - def processData(self,data): - self.name = int(data['id']) - self.stype = data['type'] - self.scoefs = tuple( float(x) for x in data['coeffs'].split() ) + def processData(self, data): + self.name = int(data["id"]) + self.stype = data["type"] + self.scoefs = tuple(float(x) for x in data["coeffs"].split()) def get_cards(root): for c in root: yield process_card(c) + def process_card(card): - ctype = card.tag - if ctype == 'cell' : - return cellCARD(card.attrib) + ctype = card.tag + if ctype == "cell": + return cellCARD(card.attrib) - elif ctype == 'surface' : - return surfCARD(card.attrib) + elif ctype == "surface": + return surfCARD(card.attrib) diff --git a/src/geouned/GEOReverse/Modules/XMLinput.py b/src/geouned/GEOReverse/Modules/XMLinput.py index a801e557..9b22ee67 100644 --- a/src/geouned/GEOReverse/Modules/XMLinput.py +++ b/src/geouned/GEOReverse/Modules/XMLinput.py @@ -12,240 +12,256 @@ class XMLinput: - def __init__(self,name): + def __init__(self, name): if not os.path.isfile(name): raise FileNotFoundError(f"File {name} does not exist") - + tree = ET.parse(name) root = tree.getroot() - - self.__inputcards__ = list(get_cards(root)) + + self.__inputcards__ = list(get_cards(root)) return - def GetFilteredCells(self,Surfaces,config): - levels,contLevels,Universes = self.GetLevelStructure() + def GetFilteredCells(self, Surfaces, config): + levels, contLevels, Universes = self.GetLevelStructure() + + FilteredCells = {} - FilteredCells = {} - - Ustart = config['Ustart'] - subUniverses = getSubUniverses(Ustart,Universes) + Ustart = config["Ustart"] + subUniverses = getSubUniverses(Ustart, Universes) subUniverses.add(Ustart) - if config['levelMax'] =='all': - levelMax = len(levels) - else : - levelMax = config['levelMax'] + 1 + if config["levelMax"] == "all": + levelMax = len(levels) + else: + levelMax = config["levelMax"] + 1 - levelUniverse = set() - for lev in range(0,levelMax) : - for U in levels[lev]: - levelUniverse.add(U) + levelUniverse = set() + for lev in range(0, levelMax): + for U in levels[lev]: + levelUniverse.add(U) subUniverses = subUniverses.intersection(levelUniverse) for U in list(Universes.keys()): - if U not in subUniverses : del(Universes[U]) - + if U not in subUniverses: + del Universes[U] + for U in Universes.keys(): - FilteredCells[U] = selectCells(Universes[U],config) - processSurfaces(FilteredCells[U],Surfaces) + FilteredCells[U] = selectCells(Universes[U], config) + processSurfaces(FilteredCells[U], Surfaces) # change the surface name in surface dict newSurfaces = {} for k in Surfaces.keys(): - newkey = Surfaces[k].id - newSurfaces[newkey] = Surfaces[k] + newkey = Surfaces[k].id + newSurfaces[newkey] = Surfaces[k] - - for U,universe in FilteredCells.items() : - - # set cell as CAD cell Object - for cname,c in universe.items(): - #print(cname,c.geom.str) - universe[cname] = CADCell(c) - - return levels,FilteredCells,newSurfaces + for U, universe in FilteredCells.items(): + # set cell as CAD cell Object + for cname, c in universe.items(): + # print(cname,c.geom.str) + universe[cname] = CADCell(c) + return levels, FilteredCells, newSurfaces - def GetLevelStructure(self): + def GetLevelStructure(self): containers = [] Universe_dict = {} cellCards = {} - for c in self.__inputcards__ : - if c.type != 'cell' : continue - if c.U not in Universe_dict.keys(): Universe_dict[c.U] = {} - Universe_dict[c.U].update({c.name:c}) + for c in self.__inputcards__: + if c.type != "cell": + continue + if c.U not in Universe_dict.keys(): + Universe_dict[c.U] = {} + Universe_dict[c.U].update({c.name: c}) + + if c.FILL: + containers.append(c) - if c.FILL : - containers.append(c) - - currentLevel = [0] - nextLevel = [] - contLevel ={0:[(0,0)]} - univLevel = {0 : {0}} + nextLevel = [] + contLevel = {0: [(0, 0)]} + univLevel = {0: {0}} level = 0 - + while True: - level += 1 - contLevel[level] = [] - univLevel[level] = set() - for c in reversed(containers) : - if c.U in currentLevel : - c.Level = level - nextLevel.append(c.FILL) - contLevel[level].append((c.U,c.name)) - univLevel[level].add(c.FILL) - - containers.remove(c) - - if nextLevel == [] : break - currentLevel = nextLevel - nextLevel = [] - - return univLevel,contLevel,Universe_dict - - - def GetCells(self,U=None,Fill=None): + level += 1 + contLevel[level] = [] + univLevel[level] = set() + for c in reversed(containers): + if c.U in currentLevel: + c.Level = level + nextLevel.append(c.FILL) + contLevel[level].append((c.U, c.name)) + univLevel[level].add(c.FILL) + + containers.remove(c) + + if nextLevel == []: + break + currentLevel = nextLevel + nextLevel = [] + + return univLevel, contLevel, Universe_dict + + def GetCells(self, U=None, Fill=None): cell_cards = {} - for c in self.__inputcards__ : - if c.type != 'cell' : continue - U_cell = c.U - Fill_cell = c.FILL - if ( U is None and Fill is None) : - cell_cards[c.name] = c - elif U_cell == U and U is not None: - cell_cards[c.name] = c - elif Fill_cell == Fill and Fill is not None: - cell_cards[c.name] = c - - return cell_cards - - def GetSurfaces(self,scale=1.): + for c in self.__inputcards__: + if c.type != "cell": + continue + U_cell = c.U + Fill_cell = c.FILL + if U is None and Fill is None: + cell_cards[c.name] = c + elif U_cell == U and U is not None: + cell_cards[c.name] = c + elif Fill_cell == Fill and Fill is not None: + cell_cards[c.name] = c + + return cell_cards + + def GetSurfaces(self, scale=1.0): surf_cards = {} number = 1 - for c in self.__inputcards__ : - if c.type != 'surface' : continue - surf_cards[c.name] = (c.stype,c.scoefs,number) - number += 1 + for c in self.__inputcards__: + if c.type != "surface": + continue + surf_cards[c.name] = (c.stype, c.scoefs, number) + number += 1 # return surface as surface Objects type - return Get_primitive_surfaces(surf_cards,scale) + return Get_primitive_surfaces(surf_cards, scale) - -def selectCells(cellList,config): +def selectCells(cellList, config): selected = {} - # options are 'all' material - if config['mat'][0] == 'all' : - if config['cell'][0]=='all' : - selected = cellList - elif config['cell'][0]=='exclude' : - for name,c in cellList.items(): - if name not in config['cell'][1]: - selected[name] = c - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if name in config['cell'][1]: - selected[name] = c - - # options are 'exclude' material - elif config['mat'][0] == 'exclude': - if config['cell'][0]=='all' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: + # options are 'all' material + if config["mat"][0] == "all": + if config["cell"][0] == "all": + selected = cellList + elif config["cell"][0] == "exclude": + for name, c in cellList.items(): + if name not in config["cell"][1]: selected[name] = c - else: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='exclude' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: - if name not in config['cell'][1]: - selected[name] = c - else: - if name not in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT not in config['mat'][1]: - if name in config['cell'][1]: - selected[name] = c - else: - if name in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - - # options are 'include' material - elif config['mat'][0] == 'include': - if config['cell'][0]=='all' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT in config['mat'][1]: + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if name in config["cell"][1]: selected[name] = c - else: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='exclude' : - for c in cellList: - if c.FILL is None: - if c.MAT in config['mat'][1]: - if name not in config['cell'][1]: - selected[name] = c - else: - if name not in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number - elif config['cell'][0]=='include' : - for name,c in cellList.items(): - if c.FILL is None: - if c.MAT in config['mat'][1]: - if name in config['cell'][1]: - selected[name] = c - else: - if name in config['cell'][1]: - selected[name] = c # Fill cell are not tested against material number + # options are 'exclude' material + elif config["mat"][0] == "exclude": + if config["cell"][0] == "all": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + selected[name] = c + else: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "exclude": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + if name not in config["cell"][1]: + selected[name] = c + else: + if name not in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT not in config["mat"][1]: + if name in config["cell"][1]: + selected[name] = c + else: + if name in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + + # options are 'include' material + elif config["mat"][0] == "include": + if config["cell"][0] == "all": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT in config["mat"][1]: + selected[name] = c + else: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "exclude": + for c in cellList: + if c.FILL is None: + if c.MAT in config["mat"][1]: + if name not in config["cell"][1]: + selected[name] = c + else: + if name not in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) + elif config["cell"][0] == "include": + for name, c in cellList.items(): + if c.FILL is None: + if c.MAT in config["mat"][1]: + if name in config["cell"][1]: + selected[name] = c + else: + if name in config["cell"][1]: + selected[name] = ( + c # Fill cell are not tested against material number + ) # remove complementary in cell of the universe # for cname,c in selected.items() : # c.geom = remove_hash(cellList,cname) - + if not selected: - raise ValueError("No cells selected. Check input or selection criteria in config file.") + raise ValueError( + "No cells selected. Check input or selection criteria in config file." + ) - return selected - + return selected -def processSurfaces(UCells,Surfaces): + +def processSurfaces(UCells, Surfaces): number = re.compile(r"\#?\s*\d+") - for cname,c in UCells.items() : + for cname, c in UCells.items(): pos = 0 while True: - m = number.search(c.geom.str,pos) - if not m : break - if "#" in m.group(): - pos = m.end() - continue - surf = int(m.group()) - if surf == 0 : - print(c.name) - print(m) - print(c.geom.str) - pos = c.geom.replace(surf,Surfaces[surf].id,pos) - - -def getSubUniverses(Ustart,Universes): - Uid = set() - for c in Universes[Ustart].values() : - if c.FILL : Uid.add(c.FILL) + m = number.search(c.geom.str, pos) + if not m: + break + if "#" in m.group(): + pos = m.end() + continue + surf = int(m.group()) + if surf == 0: + print(c.name) + print(m) + print(c.geom.str) + pos = c.geom.replace(surf, Surfaces[surf].id, pos) + + +def getSubUniverses(Ustart, Universes): + Uid = set() + for c in Universes[Ustart].values(): + if c.FILL: + Uid.add(c.FILL) AllU = Uid.copy() for U in Uid: - AllU = AllU.union(getSubUniverses(U,Universes)) - - return AllU + AllU = AllU.union(getSubUniverses(U, Universes)) + + return AllU + # traduce mcnp surface definition for Solid_Cell class # planes: @@ -268,224 +284,229 @@ def getSubUniverses(Ustart,Universes): # Stype = 'torus' # params = [[px,py,pz],[vx,vy,vz],ra,r] + # Return a diccionary with the corresponding surface Object -def Get_primitive_surfaces(mcnp_surfaces,scale=10.) : - - X_vec = FreeCAD.Vector(1.0,0.0,0.0) - Y_vec = FreeCAD.Vector(0.0,1.0,0.0) - Z_vec = FreeCAD.Vector(0.0,0.0,1.0) - negX_vec = -X_vec - negY_vec = -Y_vec - negZ_vec = -Z_vec - origin= FreeCAD.Vector(0.0,0.0,0.0) - - surfaces = {} - for Sid in mcnp_surfaces.keys() : - MCNPtype = mcnp_surfaces[Sid][0] - MCNPparams = mcnp_surfaces[Sid][1] - number = mcnp_surfaces[Sid][2] - - params = [] - Stype = None - if MCNPtype in ('plane','x-plane','y-plane','z-plane'): - Stype = 'plane' - if MCNPtype == 'plane': +def Get_primitive_surfaces(mcnp_surfaces, scale=10.0): + + X_vec = FreeCAD.Vector(1.0, 0.0, 0.0) + Y_vec = FreeCAD.Vector(0.0, 1.0, 0.0) + Z_vec = FreeCAD.Vector(0.0, 0.0, 1.0) + negX_vec = -X_vec + negY_vec = -Y_vec + negZ_vec = -Z_vec + origin = FreeCAD.Vector(0.0, 0.0, 0.0) + + surfaces = {} + for Sid in mcnp_surfaces.keys(): + MCNPtype = mcnp_surfaces[Sid][0] + MCNPparams = mcnp_surfaces[Sid][1] + number = mcnp_surfaces[Sid][2] + + params = [] + Stype = None + if MCNPtype in ("plane", "x-plane", "y-plane", "z-plane"): + Stype = "plane" + if MCNPtype == "plane": normal = FreeCAD.Vector(MCNPparams[0:3]) - params = (normal, MCNPparams[3]*scale) - elif MCNPtype == 'x-plane': - params = (X_vec, MCNPparams[0]*scale ) - elif MCNPtype == 'y-plane': - params = ( Y_vec, MCNPparams[0]*scale ) - elif MCNPtype == 'z-plane': - params = ( Z_vec, MCNPparams[0]*scale ) - - elif MCNPtype == 'sphere' : - Stype = 'sphere' - params = (FreeCAD.Vector(MCNPparams[0:3])*scale, MCNPparams[3]*scale) - - elif MCNPtype in ('x-cylinder','y-cylinder','z-cylinder') : + params = (normal, MCNPparams[3] * scale) + elif MCNPtype == "x-plane": + params = (X_vec, MCNPparams[0] * scale) + elif MCNPtype == "y-plane": + params = (Y_vec, MCNPparams[0] * scale) + elif MCNPtype == "z-plane": + params = (Z_vec, MCNPparams[0] * scale) + + elif MCNPtype == "sphere": + Stype = "sphere" + params = (FreeCAD.Vector(MCNPparams[0:3]) * scale, MCNPparams[3] * scale) + + elif MCNPtype in ("x-cylinder", "y-cylinder", "z-cylinder"): R = MCNPparams[2] x1 = MCNPparams[0] x2 = MCNPparams[1] - Stype = 'cylinder' - - if MCNPtype == 'x-cylinder': + Stype = "cylinder" + + if MCNPtype == "x-cylinder": v = X_vec - p = FreeCAD.Vector(0., x1, x2) - elif MCNPtype == 'y-cylinder': + p = FreeCAD.Vector(0.0, x1, x2) + elif MCNPtype == "y-cylinder": v = Y_vec - p = FreeCAD.Vector(x1, 0., x2) - elif MCNPtype == 'z-cylinder': + p = FreeCAD.Vector(x1, 0.0, x2) + elif MCNPtype == "z-cylinder": v = Z_vec - p = FreeCAD.Vector(x1, x2, 0.) + p = FreeCAD.Vector(x1, x2, 0.0) - if scale != 1.0 : - p = p.multiply(scale) - R *= scale + if scale != 1.0: + p = p.multiply(scale) + R *= scale - params = ( p,v,R ) + params = (p, v, R) - - elif MCNPtype in ('x-cone','y-cone','z-cone') : - Stype = 'cone' + elif MCNPtype in ("x-cone", "y-cone", "z-cone"): + Stype = "cone" x1 = MCNPparams[0] x2 = MCNPparams[1] x3 = MCNPparams[2] - p = FreeCAD.Vector(x1,x2,x3) + p = FreeCAD.Vector(x1, x2, x3) t2 = MCNPparams[3] - t = math.sqrt(t2) + t = math.sqrt(t2) dblsht = True - if MCNPtype == 'x-cone': - v = X_vec - elif MCNPtype == 'y-cone': - v = Y_vec - elif MCNPtype == 'z-cone': - v = Z_vec + if MCNPtype == "x-cone": + v = X_vec + elif MCNPtype == "y-cone": + v = Y_vec + elif MCNPtype == "z-cone": + v = Z_vec p = p.multiply(scale) - params = (p,v,t,dblsht) - - elif MCNPtype in ['x-torus','y-torus','z-torus'] : - Stype = 'torus' - p = FreeCAD.Vector(MCNPparams[0:3]) - Ra,r1,r2 = MCNPparams[3:6] - - if MCNPtype == 'x-torus': - v = X_vec - elif MCNPtype == 'y-torus': - v = Y_vec - elif MCNPtype == 'z-torus': - v = Z_vec - - if scale != 1.0 : - Ra *= scale - r1 *= scale - r2 *= scale - p = p.multiply(scale) - - params = ( p,v,Ra,r1,r2) - - elif MCNPtype == 'quadric' : - Qparams = tuple(MCNPparams[0:10]) - Stype,quadric = gq2cyl(Qparams) - - if Stype == 'cylinder' : + params = (p, v, t, dblsht) + + elif MCNPtype in ["x-torus", "y-torus", "z-torus"]: + Stype = "torus" + p = FreeCAD.Vector(MCNPparams[0:3]) + Ra, r1, r2 = MCNPparams[3:6] + + if MCNPtype == "x-torus": + v = X_vec + elif MCNPtype == "y-torus": + v = Y_vec + elif MCNPtype == "z-torus": + v = Z_vec + + if scale != 1.0: + Ra *= scale + r1 *= scale + r2 *= scale + p = p.multiply(scale) + + params = (p, v, Ra, r1, r2) + + elif MCNPtype == "quadric": + Qparams = tuple(MCNPparams[0:10]) + Stype, quadric = gq2cyl(Qparams) + + if Stype == "cylinder": p = FreeCAD.Vector(quadric[0:3]) v = FreeCAD.Vector(quadric[3:6]) R = quadric[6] - if scale != 1.0 : - R *= scale - p = p.multiply(scale) + if scale != 1.0: + R *= scale + p = p.multiply(scale) - params = ( p,v,R ) - - elif Stype == 'cone' : + params = (p, v, R) + + elif Stype == "cone": p = FreeCAD.Vector(quadric[0:3]) v = FreeCAD.Vector(quadric[3:6]) t = quadric[6] dblsht = quadric[7] - if scale != 1.0 : + if scale != 1.0: p = p.multiply(scale) - - params = ( p,v,t,dblsht ) + + params = (p, v, t, dblsht) else: - print ( Stype ) + print(Stype) params = None -# get_quadric_surface(params) - - if Stype == 'plane': - surfaces[Sid] = Plane(number, params) - elif Stype == 'sphere': - surfaces[Sid] = Sphere(number, params) - elif Stype == 'cylinder': - surfaces[Sid] = Cylinder(number, params) - elif Stype == 'cone': - surfaces[Sid] = Cone(number, params) - elif Stype == 'torus': - surfaces[Sid] = Torus(number, params) - else : - print('Undefined',Sid) - print( MCNPtype ,number,MCNPparams) - - return surfaces + # get_quadric_surface(params) + + if Stype == "plane": + surfaces[Sid] = Plane(number, params) + elif Stype == "sphere": + surfaces[Sid] = Sphere(number, params) + elif Stype == "cylinder": + surfaces[Sid] = Cylinder(number, params) + elif Stype == "cone": + surfaces[Sid] = Cone(number, params) + elif Stype == "torus": + surfaces[Sid] = Torus(number, params) + else: + print("Undefined", Sid) + print(MCNPtype, number, MCNPparams) + + return surfaces + def gq2cyl(x): -# Conversion de GQ a Cyl -# Ax2+By2+Cz2+Dxy+Eyz+Fxz+Gx+Hy+Jz+K=0 -# x.T*M*x + b.T*x + K = 0 - minWTol=5.e-2 - minRTol=1.e-3 - #minRTol=3.e-1 - # lx = np.array(x) - tp = '' - M = np.array( [[x[0],x[3]/2,x[5]/2], \ - [x[3]/2,x[1],x[4]/2], \ - [x[5]/2,x[4]/2,x[2]]] ) - w,P = LA.eigh(M) - sw = np.sort(w) - aw = np.abs(w) - asw= np.sort(aw) - # Test for cylinder (least abs value is much less than others) - if asw[0]minRTol*asw[2]: - tp = 'not found - ellipsoid cylinder' - rv = [0] - return tp,rv - # Vector de desplazamiento - # x0 = -0.5*Pt*D-1*P*b pero ojo que un lambda es cero - # P es la matriz de valores propios - b = np.array(x[6:9]) - Pb= np.matmul(P,b) - for i in otherAxes: Pb[i] /= w[i] - x0 = -0.5*np.matmul(P.T,Pb) - k = -0.5*np.matmul(x0,b) - x[9] - # Resultados finales - - rv[0:3] = x0 # Punto del eje - rv[3:6] = P[:,iaxis] # Vector director - rv[6] = np.sqrt(k/sw[1]) # Radio - # Test for cone (incomplete, returns empty data list) - elif np.sign(sw[0])!=np.sign(sw[2]): # maybe cone - tp = 'cone' - rv = [0.]*8 # X0, Y0, Z0, VX, VY, VZ, tgAlpha, double sheet - if np.sign(sw[0])==np.sign(sw[1]): - iaxis = np.where(w==sw[2])[0][0] + # Conversion de GQ a Cyl + # Ax2+By2+Cz2+Dxy+Eyz+Fxz+Gx+Hy+Jz+K=0 + # x.T*M*x + b.T*x + K = 0 + minWTol = 5.0e-2 + minRTol = 1.0e-3 + # minRTol=3.e-1 + # lx = np.array(x) + tp = "" + M = np.array( + [ + [x[0], x[3] / 2, x[5] / 2], + [x[3] / 2, x[1], x[4] / 2], + [x[5] / 2, x[4] / 2, x[2]], + ] + ) + w, P = LA.eigh(M) + sw = np.sort(w) + aw = np.abs(w) + asw = np.sort(aw) + # Test for cylinder (least abs value is much less than others) + if asw[0] < minWTol * asw[1]: + tp = "cylinder" + rv = [0.0] * 7 # X0,Y0,Z0, VX, VY, VZ, R + iaxis = np.where(aw == asw[0])[0][0] + otherAxes = ((iaxis + 1) % 3, (iaxis + 2) % 3) + if abs(w[otherAxes[0]] - w[otherAxes[1]]) > minRTol * asw[2]: + tp = "not found - ellipsoid cylinder" + rv = [0] + return tp, rv + # Vector de desplazamiento + # x0 = -0.5*Pt*D-1*P*b pero ojo que un lambda es cero + # P es la matriz de valores propios + b = np.array(x[6:9]) + Pb = np.matmul(P, b) + for i in otherAxes: + Pb[i] /= w[i] + x0 = -0.5 * np.matmul(P.T, Pb) + k = -0.5 * np.matmul(x0, b) - x[9] + # Resultados finales + + rv[0:3] = x0 # Punto del eje + rv[3:6] = P[:, iaxis] # Vector director + rv[6] = np.sqrt(k / sw[1]) # Radio + # Test for cone (incomplete, returns empty data list) + elif np.sign(sw[0]) != np.sign(sw[2]): # maybe cone + tp = "cone" + rv = [0.0] * 8 # X0, Y0, Z0, VX, VY, VZ, tgAlpha, double sheet + if np.sign(sw[0]) == np.sign(sw[1]): + iaxis = np.where(w == sw[2])[0][0] + else: + iaxis = np.where(w == sw[0])[0][0] + otherAxes = ((iaxis + 1) % 3, (iaxis + 2) % 3) + if abs(w[otherAxes[0]] - w[otherAxes[1]]) > minRTol * asw[2]: + tp = "not found - ellipsoid cone/hyperboloid" + rv = [0] + return tp, rv + # Displacement vector ( x0 = -0.5*M^-1*b = -0.5*P.T*D^-1*P*b + b = np.array(x[6:9]) + x0 = -0.5 * np.matmul(P, np.matmul(P.T, b) / w) + k = x0.T @ M @ x0 - x[9] + if np.abs(k * w[iaxis]) > minRTol * minRTol * asw[2]: + + # tp = 'not found - hyperboloid' + # rv = [0] + # force cone surface + print("Force cone surface") + tp = "cone" + rv[0:3] = x0 # vertex point + rv[3:6] = P[:, iaxis] # axis direction + rv[6] = np.sqrt(-w[otherAxes[0]] / w[iaxis]) # semiangle tangent + rv[7] = True # here always double sheet cones + return tp, rv + # return value + rv[0:3] = x0 # vertex point + rv[3:6] = P[:, iaxis] # axis direction + rv[6] = np.sqrt(-w[otherAxes[0]] / w[iaxis]) # semiangle tangent + rv[7] = True # here always double sheet cones else: - iaxis = np.where(w==sw[0])[0][0] - otherAxes = ( (iaxis+1)%3, (iaxis+2)%3 ) - if abs(w[otherAxes[0]]-w[otherAxes[1]])>minRTol*asw[2]: - tp = 'not found - ellipsoid cone/hyperboloid' - rv = [0] - return tp,rv - # Displacement vector ( x0 = -0.5*M^-1*b = -0.5*P.T*D^-1*P*b - b = np.array(x[6:9]) - x0= -0.5*np.matmul(P,np.matmul(P.T,b)/w) - k = x0.T @ M @ x0 - x[9] - if np.abs(k*w[iaxis])>minRTol*minRTol*asw[2]: - - # tp = 'not found - hyperboloid' - # rv = [0] - # force cone surface - print('Force cone surface') - tp = 'cone' - rv[0:3] = x0 # vertex point - rv[3:6] = P[:,iaxis] # axis direction - rv[6] = np.sqrt(-w[otherAxes[0]]/w[iaxis]) # semiangle tangent - rv[7] = True # here always double sheet cones - return tp,rv - # return value - rv[0:3] = x0 # vertex point - rv[3:6] = P[:,iaxis] # axis direction - rv[6] = np.sqrt(-w[otherAxes[0]]/w[iaxis]) # semiangle tangent - rv[7] = True # here always double sheet cones - else: - tp = 'not found - unknown' - rv = [0] - return tp,rv - + tp = "not found - unknown" + rv = [0] + return tp, rv diff --git a/src/geouned/GEOReverse/Modules/buildCAD.py b/src/geouned/GEOReverse/Modules/buildCAD.py index 8a035948..f0064ccd 100644 --- a/src/geouned/GEOReverse/Modules/buildCAD.py +++ b/src/geouned/GEOReverse/Modules/buildCAD.py @@ -4,194 +4,208 @@ from .Utils.booleanFunction import BoolSequence -def buildCAD(UnivCell,data,config): +def buildCAD(UnivCell, data, config): - UniverseCut = True - if 'Ustart' not in config.keys(): config['Ustart'] = 0 - if 'levelMax' not in config.keys(): config['levelMax'] = 'all' + UniverseCut = True + if "Ustart" not in config.keys(): + config["Ustart"] = 0 + if "levelMax" not in config.keys(): + config["levelMax"] = "all" UnivCell.name = 0 - UnivCell.Fill = config['Ustart'] - + UnivCell.Fill = config["Ustart"] + # read all surfaces definition - if config['format'] == 'mcnp' : - factor = 10 + if config["format"] == "mcnp": + factor = 10 else: - factor = 1 + factor = 1 + + modelSurfaces = data.GetSurfaces( + scale=factor + ) # scale change cm in mcnp to mm in CAD Obj - modelSurfaces = data.GetSurfaces(scale=factor) # scale change cm in mcnp to mm in CAD Obj - # read Cells and group into universes print(config) - levels,UniverseCells,modelSurfaces = data.GetFilteredCells(modelSurfaces,config) + levels, UniverseCells, modelSurfaces = data.GetFilteredCells(modelSurfaces, config) # assign to each cell the surfaces belonging to the cell - AssignSurfaceToCell(UniverseCells,modelSurfaces) - -# print(UniverseCells[0][120].definition.str) -# print(UniverseCells[0][120].surfaces) -# CT=buildCTableFromSolids(UnivCell.shape,UniverseCells[0][70],option='full') -# print(CT) -# simply = BoolSequence(UniverseCells[0][70].definition.str) -# print('antesSimply',simply) -# simply.simplify(CT) -# print('despues',simply) - #exit() - + AssignSurfaceToCell(UniverseCells, modelSurfaces) + + # print(UniverseCells[0][120].definition.str) + # print(UniverseCells[0][120].surfaces) + # CT=buildCTableFromSolids(UnivCell.shape,UniverseCells[0][70],option='full') + # print(CT) + # simply = BoolSequence(UniverseCells[0][70].definition.str) + # print('antesSimply',simply) + # simply.simplify(CT) + # print('despues',simply) + # exit() # dictionnary of the cells filled with a given Universe U # universeContainers = GetUniverseContainers(levels,UniverseCells) UnivCell.level = None - levelMax = config['levelMax'] - Ustart = config['Ustart'] - if levelMax == 'all': + levelMax = config["levelMax"] + Ustart = config["Ustart"] + if levelMax == "all": levelMax = len(levels) - - for lev,Univ in levels.items(): - if Ustart in Univ : - UnivCell.level = lev-1 - break - startInfo =(Ustart,levelMax) - - return BuildUniverse(startInfo,UnivCell,UniverseCells,universeCut=UniverseCut) - - -def interferencia(container,cell,mode='slice'): - - if mode == 'common': + + for lev, Univ in levels.items(): + if Ustart in Univ: + UnivCell.level = lev - 1 + break + startInfo = (Ustart, levelMax) + + return BuildUniverse(startInfo, UnivCell, UniverseCells, universeCut=UniverseCut) + + +def interferencia(container, cell, mode="slice"): + + if mode == "common": return cell.shape.common(container.shape) Base = cell.shape Tool = (container.shape,) - - solids = BOPTools.SplitAPI.slice(Base,Tool, 'Split',tolerance = 0).Solids + + solids = BOPTools.SplitAPI.slice(Base, Tool, "Split", tolerance=0).Solids cellParts = [] for s in solids: - if container.shape.isInside(s.CenterOfMass,0.0,False) : cellParts.append(s) - - if not cellParts : + if container.shape.isInside(s.CenterOfMass, 0.0, False): + cellParts.append(s) + + if not cellParts: return cell.shape else: - return FuseSolid(cellParts) - -def AssignSurfaceToCell(UniverseCells,modelSurfaces): + return FuseSolid(cellParts) + - for Uid,uniCells in UniverseCells.items(): - for cId,c in uniCells.items(): - c.setSurfaces(modelSurfaces) +def AssignSurfaceToCell(UniverseCells, modelSurfaces): -def GetUniverseContainers(levels,Universes): + for Uid, uniCells in UniverseCells.items(): + for cId, c in uniCells.items(): + c.setSurfaces(modelSurfaces) + + +def GetUniverseContainers(levels, Universes): Ucontainer = {} - for lev in range(1,len(levels)): - for U,name in levels[lev]: + for lev in range(1, len(levels)): + for U, name in levels[lev]: UFILL = Universes[U][name].FILL - if UFILL in Ucontainer.keys() : - Ucontainer[UFILL].append((U,name,lev)) + if UFILL in Ucontainer.keys(): + Ucontainer[UFILL].append((U, name, lev)) else: - Ucontainer[UFILL] = [(U,name,lev)] - return Ucontainer + Ucontainer[UFILL] = [(U, name, lev)] + return Ucontainer + -def BuildUniverse(startInfo,ContainerCell,AllUniverses,universeCut=True,duplicate=False): - CADUniverse=[] +def BuildUniverse( + startInfo, ContainerCell, AllUniverses, universeCut=True, duplicate=False +): + CADUniverse = [] - Ustart,levelMax = startInfo + Ustart, levelMax = startInfo Universe = AllUniverses[Ustart] - - print('Build Universe {} in container cell {}'.format(ContainerCell.FILL,ContainerCell.name)) + + print( + "Build Universe {} in container cell {}".format( + ContainerCell.FILL, ContainerCell.name + ) + ) fails = [] for NTcell in Universe.values(): if duplicate: - if NTcell.shape : - buildShape = False - if ContainerCell.CurrentTR : - cell = NTcell.copy() - cell.transformSolid(ContainerCell.CurrentTR) - else: - cell = NTcell - else: - CTRF = None - buildShape = True - if ContainerCell.CurrentTR: - CC = ContainerCell.copy() - CC.transformSolid(CC.CurrentTR,reverse=True) - else: - CC = ContainerCell + if NTcell.shape: + buildShape = False + if ContainerCell.CurrentTR: + cell = NTcell.copy() + cell.transformSolid(ContainerCell.CurrentTR) + else: + cell = NTcell + else: + CTRF = None + buildShape = True + if ContainerCell.CurrentTR: + CC = ContainerCell.copy() + CC.transformSolid(CC.CurrentTR, reverse=True) + else: + CC = ContainerCell else: - CTRF = ContainerCell.CurrentTR - CC = ContainerCell - buildShape = True - NTcell = NTcell.copy() - - if buildShape: - print('Level :{} build Cell {} '.format(CC.level + 1,NTcell.name)) - if type(NTcell.definition) is not BoolSequence: - NTcell.definition = BoolSequence(NTcell.definition.str) - - bBox = ContainerCell.shape.BoundBox - - debug = False - if debug : - NTcell.buildShape(bBox,surfTR=CTRF,simplify=False) - else: - try: - NTcell.buildShape(bBox,surfTR=CTRF,simplify=False) - except: - print(f'fail converting cell {NTcell.name}') - fails.append(NTcell.name) - - if NTcell.shape is None : continue - - if duplicate : - if ContainerCell.CurrentTR : - cell = NTcell.copy() - cell.transformSolid(ContainerCell.CurrentTR) - else: - cell = NTcell - else: - cell = NTcell - - - if universeCut and ContainerCell.shape : cell.shape = interferencia(ContainerCell,cell) - + CTRF = ContainerCell.CurrentTR + CC = ContainerCell + buildShape = True + NTcell = NTcell.copy() + + if buildShape: + print("Level :{} build Cell {} ".format(CC.level + 1, NTcell.name)) + if type(NTcell.definition) is not BoolSequence: + NTcell.definition = BoolSequence(NTcell.definition.str) + + bBox = ContainerCell.shape.BoundBox + + debug = False + if debug: + NTcell.buildShape(bBox, surfTR=CTRF, simplify=False) + else: + try: + NTcell.buildShape(bBox, surfTR=CTRF, simplify=False) + except: + print(f"fail converting cell {NTcell.name}") + fails.append(NTcell.name) + + if NTcell.shape is None: + continue + + if duplicate: + if ContainerCell.CurrentTR: + cell = NTcell.copy() + cell.transformSolid(ContainerCell.CurrentTR) + else: + cell = NTcell + else: + cell = NTcell + + if universeCut and ContainerCell.shape: + cell.shape = interferencia(ContainerCell, cell) + if not cell.FILL or ContainerCell.level + 1 == levelMax: - CADUniverse.append(cell) + CADUniverse.append(cell) else: - if ContainerCell.CurrentTR : + if ContainerCell.CurrentTR: cell.CurrentTR = ContainerCell.CurrentTR.multiply(cell.TRFL) - cell.level = ContainerCell.level + 1 - univ,ff = BuildUniverse((cell.FILL,levelMax),cell,AllUniverses,universeCut=universeCut) - CADUniverse.append( univ ) - fails.extend(ff) + cell.level = ContainerCell.level + 1 + univ, ff = BuildUniverse( + (cell.FILL, levelMax), cell, AllUniverses, universeCut=universeCut + ) + CADUniverse.append(univ) + fails.extend(ff) + + return ((ContainerCell.name, Ustart), CADUniverse), fails - return ((ContainerCell.name,Ustart),CADUniverse),fails +def makeTree(CADdoc, CADCells): + label, universeCADCells = CADCells + groupObj = CADdoc.addObject("App::Part", "Materials") -def makeTree(CADdoc,CADCells): + groupObj.Label = "Universe_{}_Container_{}".format(label[1], label[0]) - label,universeCADCells = CADCells - groupObj = CADdoc.addObject('App::Part','Materials') - - groupObj.Label = 'Universe_{}_Container_{}'.format(label[1],label[0]) - CADObj = {} - for i,c in enumerate(universeCADCells): + for i, c in enumerate(universeCADCells): if type(c) is tuple: - groupObj.addObject(makeTree(CADdoc,c)) - else: - featObj = CADdoc.addObject( "Part::FeaturePython", "solid{}".format(i)) - featObj.Label = "Cell_{}_{}".format(c.name,c.MAT) - featObj.Shape = c.shape - if c.MAT not in CADObj.keys(): - CADObj[c.MAT] = [featObj] - else: - CADObj[c.MAT].append(featObj) - - for mat,matGroup in CADObj.items(): - groupMatObj = CADdoc.addObject('App::Part','Materials') - groupMatObj.Label = 'Material_{}'.format(mat) - groupMatObj.addObjects(matGroup) - groupObj.addObject(groupMatObj) - - return groupObj + groupObj.addObject(makeTree(CADdoc, c)) + else: + featObj = CADdoc.addObject("Part::FeaturePython", "solid{}".format(i)) + featObj.Label = "Cell_{}_{}".format(c.name, c.MAT) + featObj.Shape = c.shape + if c.MAT not in CADObj.keys(): + CADObj[c.MAT] = [featObj] + else: + CADObj[c.MAT].append(featObj) + + for mat, matGroup in CADObj.items(): + groupMatObj = CADdoc.addObject("App::Part", "Materials") + groupMatObj.Label = "Material_{}".format(mat) + groupMatObj.addObjects(matGroup) + groupObj.addObject(groupMatObj) + return groupObj diff --git a/src/geouned/GEOReverse/Modules/buildSolidCell.py b/src/geouned/GEOReverse/Modules/buildSolidCell.py index 78d579eb..7c8c8178 100644 --- a/src/geouned/GEOReverse/Modules/buildSolidCell.py +++ b/src/geouned/GEOReverse/Modules/buildSolidCell.py @@ -8,272 +8,278 @@ def getPart(slist): sol = [] for s in slist: - if type(s) is list : - sol.extend(getPart(s)) - else: - sol.append(s) - return sol + if type(s) is list: + sol.extend(getPart(s)) + else: + sol.append(s) + return sol + -def BuildSolid(cell,boundBox,mode='oneByOne',simplify=False): +def BuildSolid(cell, boundBox, mode="oneByOne", simplify=False): - cutCell = cell.makeBox(boundBox) - #cell.definition = BoolSequence(cell.definition.str) + cutCell = cell.makeBox(boundBox) + # cell.definition = BoolSequence(cell.definition.str) cell.cleanUndefined() - celParts = BuildDepth(cell,splitBase(cutCell),mode,True,simplify) + celParts = BuildDepth(cell, splitBase(cutCell), mode, True, simplify) celParts = getPart(celParts) - #print('celparts',len(celParts)) + # print('celparts',len(celParts)) shapeParts = [] - for i,s in enumerate(celParts): + for i, s in enumerate(celParts): shapeParts.append(s.base) - #s.base.exportStep('solid{}.stp'.format(i)) + # s.base.exportStep('solid{}.stp'.format(i)) - # tt = FuseSolid(shapeParts) - # tt = tt.removeSplitter() - #tt=Part.makeCompound(shapeParts) - #tt.exportStep('cell{}.stp'.format(cell.name)) + # tt = FuseSolid(shapeParts) + # tt = tt.removeSplitter() + # tt=Part.makeCompound(shapeParts) + # tt.exportStep('cell{}.stp'.format(cell.name)) return shapeParts - #return FuseSolid(shapeParts) + # return FuseSolid(shapeParts) + +def BuildDepth(cell, cutShape, mode, baseBox, simplify=False, loop=0): -def BuildDepth(cell,cutShape,mode,baseBox,simplify=False,loop=0): - loop += 1 seq = cell.definition - if seq.level == 0 : - if baseBox : - cutShape,cut = BuildSolidParts(cell,cutShape,mode) - else: - cutShape,cut = BuildSolidParts(cell,cutShape,'solids') - return cutShape - - if type(cutShape) is not list: cutShape=[cutShape] + if seq.level == 0: + if baseBox: + cutShape, cut = BuildSolidParts(cell, cutShape, mode) + else: + cutShape, cut = BuildSolidParts(cell, cutShape, "solids") + return cutShape + + if type(cutShape) is not list: + cutShape = [cutShape] newCutShape = [] - for i,CS in enumerate(cutShape): - cbaseBox = baseBox - #CS.base.exportStep('CS_{}_{}.stp'.format(i,str(cell.definition))) - #CTable =buildCTableFromSolids(cell.makeBox(CS.base.BoundBox),cell.surfaces,option='full') - #cell.definition.simplify(CTable) - cell.definition.groupSingle() - - if type(cell.definition.elements) is not bool : - if cell.definition.level == 0: - tmp = BoolSequence(operator=cell.definition.operator) - tmp.append(cell.definition) - cell.definition = tmp - - if seq.operator == 'AND': - part = CS - for e in cell.definition.elements: - part = BuildDepth(cell.getSubCell(e),part,mode,cbaseBox,simplify,loop=loop) - cbaseBox = False - newCutShape.extend(part) - else: - cellParts = [] - for e in cell.definition.elements: - sub = cell.getSubCell(e) - part = BuildDepth(sub,CS,mode,baseBox,simplify,loop=loop) - cellParts.extend(part) - - JB = joinBase(cellParts) - if JB.base is not None : newCutShape.append(JB) - - elif cell.definition.elements : - newCutShape.append(CS) - - cutShape=newCutShape - return cutShape - - - -def BuildSolidParts(cell,base,mode): + for i, CS in enumerate(cutShape): + cbaseBox = baseBox + # CS.base.exportStep('CS_{}_{}.stp'.format(i,str(cell.definition))) + # CTable =buildCTableFromSolids(cell.makeBox(CS.base.BoundBox),cell.surfaces,option='full') + # cell.definition.simplify(CTable) + cell.definition.groupSingle() + + if type(cell.definition.elements) is not bool: + if cell.definition.level == 0: + tmp = BoolSequence(operator=cell.definition.operator) + tmp.append(cell.definition) + cell.definition = tmp + + if seq.operator == "AND": + part = CS + for e in cell.definition.elements: + part = BuildDepth( + cell.getSubCell(e), part, mode, cbaseBox, simplify, loop=loop + ) + cbaseBox = False + newCutShape.extend(part) + else: + cellParts = [] + for e in cell.definition.elements: + sub = cell.getSubCell(e) + part = BuildDepth(sub, CS, mode, baseBox, simplify, loop=loop) + cellParts.extend(part) + + JB = joinBase(cellParts) + if JB.base is not None: + newCutShape.append(JB) + + elif cell.definition.elements: + newCutShape.append(CS) + + cutShape = newCutShape + return cutShape + + +def BuildSolidParts(cell, base, mode): # part if several base in input - if type(base) is list or type(base) is tuple : - fullPart = [] - cutPart = [] - for b in base : - fullList,cutList = BuildSolidParts(cell,b,mode) - fullPart.extend(fullList) - cutPart.extend(cutList) - return fullPart,cutPart - + if type(base) is list or type(base) is tuple: + fullPart = [] + cutPart = [] + for b in base: + fullList, cutList = BuildSolidParts(cell, b, mode) + fullPart.extend(fullList) + cutPart.extend(cutList) + return fullPart, cutPart + boundBox = base.base.BoundBox surfaces = tuple(cell.surfaces.values()) - #print('\nbuild Parts :',mode) - #print(cell.definition) - #print(boundBox) - - if mode == 'solids' : - #boundBox.enlarge(10) - if cell.definition.operator=='OR' and False : - Def = cell.definition - cell.definition = cell.definition.getComplementary() - cell.buildShape(boundBox,force=False,simplify=False) - cell.definition = Def - else: - cell.buildShape(boundBox,force=True,simplify=False,fuse=True) - - #print('export') - # base.base.exportStep('base.stp') - #name=''.join(str(cell.definition)) - #cell.shape.exportStep('sol{}.stp'.format(name)) + # print('\nbuild Parts :',mode) + # print(cell.definition) + # print(boundBox) + + if mode == "solids": + # boundBox.enlarge(10) + if cell.definition.operator == "OR" and False: + Def = cell.definition + cell.definition = cell.definition.getComplementary() + cell.buildShape(boundBox, force=False, simplify=False) + cell.definition = Def + else: + cell.buildShape(boundBox, force=True, simplify=False, fuse=True) + + # print('export') + # base.base.exportStep('base.stp') + # name=''.join(str(cell.definition)) + # cell.shape.exportStep('sol{}.stp'.format(name)) else: - cell.buildSurfaceShape(boundBox) + cell.buildSurfaceShape(boundBox) if not surfaces: - print('not cutting surfaces') - return tuple(base.base),tuple() - if mode == 'solids': - full, cut = SplitSolid(base,surfaces,cell,solidTool=True,tolerance=Options.splitTolerance) - elif mode == 'allSurfaces': - full, cut = SplitSolid(base,surfaces,cell,tolerance=Options.splitTolerance) - - elif mode == 'planeFirst' : + print("not cutting surfaces") + return tuple(base.base), tuple() + if mode == "solids": + full, cut = SplitSolid( + base, surfaces, cell, solidTool=True, tolerance=Options.splitTolerance + ) + elif mode == "allSurfaces": + full, cut = SplitSolid(base, surfaces, cell, tolerance=Options.splitTolerance) + + elif mode == "planeFirst": planes = [] others = [] - for s in surfaces: - #s.buildShape( boundBox) - #s.shape.exportStep('Tool_{}_{}.stp'.format(s.type,s.id)) - if s.type == 'plane' : - planes.append(s) - else: - others.append(s) - - if planes : - - full, cut = SplitSolid(base,planes,cell,tolerance=Options.splitTolerance) - #for i,s in enumerate(full): - # s.exportStep('fullplane_{}.stp'.format(i)) - #for i,s in enumerate(cut): - # s.base.exportStep('cutplane_{}.stp'.format(i)) - #print('planes',full) - #print('planes',cut) + for s in surfaces: + # s.buildShape( boundBox) + # s.shape.exportStep('Tool_{}_{}.stp'.format(s.type,s.id)) + if s.type == "plane": + planes.append(s) + else: + others.append(s) + + if planes: + + full, cut = SplitSolid(base, planes, cell, tolerance=Options.splitTolerance) + # for i,s in enumerate(full): + # s.exportStep('fullplane_{}.stp'.format(i)) + # for i,s in enumerate(cut): + # s.base.exportStep('cutplane_{}.stp'.format(i)) + # print('planes',full) + # print('planes',cut) else: - full = [] - cut = base - - if others : - newf, cut = SplitSolid(cut,others,cell,tolerance=Options.splitTolerance) - #print('others',newf) - #print('others',cut) + full = [] + cut = base + + if others: + newf, cut = SplitSolid(cut, others, cell, tolerance=Options.splitTolerance) + # print('others',newf) + # print('others',cut) else: - newf = [] + newf = [] full.extend(newf) - elif mode == 'otherFirst' : + elif mode == "otherFirst": planes = [] others = [] for s in surfaces: - # s.buildShape( boundBox) - if s.type == 'plane' : - planes.append(s) - else: - others.append(s) - - if others : - full, cut = SplitSolid(base,others,cell,tolerance=Options.splitTolerance) - #print('others',full) - #print('others',cut) + # s.buildShape( boundBox) + if s.type == "plane": + planes.append(s) + else: + others.append(s) + + if others: + full, cut = SplitSolid(base, others, cell, tolerance=Options.splitTolerance) + # print('others',full) + # print('others',cut) else: - full = [] - cut = base - - if planes : - newf, cut = SplitSolid(cut,planes,cell,tolerance=Options.splitTolerance) - #print('planes',newf) - #print('planes',cut) + full = [] + cut = base + + if planes: + newf, cut = SplitSolid(cut, planes, cell, tolerance=Options.splitTolerance) + # print('planes',newf) + # print('planes',cut) else: - newf = [] + newf = [] full.extend(newf) - - elif mode == 'oneByOne': + + elif mode == "oneByOne": planes = [] others = [] for s in surfaces: - if s.type == 'plane' : - planes.append(s) - else: - others.append(s) - - if planes : - full, cut = SplitSolid(base,planes,cell,tolerance=Options.splitTolerance) + if s.type == "plane": + planes.append(s) + else: + others.append(s) + + if planes: + full, cut = SplitSolid(base, planes, cell, tolerance=Options.splitTolerance) else: - full = [] - cut = base + full = [] + cut = base - #cut[0].base.exportStep('cutPlane.stp') - for surf in others : - newf, cut = SplitSolid(cut,(surf,),cell,tolerance=Options.splitTolerance) - full.extend(newf) + # cut[0].base.exportStep('cutPlane.stp') + for surf in others: + newf, cut = SplitSolid(cut, (surf,), cell, tolerance=Options.splitTolerance) + full.extend(newf) - elif mode == 'otherOneByOne': + elif mode == "otherOneByOne": planes = [] others = [] for s in surfaces: - if s.type == 'plane' : - planes.append(s) - else: - others.append(s) + if s.type == "plane": + planes.append(s) + else: + others.append(s) cut = base full = [] - for surf in others : - newf, cut = SplitSolid(cut,(surf,),cell,tolerance=Options.splitTolerance) - full.extend(newf) + for surf in others: + newf, cut = SplitSolid(cut, (surf,), cell, tolerance=Options.splitTolerance) + full.extend(newf) + + for surf in planes: + newf, cut = SplitSolid(cut, (surf,), cell, tolerance=Options.splitTolerance) + full.extend(newf) + + return full, cut - for surf in planes : - newf, cut = SplitSolid(cut,(surf,),cell,tolerance=Options.splitTolerance) - full.extend(newf) - - return full,cut - def FuseSolid(parts): if (len(parts)) <= 1: - if parts : - solid = parts[0] - else: - return None + if parts: + solid = parts[0] + else: + return None else: - try: - fused = parts[0].fuse(parts[1:]) - except: - fused = None - - if fused is not None: - try : - refinedfused = fused.removeSplitter() - except : - refinedfused = fused - - if refinedfused.isValid() : - solid = refinedfused - else : - if fused.isValid(): - solid = fused - else: - solid = Part.makeCompound(parts) - else: - solid = Part.makeCompound(parts) - - if solid.Volume < 0 : solid.reverse() + try: + fused = parts[0].fuse(parts[1:]) + except: + fused = None + + if fused is not None: + try: + refinedfused = fused.removeSplitter() + except: + refinedfused = fused + + if refinedfused.isValid(): + solid = refinedfused + else: + if fused.isValid(): + solid = fused + else: + solid = Part.makeCompound(parts) + else: + solid = Part.makeCompound(parts) + + if solid.Volume < 0: + solid.reverse() return solid def noOR(Seq): - if len(Seq.elements) == 1 : - #Seq.operator = 'AND' - return Seq - newOR=BoolSequence(operator='OR') - neg = [] - for e in Seq.elements: - AND = BoolSequence(operator='AND') - AND.append(*neg,e) - newOR.append(AND) - neg.append(-e) - return newOR - + if len(Seq.elements) == 1: + # Seq.operator = 'AND' + return Seq + newOR = BoolSequence(operator="OR") + neg = [] + for e in Seq.elements: + AND = BoolSequence(operator="AND") + AND.append(*neg, e) + newOR.append(AND) + neg.append(-e) + return newOR diff --git a/src/geouned/GEOReverse/Modules/options.py b/src/geouned/GEOReverse/Modules/options.py index 2efa2396..d738236f 100644 --- a/src/geouned/GEOReverse/Modules/options.py +++ b/src/geouned/GEOReverse/Modules/options.py @@ -1,3 +1,2 @@ -class Options : - splitTolerance = 1.e-2 - +class Options: + splitTolerance = 1.0e-2 diff --git a/src/geouned/GEOReverse/Modules/processInp.py b/src/geouned/GEOReverse/Modules/processInp.py index 3f300bb3..2507ea67 100644 --- a/src/geouned/GEOReverse/Modules/processInp.py +++ b/src/geouned/GEOReverse/Modules/processInp.py @@ -5,203 +5,208 @@ def setOptions(optionFile): - setting = {'fileIn' : '' , - 'fileOut' : '' , - 'outBox' : tuple() , - 'inFormat' : 'mcnp' , - - 'UStart' : 0 , - 'levelMax' : 'all' , - 'cell' : ('all',) , - 'mat' : ('exclude',(0,)) } - - - sectionNames =('Setting', 'Levels', 'Cells', 'Materials','Options') - - config = configparser.ConfigParser() - config.optionxform = str - config.read(optionFile) - - - fileData = False - for section in config.sections(): - if section not in sectionNames: - raise ValueError(f'{section} bad section name') - - if section == 'Setting' : - fileIn,fileOut,outBox,inFormat = getSetting(config) - - i = 0 - if fileIn is not None : - setting['fileIn'] = fileIn - i += 1 - - if fileOut is not None : - setting['fileOut'] = fileOut - i += 1 - - if outBox is not None : - setting['outBox'] = outBox - i += 1 - - if inFormat is not None : - setting['inFormat'] = inFormat - - if i==3 : fileData = True - - - elif section == 'Levels' : - UStart,levMax = getLevel(config) - if UStart is not None: setting['UStart'] = UStart - if levMax is not None: setting['levelMax'] = levMax - - - elif section in ('Cells','Materials'): - CMRange = getRange(section,config) - if CMRange is None : continue - if section == 'Cells': - setting['cell'] = CMRange - else: - setting['mat'] = CMRange + setting = { + "fileIn": "", + "fileOut": "", + "outBox": tuple(), + "inFormat": "mcnp", + "UStart": 0, + "levelMax": "all", + "cell": ("all",), + "mat": ("exclude", (0,)), + } + + sectionNames = ("Setting", "Levels", "Cells", "Materials", "Options") + + config = configparser.ConfigParser() + config.optionxform = str + config.read(optionFile) + + fileData = False + for section in config.sections(): + if section not in sectionNames: + raise ValueError(f"{section} bad section name") + + if section == "Setting": + fileIn, fileOut, outBox, inFormat = getSetting(config) + + i = 0 + if fileIn is not None: + setting["fileIn"] = fileIn + i += 1 + + if fileOut is not None: + setting["fileOut"] = fileOut + i += 1 + + if outBox is not None: + setting["outBox"] = outBox + i += 1 + + if inFormat is not None: + setting["inFormat"] = inFormat + + if i == 3: + fileData = True + + elif section == "Levels": + UStart, levMax = getLevel(config) + if UStart is not None: + setting["UStart"] = UStart + if levMax is not None: + setting["levelMax"] = levMax + + elif section in ("Cells", "Materials"): + CMRange = getRange(section, config) + if CMRange is None: + continue + if section == "Cells": + setting["cell"] = CMRange + else: + setting["mat"] = CMRange - elif section == 'Options' : - setSecOptions(config) + elif section == "Options": + setSecOptions(config) - if not fileData: - raise ValueError('missing input data in [Setting] section') + if not fileData: + raise ValueError("missing input data in [Setting] section") - return setting + return setting def getSetting(config): - fileIn, fileOut, outBox,inFormat = None, None, None, None - for key in config['Setting'].keys() : + fileIn, fileOut, outBox, inFormat = None, None, None, None + for key in config["Setting"].keys(): - if key in ['inputFile','mcnpFile']: - fileIn = config.get('Setting',key) - elif key == 'CADFile': - fileOut = config.get('Setting',key) - elif key == 'outBox': - outBox = getBoxData(config.get('Setting',key)) - elif key == 'inFormat': - inFormat = config.get('Setting',key) - else: - print('{} bad keyword. Ignored'.format(key)) + if key in ["inputFile", "mcnpFile"]: + fileIn = config.get("Setting", key) + elif key == "CADFile": + fileOut = config.get("Setting", key) + elif key == "outBox": + outBox = getBoxData(config.get("Setting", key)) + elif key == "inFormat": + inFormat = config.get("Setting", key) + else: + print("{} bad keyword. Ignored".format(key)) + + return fileIn, fileOut, outBox, inFormat - return fileIn, fileOut, outBox, inFormat - def getLevel(config): - UStart, levMax = None, None - for key in config['Levels'].keys() : - if key == 'levelMax': - levMax = config.get('Levels',key) - if levMax.lower() == 'all' : levMax = 'all' - elif levMax.isnumeric() : levMax = int(UStart) - else: - print('bad value for levMax') - elif key == 'UStart': - UStart = config.getint('Levels',key) - else: - print('{} bad keyword. Ignored'.format(key)) - - return UStart, levMax - - -def getRange(section,config): - rType = None - rawRange = None - for key in config[section].keys() : - if key == 'rangeType': - rType = config.get(section,key) - elif key == 'range': - rawRange = config.get(section,key) - else: - print('{} bad keyword. Ignored'.format(key)) - - - if rType is None : - return None - elif rType.lower() == 'all': - return ('all',) - - elif rType.lower() == 'exclude' or rType.lower() == 'include': - ctRange = getRangeData(rawRange) - if ctRange is None : - print('bad range in section {}'.format(section)) - return None - else: - return (rType.lower(),ctRange) - else: - return None + UStart, levMax = None, None + for key in config["Levels"].keys(): + if key == "levelMax": + levMax = config.get("Levels", key) + if levMax.lower() == "all": + levMax = "all" + elif levMax.isnumeric(): + levMax = int(UStart) + else: + print("bad value for levMax") + elif key == "UStart": + UStart = config.getint("Levels", key) + else: + print("{} bad keyword. Ignored".format(key)) + + return UStart, levMax + + +def getRange(section, config): + rType = None + rawRange = None + for key in config[section].keys(): + if key == "rangeType": + rType = config.get(section, key) + elif key == "range": + rawRange = config.get(section, key) + else: + print("{} bad keyword. Ignored".format(key)) + + if rType is None: + return None + elif rType.lower() == "all": + return ("all",) + + elif rType.lower() == "exclude" or rType.lower() == "include": + ctRange = getRangeData(rawRange) + if ctRange is None: + print("bad range in section {}".format(section)) + return None + else: + return (rType.lower(), ctRange) + else: + return None def getBoxData(string): - data = tuple(map(float,string.split())) - if len(data) != 6 : - raise ValueError('bad Outbox value number') + data = tuple(map(float, string.split())) + if len(data) != 6: + raise ValueError("bad Outbox value number") - elif( (data[0] > data[1]) or - (data[2] > data[3]) or - (data[4] > data[5]) ) : - raise ValueError('bad Outbox boundaries') + elif (data[0] > data[1]) or (data[2] > data[3]) or (data[4] > data[5]): + raise ValueError("bad Outbox boundaries") + + else: + return ( + 10 * data[0], + 10 * data[2], + 10 * data[4], + 10 * data[1], + 10 * data[3], + 10 * data[5], + ) - else: - return (10*data[0],10*data[2],10*data[4],10*data[1],10*data[3],10*data[5]) - def getRangeData(rawData): - if rawData is None : return None - - intervals = rawData.split(',') - rangeValues = set() - - for i in intervals: - if i.strip().isnumeric() : - rangeValues.add(int(i)) - else: - bounds = i.split(':') - if len(bounds) != 2: - print('bad range definition') - return None - else: - if bounds[0].strip().isnumeric() and bounds[1].strip().isnumeric(): - i1,i2 = map(int,bounds) - if i1 > i2 : - print('bad range definition') - return None - else: - rangeValues.update( range(i1,i2+1) ) + if rawData is None: + return None + + intervals = rawData.split(",") + rangeValues = set() + + for i in intervals: + if i.strip().isnumeric(): + rangeValues.add(int(i)) + else: + bounds = i.split(":") + if len(bounds) != 2: + print("bad range definition") + return None else: - print('bad range definition') - return None + if bounds[0].strip().isnumeric() and bounds[1].strip().isnumeric(): + i1, i2 = map(int, bounds) + if i1 > i2: + print("bad range definition") + return None + else: + rangeValues.update(range(i1, i2 + 1)) + else: + print("bad range definition") + return None + + rangeValues = list(rangeValues) + rangeValues.sort() + return tuple(rangeValues) - rangeValues = list(rangeValues) - rangeValues.sort() - return tuple(rangeValues) def setSecOptions(config): - for key in config['Options'].keys() : - if key == 'splitTolerance': - tolerance = config.getfloat('Options',key) - setattr(Options,key ,tolerance) - else: - print('{} bad keyword. Ignored'.format(key)) + for key in config["Options"].keys(): + if key == "splitTolerance": + tolerance = config.getfloat("Options", key) + setattr(Options, key, tolerance) + else: + print("{} bad keyword. Ignored".format(key)) - return + return def rangeGenerator(intervals): - for i in intervals: - if type(i) is tuple : - for v in range(i[0],i[1]+1): - yield v - else: - yield i - - - - + for i in intervals: + if type(i) is tuple: + for v in range(i[0], i[1] + 1): + yield v + else: + yield i diff --git a/src/geouned/GEOReverse/Modules/remh.py b/src/geouned/GEOReverse/Modules/remh.py index 701b322b..0abf384f 100644 --- a/src/geouned/GEOReverse/Modules/remh.py +++ b/src/geouned/GEOReverse/Modules/remh.py @@ -7,674 +7,770 @@ # used in card_split -celmat=re.compile(r"(?P^ *\d+) +(?P(\d+|like))",re.I) # identify first two entries on cell card (cell name, material) -grlnumber=re.compile(r"[-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?",re.I) # identify a general number form signed integer, float or exponential -param=re.compile(r"((^|\n {5})[\(\):\-\+\d+\.\# ]*)([\*a-z])",re.I) # identity begining of the paramter part of the cell card -likebut=re.compile(r"but",re.I) # identify likebut card -trans=re.compile(r"trcl|fill= *\d+[ c\$\n]*\(,",re.I) # identify tranformed card +celmat = re.compile( + r"(?P^ *\d+) +(?P(\d+|like))", re.I +) # identify first two entries on cell card (cell name, material) +grlnumber = re.compile( + r"[-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?", re.I +) # identify a general number form signed integer, float or exponential +param = re.compile( + r"((^|\n {5})[\(\):\-\+\d+\.\# ]*)([\*a-z])", re.I +) # identity begining of the paramter part of the cell card +likebut = re.compile(r"but", re.I) # identify likebut card +trans = re.compile(r"trcl|fill= *\d+[ c\$\n]*\(,", re.I) # identify tranformed card unsignedint = re.compile(r"\d+") # user in get_stat function -reword=re.compile(r"(\d+|\(|\)|:|\#)") # word identification in cell line -compcell=re.compile(r"\#\d") # identify hashcell complement operator +reword = re.compile(r"(\d+|\(|\)|:|\#)") # word identification in cell line +compcell = re.compile(r"\#\d") # identify hashcell complement operator # used in Complementary operator function -number=re.compile(r"(?P[-+]?\d+)") # signed (+-) (or not) numbers +number = re.compile(r"(?P[-+]?\d+)") # signed (+-) (or not) numbers # leftp=re.compile(r"^ *(?P[-\d\(\#])",re.M) # identify first valid character -leftp=re.compile(r"(?P[-+\d\(\#])",re.I) # identify first valid character -rightp=re.compile(r"(?P[ c\$\n]*$)",re.I) # identify last valid character -#interblk=re.compile(r"(?P\d)(?P(( +| *(\$)?\n(C\n)* *)[-+]?\d))") # two numbers separated by blank (or newline or comments) -#intercls=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)[-+]?\d))") # closed parenthesis followed by number -#interopn=re.compile(r"(?P\d)(?P(( *| *(\$)?\n(C\n)* *)\())") # number followed by opened parenthesis -#intercop=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)\())") # closed parenthesis followed by opened parenthesis -interblk=re.compile(r"(?P\d)(?P(( +| *((\n *)?\$|\nC)*\n *)[-+]?\d))") # two numbers separated by blank (or newline or comments) -intercls=re.compile(r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)[-+]?\d))") # closed parenthesis followed by number -interopn=re.compile(r"(?P\d)(?P(( *| *((\n *)?\$|\nC)*\n *)\())") # number followed by opened parenthesis -intercop=re.compile(r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)\())") # closed parenthesis followed by opened parenthesis -colonamp=re.compile(r"[:&]") # colon or amperserand +leftp = re.compile(r"(?P[-+\d\(\#])", re.I) # identify first valid character +rightp = re.compile(r"(?P[ c\$\n]*$)", re.I) # identify last valid character +# interblk=re.compile(r"(?P\d)(?P(( +| *(\$)?\n(C\n)* *)[-+]?\d))") # two numbers separated by blank (or newline or comments) +# intercls=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)[-+]?\d))") # closed parenthesis followed by number +# interopn=re.compile(r"(?P\d)(?P(( *| *(\$)?\n(C\n)* *)\())") # number followed by opened parenthesis +# intercop=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)\())") # closed parenthesis followed by opened parenthesis +interblk = re.compile( + r"(?P\d)(?P(( +| *((\n *)?\$|\nC)*\n *)[-+]?\d))" +) # two numbers separated by blank (or newline or comments) +intercls = re.compile( + r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)[-+]?\d))" +) # closed parenthesis followed by number +interopn = re.compile( + r"(?P\d)(?P(( *| *((\n *)?\$|\nC)*\n *)\())" +) # number followed by opened parenthesis +intercop = re.compile( + r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)\())" +) # closed parenthesis followed by opened parenthesis +colonamp = re.compile(r"[:&]") # colon or amperserand # used for remove redundant parenthesis function -mostinner=re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses -bracketsemi=re.compile(r"[\]\[;]") # square bracket or semicolon -blnkline=re.compile(r"^ *\n",re.M) # identify blank line -contline=re.compile(r"\n {0,4}(?P[^c^ ])",re.I) # identify character other than 'C' in fisrt 5 columns -comdollar=re.compile(r"\n(?P *)\$") # identify dollar on 'blank line' -startgeom=re.compile(r"(?P^ *)(?P[\-\+\d])") # identify beginning of the geomtric part -endgeom=re.compile(r"(?P\d)(?P *((\n *)?\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part -#endgeom=re.compile(r"(?P\d)(?P *(\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part +mostinner = re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses +bracketsemi = re.compile(r"[\]\[;]") # square bracket or semicolon +blnkline = re.compile(r"^ *\n", re.M) # identify blank line +contline = re.compile( + r"\n {0,4}(?P[^c^ ])", re.I +) # identify character other than 'C' in fisrt 5 columns +comdollar = re.compile(r"\n(?P *)\$") # identify dollar on 'blank line' +startgeom = re.compile( + r"(?P^ *)(?P[\-\+\d])" +) # identify beginning of the geomtric part +endgeom = re.compile( + r"(?P\d)(?P *((\n *)?\$|\nc)?(\n *)?$)", re.I +) # identify end of the geomtric part +# endgeom=re.compile(r"(?P\d)(?P *(\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part # other -rehash=re.compile(r"# *(\d+|\()") # find beginning of complementary operator (both cell and surf) -parent=re.compile(r"[\(|\)]") # position of open and close parenthesis (get_hashcell) -gline=re.compile(r"(^ ?[\(\):\-\+\d+\.\# ]+|\n {5}[\(\):\-\+\d+\.\# ]+)",re.I) # valid geometric part of the line (remove/restore_comments) -comments=re.compile(r"((\n *)?\$|\n *c)",re.I) # begining of comment part (remove/restore_comments) -#comments=re.compile(r"\$|\n *c",re.I) # begining of comment part (remove/restore_comments) -celtrsf = re.compile(r"TRCL *= *",re.I) -celuniverse = re.compile(r"U *= *",re.I) -celfill = re.compile(r"FILL *= *",re.I) -trfnumber=re.compile(r"([-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?)|\)",re.I) # search for general number or close bracket ) -likemat=re.compile(r"MAT *= *(?P\d+)",re.I) # identify material value on like but card -dollar = re.compile(r"\$.*\n",re.I) +rehash = re.compile( + r"# *(\d+|\()" +) # find beginning of complementary operator (both cell and surf) +parent = re.compile(r"[\(|\)]") # position of open and close parenthesis (get_hashcell) +gline = re.compile( + r"(^ ?[\(\):\-\+\d+\.\# ]+|\n {5}[\(\):\-\+\d+\.\# ]+)", re.I +) # valid geometric part of the line (remove/restore_comments) +comments = re.compile( + r"((\n *)?\$|\n *c)", re.I +) # begining of comment part (remove/restore_comments) +# comments=re.compile(r"\$|\n *c",re.I) # begining of comment part (remove/restore_comments) +celtrsf = re.compile(r"TRCL *= *", re.I) +celuniverse = re.compile(r"U *= *", re.I) +celfill = re.compile(r"FILL *= *", re.I) +trfnumber = re.compile( + r"([-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?)|\)", re.I +) # search for general number or close bracket ) +likemat = re.compile( + r"MAT *= *(?P\d+)", re.I +) # identify material value on like but card +dollar = re.compile(r"\$.*\n", re.I) + + ############################################################ # Auxiliary functions used in regular expresion functions # ############################################################ def remove_dollar(string): - m = dollar.search(string) - while m: - string = string[0:m.start()] + ' ' + string[m.end():] - m = dollar.search(string) - return string - - -def redundant(m,geom): - """ check if the inner parentheses are redundant """ - term = m.group() - - # Find first valid character at the left of the parenthese - hashsmb = False - leftOK= True - left = m.start()-1 - while left > -1: - if geom[left] in ('\n','C','$',' '): - left -= 1 - else: - if geom[left] not in ('(',':') : leftOK = False - if (geom[left] == '#') : hashsmb = True - break - - # if hash symbol found means parentheses delimits complementary - # cell defined with surface. Theses parentheses are not redundants - if hashsmb : return False - - # check if no ':' (or) are inside the parenthese - # if not, parentheses are redundants - if (term.find(':') == -1) : return True - - # Find first valid character at the right of the parenthese - rightOK= True - right = m.end() - while right < len(geom) : - if geom[right] in ('\n','C','$',' '): - right += 1 - else: - if geom[right] not in (')',':') : rightOK = False - break - - # if parentheses are like: - # {( or : } ( ....... ) {) or :} - # parentheses are redundants - - if leftOK and rightOK : - return True - else: - return False + m = dollar.search(string) + while m: + string = string[0 : m.start()] + " " + string[m.end() :] + m = dollar.search(string) + return string + + +def redundant(m, geom): + """check if the inner parentheses are redundant""" + term = m.group() + + # Find first valid character at the left of the parenthese + hashsmb = False + leftOK = True + left = m.start() - 1 + while left > -1: + if geom[left] in ("\n", "C", "$", " "): + left -= 1 + else: + if geom[left] not in ("(", ":"): + leftOK = False + if geom[left] == "#": + hashsmb = True + break + + # if hash symbol found means parentheses delimits complementary + # cell defined with surface. Theses parentheses are not redundants + if hashsmb: + return False + + # check if no ':' (or) are inside the parenthese + # if not, parentheses are redundants + if term.find(":") == -1: + return True + + # Find first valid character at the right of the parenthese + rightOK = True + right = m.end() + while right < len(geom): + if geom[right] in ("\n", "C", "$", " "): + right += 1 + else: + if geom[right] not in (")", ":"): + rightOK = False + break + + # if parentheses are like: + # {( or : } ( ....... ) {) or :} + # parentheses are redundants + + if leftOK and rightOK: + return True + else: + return False + # function used in Regular expresion sub function # function user in complementary function # change the sign of the number def chgsign(m): - num=m.group(0) - if num[0] == '-': - return num[1:] - if num[0] == '+': - return '-'+num[1:] + num = m.group(0) + if num[0] == "-": + return num[1:] + if num[0] == "+": + return "-" + num[1:] else: - return '-'+num + return "-" + num + # function used in Regular expersion sub function # function user in complementary function # change ':' in ')(' and # '&' in ':' def repl_inter_union(m): - if m.group(0) == ':' : - return ')(' - else : - return ':' + if m.group(0) == ":": + return ")(" + else: + return ":" + # function used in Regular expersion sub function # function user in remove_redundant function # restore curve parentheses and colon characters def reverse_repl(m): - symb=m.group(0) - if symb == '[' : - return '(' - elif symb == ']' : - return ')' - else : - return ':' + symb = m.group(0) + if symb == "[": + return "(" + elif symb == "]": + return ")" + else: + return ":" + + ############################################################ -def complementary(ccell,outter=True) : - """ return the complementary cell """ + +def complementary(ccell, outter=True): + """return the complementary cell""" wrkcell = cline(ccell.str) - if (wrkcell.str[-1] == '\n') : wrkcell.str=wrkcell.str[:-1] + if wrkcell.str[-1] == "\n": + wrkcell.str = wrkcell.str[:-1] # simplify comment in geometry string wrkcell.remove_comments() # insert external parenthesis - wrkcell.str= re.sub(leftp,r"(\g",wrkcell.str,count=1) - wrkcell.str= re.sub(rightp,r")\g",wrkcell.str,count=1) + wrkcell.str = re.sub(leftp, r"(\g", wrkcell.str, count=1) + wrkcell.str = re.sub(rightp, r")\g", wrkcell.str, count=1) # insert '&' as intersection operator - wrkcell.str=re.sub(interblk,r"\g&\g",wrkcell.str) # change intersection separate by blank space ie: "number number" - wrkcell.str=re.sub(interblk,r"\g&\g",wrkcell.str) # 2nd pass intersection blank space (require 2 pass) - wrkcell.str=re.sub(intercls,r"\g&\g",wrkcell.str) # change intersection close parenthesis ie: ") number" - wrkcell.str=re.sub(interopn,r"\g&\g",wrkcell.str) # change intersection open parenthesis ie: "number (" - wrkcell.str=re.sub(intercop,r"\g&\g",wrkcell.str) # change intersection close-open parenthesis ie: ") (" + wrkcell.str = re.sub( + interblk, r"\g&\g", wrkcell.str + ) # change intersection separate by blank space ie: "number number" + wrkcell.str = re.sub( + interblk, r"\g&\g", wrkcell.str + ) # 2nd pass intersection blank space (require 2 pass) + wrkcell.str = re.sub( + intercls, r"\g&\g", wrkcell.str + ) # change intersection close parenthesis ie: ") number" + wrkcell.str = re.sub( + interopn, r"\g&\g", wrkcell.str + ) # change intersection open parenthesis ie: "number (" + wrkcell.str = re.sub( + intercop, r"\g&\g", wrkcell.str + ) # change intersection close-open parenthesis ie: ") (" # invert operators # substitute colon by ')(' and '&' by colon - wrkcell.str=re.sub(colonamp,repl_inter_union,wrkcell.str) + wrkcell.str = re.sub(colonamp, repl_inter_union, wrkcell.str) wrkcell.remove_redundant(remove_com=False) # Change signs - wrkcell.str=re.sub(number,chgsign,wrkcell.str) + wrkcell.str = re.sub(number, chgsign, wrkcell.str) # insert external parenthesis - if outter : - wrkcell.str= re.sub(leftp,r"(\g",wrkcell.str,count=1) - wrkcell.str= re.sub(rightp,r")\g",wrkcell.str,count=1) + if outter: + wrkcell.str = re.sub(leftp, r"(\g", wrkcell.str, count=1) + wrkcell.str = re.sub(rightp, r")\g", wrkcell.str, count=1) -# restore original comments + # restore original comments wrkcell.restore_comments() return wrkcell.str + ############################################################ -class cline(): - def __init__(self,line): - self.str=line - - def copy(self): - return cline(self.str) - - def getSurfacesNumbers(self): - s = set(unsignedint.findall(self.str)) - return tuple(map(int,s)) - - def remove_multispace(self): - self.str.strip() - self.str = re.sub(r' +',' ',self.str) - - def remove_cr(self): - self.str=re.sub(r'\n',' ',self.str) - return - - def remove_comments(self,full=False): - """ Remove the text of the comment. The symbol 'C' or '$' is -kept in the line if 'full' option is False (default)""" - celltab = re.split(gline,self.str) - cont=True - while cont: - try: - celltab.remove('') - except: - cont=False - - self.__comtab__=[] - for i,s in enumerate(celltab) : - c = comments.match(s) - if ( c ): - if not full : - self.__comtab__.append(s) - celltab[i] = c.group() +class cline: + def __init__(self, line): + self.str = line + + def copy(self): + return cline(self.str) + + def getSurfacesNumbers(self): + s = set(unsignedint.findall(self.str)) + return tuple(map(int, s)) + + def remove_multispace(self): + self.str.strip() + self.str = re.sub(r" +", " ", self.str) + + def remove_cr(self): + self.str = re.sub(r"\n", " ", self.str) + return + + def remove_comments(self, full=False): + """Remove the text of the comment. The symbol 'C' or '$' is + kept in the line if 'full' option is False (default)""" + celltab = re.split(gline, self.str) + cont = True + while cont: + try: + celltab.remove("") + except: + cont = False + + self.__comtab__ = [] + for i, s in enumerate(celltab): + c = comments.match(s) + if c: + if not full: + self.__comtab__.append(s) + celltab[i] = c.group() + else: + celltab[i] = "" + + self.str = "".join(celltab) + return + + def restore_comments(self): + """Restore the text of the comment.""" + celltab = re.split(gline, self.str) + cont = True + while cont: + try: + celltab.remove("") + except: + cont = False + + j = 0 + for i, s in enumerate(celltab): + c = comments.match(s) + if c: + celltab[i] = self.__comtab__[j] + j += 1 + + self.str = "".join(celltab) + return + + def outterTerms(self): + cgeom = cline(self.str) + + cgeom.remove_comments(full=True) + cgeom.remove_redundant() + cgeom.remove_cr() + geom = cgeom.str + + # Loop until no redundant parentheses are found + cont = True + + while cont: + # Loop over most inner parentheses + pos = 0 + cont = False + while True: + m = mostinner.search(geom, pos) + if not m: + break + cont = True + if redundant(m, geom): + # remove redundant parentheses + geom = ( + geom[: m.start()] + + " " + + geom[m.start() + 1 : m.end() - 1] + + " " + + geom[m.end() :] + ) + else: + # replace no redundant parentheses by 0 and : by ; + zeros = "0" * (m.end() - m.start()) + geom = geom[: m.start()] + zeros + geom[m.end() :] + + pos = m.end() + + if ":" in geom: + terms = [] + pos = 0 + while True: + newpos = geom.find(":", pos) + if newpos == -1: + terms.append(cgeom.str[pos:].strip()) + break + terms.append(cgeom.str[pos:newpos].strip()) + pos = newpos + 1 + return (terms, "OR") + else: + terms = [] + pos = 0 + while True: + m = number.search(geom, pos) + if not m: + break + terms.append(cgeom.str[m.start() : m.end()]) + pos = m.end() + return (terms, "AND") + + def remove_redundant(self, remove_com=True, remopt="nochg"): + """return cell without redundant parenthesis""" + + # simplify comment in geometry string + if remove_com: + self.remove_comments() + geom = self.str + + if remopt == "nochg" and geom.find(")") == -1: + self.removedp = None + return + + porg = self.countP() + # Loop until no redundant parentheses are found + cont = True + while cont: + # Loop over most inner parentheses + pos = 0 + cont = False + while True: + m = mostinner.search(geom, pos) + if not m: + break + cont = True + if redundant(m, geom): + # remove redundant parentheses + geom = ( + geom[: m.start()] + + " " + + geom[m.start() + 1 : m.end() - 1] + + " " + + geom[m.end() :] + ) + else: + # replace no redundant parentheses by [] and : by ; + term = geom[m.start() + 1 : m.end() - 1].replace(":", ";") + geom = geom[: m.start()] + "[" + term + "]" + geom[m.end() :] + pos = m.end() + + # restore curved parenthesis and colon + geom = re.sub(bracketsemi, reverse_repl, geom) + + # remove possible blank line + geom = re.sub(blnkline, "", geom) + + # ensure 5 blanks continous line + geom = re.sub(contline, r"\n \g", geom) + + if remopt != "all": + # add parenthesis to set geom as MCNP complex cell + if geom.find(":") == -1 and geom.find("#") == -1: + geom = re.sub(startgeom, r"\g(\g", geom) + geom = re.sub(endgeom, r"\g)\g", geom) + + # restore original comments + self.str = geom + pmod = self.countP() + if remove_com: + self.restore_comments() + + # subtitute comment $ with blank line + self.str = re.sub(comdollar, r"\nC\g", self.str) + pdiff = [x - y for x, y in zip(pmod, porg)] + self.removedp = pdiff + return + + def get_hashcell(self, start=0): + """get the complementary cell defined with surfaces combination""" + count = 0 + for p in parent.finditer(self.str, start): + if p.group() == "(": + count += 1 else: - celltab[i] = '' - - self.str=''.join(celltab) - return - - def restore_comments(self): - """ Restore the text of the comment.""" - celltab = re.split(gline,self.str) - cont=True - while cont: - try: - celltab.remove('') - except: - cont=False - - j = 0 - for i,s in enumerate(celltab) : - c = comments.match(s) - if ( c ): - celltab[i] = self.__comtab__[j] - j += 1 - - self.str = ''.join(celltab) - return - - def outterTerms(self): - cgeom = cline(self.str) - - cgeom.remove_comments(full=True) - cgeom.remove_redundant() - cgeom.remove_cr() - geom = cgeom.str - - # Loop until no redundant parentheses are found - cont = True - - while cont: - # Loop over most inner parentheses - pos = 0 - cont = False - while True : - m = mostinner.search(geom,pos) - if not m : break - cont = True - if redundant(m,geom): - # remove redundant parentheses - geom = geom[:m.start()]+ ' ' + geom[m.start()+1:m.end()-1]+ ' ' + geom[m.end():] - else: - # replace no redundant parentheses by 0 and : by ; - zeros = '0'* (m.end()-m.start()) - geom = geom[:m.start()] + zeros + geom[m.end():] - - pos = m.end() - - if ':' in geom : - terms = [] - pos = 0 - while True : - newpos = geom.find(':',pos) - if newpos == -1 : - terms.append(cgeom.str[pos:].strip()) - break - terms.append(cgeom.str[pos:newpos].strip()) - pos = newpos + 1 - return (terms,'OR') - else: - terms = [] - pos = 0 - while True: - m = number.search(geom,pos) - if not m : break - terms.append(cgeom.str[m.start():m.end()]) - pos = m.end() - return (terms,'AND') - - def remove_redundant(self,remove_com=True,remopt='nochg'): - """ return cell without redundant parenthesis """ - - #simplify comment in geometry string - if remove_com: self.remove_comments() - geom = self.str - - if (remopt == 'nochg' and geom.find(')') == -1 ) : - self.removedp = None - return - - porg=self.countP() - # Loop until no redundant parentheses are found - cont = True - while cont: - # Loop over most inner parentheses - pos = 0 - cont = False - while True : - m = mostinner.search(geom,pos) - if not m : break - cont = True - if redundant(m,geom): - # remove redundant parentheses - geom = geom[:m.start()]+ ' ' + geom[m.start()+1:m.end()-1]+ ' ' + geom[m.end():] - else: - # replace no redundant parentheses by [] and : by ; - term = geom[m.start()+1:m.end()-1].replace(':',';') - geom = geom[:m.start()] + '[' + term + ']' + geom[m.end():] - pos = m.end() - - # restore curved parenthesis and colon - geom=re.sub(bracketsemi,reverse_repl,geom) - - # remove possible blank line - geom=re.sub(blnkline,'',geom) - - # ensure 5 blanks continous line - geom=re.sub(contline, r'\n \g',geom) - - if remopt != 'all' : - # add parenthesis to set geom as MCNP complex cell - if geom.find(':') == -1 and geom.find('#') == -1 : - geom=re.sub(startgeom,r'\g(\g',geom) - geom=re.sub(endgeom,r'\g)\g',geom) - - # restore original comments - self.str = geom - pmod=self.countP() - if remove_com: self.restore_comments() - - # subtitute comment $ with blank line - self.str=re.sub(comdollar,r'\nC\g',self.str) - pdiff = [x-y for x,y in zip(pmod,porg)] - self.removedp=pdiff - return - - - def get_hashcell(self,start=0): - """ get the complementary cell defined with surfaces combination """ - count=0 - for p in parent.finditer(self.str,start): - if (p.group() == '(') : - count += 1 - else: - count -= 1 - if (count == 0 ): - end=p.end() - cell=cline(self.str[start+1:end]) - break - return cell,end - - def replace(self,surf,new,pos = 0): - - s1 = str(surf) - s2 = str(new) - m = unsignedint.search(self.str,pos) - if not m : - print('no number in line') - return -1 - if surf == new : - return m.start()+len(s2) - elif m.group() == s1 : - self.str = self.str[0:m.start()] + s2 + self.str[m.end():] - return m.start()+len(s2) - else: - print('number {} not found'.format(surf)) - return -1 - - - def countP(self): - lp=self.str.count('(') - rp=self.str.count(')') - return (lp,rp) - - def SplitCell(self): - self.remove_redundant(remopt='all') - self.remove_comments() - geom = self.str - self.restore_comments() - - # insert '&' as intersection operator - geom=re.sub(interblk,r"\g&\g",geom) # change intersection separate by blank space ie: "number number" - geom=re.sub(interblk,r"\g&\g",geom) # 2nd pass intersection blank space (require 2 pass) - geom=re.sub(intercls,r"\g&\g",geom) # change intersection close parenthesis ie: ") number" - geom=re.sub(interopn,r"\g&\g",geom) # change intersection open parenthesis ie: "number (" - geom=re.sub(intercop,r"\g&\g",geom) # change intersection close-open parenthesis ie: ") (" - - - parts=[] - block = '' - iopen = 0 - ctype = None - - for c in geom : - if c == '\n': continue - if c in [':','&'] : - if iopen == 0 : - if ctype == None : - if c == '&' : ctype ='AND' - if c == ':' : ctype ='OR' - if ctype == 'AND' and c==':' : - ctype='OR' + count -= 1 + if count == 0: + end = p.end() + cell = cline(self.str[start + 1 : end]) break - elif c == '(' : - iopen += 1 - elif c == ')' : - iopen -= 1 - - for c in geom: - if c == '\n': continue - if c in [':','&'] : - if iopen == 0 : - if ctype == 'AND' and c == '&' : - parts.append(block) - block = '' - if ctype == 'OR' and c == ':' : - parts.append(block) - block = '' - else: - if c != '&' : - block = block + c - else : - if c != '&' : - block = block + c - if c == '(' : - iopen += 1 - elif c == ')' : - iopen -= 1 - parts.append(block) - return parts,ctype - - + return cell, end + + def replace(self, surf, new, pos=0): + + s1 = str(surf) + s2 = str(new) + m = unsignedint.search(self.str, pos) + if not m: + print("no number in line") + return -1 + if surf == new: + return m.start() + len(s2) + elif m.group() == s1: + self.str = self.str[0 : m.start()] + s2 + self.str[m.end() :] + return m.start() + len(s2) + else: + print("number {} not found".format(surf)) + return -1 + + def countP(self): + lp = self.str.count("(") + rp = self.str.count(")") + return (lp, rp) + + def SplitCell(self): + self.remove_redundant(remopt="all") + self.remove_comments() + geom = self.str + self.restore_comments() + + # insert '&' as intersection operator + geom = re.sub( + interblk, r"\g&\g", geom + ) # change intersection separate by blank space ie: "number number" + geom = re.sub( + interblk, r"\g&\g", geom + ) # 2nd pass intersection blank space (require 2 pass) + geom = re.sub( + intercls, r"\g&\g", geom + ) # change intersection close parenthesis ie: ") number" + geom = re.sub( + interopn, r"\g&\g", geom + ) # change intersection open parenthesis ie: "number (" + geom = re.sub( + intercop, r"\g&\g", geom + ) # change intersection close-open parenthesis ie: ") (" + + parts = [] + block = "" + iopen = 0 + ctype = None + + for c in geom: + if c == "\n": + continue + if c in [":", "&"]: + if iopen == 0: + if ctype == None: + if c == "&": + ctype = "AND" + if c == ":": + ctype = "OR" + if ctype == "AND" and c == ":": + ctype = "OR" + break + elif c == "(": + iopen += 1 + elif c == ")": + iopen -= 1 + + for c in geom: + if c == "\n": + continue + if c in [":", "&"]: + if iopen == 0: + if ctype == "AND" and c == "&": + parts.append(block) + block = "" + if ctype == "OR" and c == ":": + parts.append(block) + block = "" + else: + if c != "&": + block = block + c + else: + if c != "&": + block = block + c + if c == "(": + iopen += 1 + elif c == ")": + iopen -= 1 + parts.append(block) + return parts, ctype + + ############################################################ -class cell_card_string(): - - def __init__(self,card): - self.stat={ 'word' : None ,\ - 'hashcell' : None ,\ - 'hashsurf' : None ,\ - 'hash' : None } - - self.name = None - self.MAT = None - self.U = None - self.FILL = None - self.TR = None - self.TRCL = None - self.__card_split__(card) - self.__get_data__() - - def __card_split__(self,cardin): - """ Split the card string in three parts : - - headstr : string containing the cell name, mat number and density (if mat != 0) of the cell - - geom : cline class containing the part of the geometric definition of the cell - - param : cline class containing the cell parameters part - hproc is true if the complementary operator of the cell can be substituted""" - - m=celmat.match(cardin) - self.name = int(m.group('cel')) - self.hproc=True - self.likeCell = None - if m.group('scnd').lower() == 'like': - self.headstr = cardin[:m.start('scnd')] - s = likebut.search(cardin,m.end('scnd')) - self.geom = cline(cardin[m.start('scnd'):s.end()]) - self.parm = cline(cardin[s.end():]) - self.hproc=False - mc = unsignedint.search(self.geom.str) - self.likeCell = int(mc.group()) - ml = likemat.search(self.parm.str) - if ml : - self.MAT = int(ml.group('mat')) - elif m.group('scnd') == '0': - cstart=m.end('scnd') - self.MAT = 0 - else : - self.MAT = int(m.group('scnd')) - p=grlnumber.search(cardin,m.end('scnd')) - cstart=p.end() - - if self.hproc: - self.headstr = cardin[:cstart] - cellcard=cline(cardin[cstart:]) - cellcard.remove_comments() - m = param.search(cellcard.str) - if m: - linecut = cellcard.str[:m.end(1)].count('\n') - else: - linecut = cellcard.str.count('\n') - - cellcard.restore_comments() - - # look for the last line geometry string - if linecut != 0 : - pos=0 - c=0 - while c != linecut : - pos=cellcard.str.find('\n',pos) - c += 1 - m = param.search(cellcard.str,pos) - - if m: - start = m.end(1) - self.geom = cline(cellcard.str[:start]) - self.parm = cline(cellcard.str[start:]) - - # look for transformation in cell parameters - self.parm.remove_comments() - m = trans.search(self.parm.str) - if m : self.hproc = False - self.parm.restore_comments() - else : - self.geom = cline(cellcard.str) - self.parm = cline('') - - return - - def __get_data__(self): - - - mt = celtrsf.search(self.parm.str) - if mt : - string = self.parm.str[mt.end():] - m = grlnumber.search(string) - - if self.parm.str[mt.start()-1] == '*' : - angle = True - else: - angle = False - - if '(' in string[:m.end()] : - self.TRCL=[] - pos = 0 - while True: - m = trfnumber.search(string,pos) - pos = m.end() - if not m or m.group() == ')' : break - self.TRCL.append(float(m.group())) - if angle and len(self.TRCL) > 3 : - self.TRCL[3:12] = list(map(math.radians,self.TRCL[3:12] )) - self.TRCL[3:12] = list(map(math.cos,self.TRCL[3:12])) - else: - self.TRCL = int(m.group()) - - - # get universe number - m = celuniverse.search(self.parm.str) - if m: - m = grlnumber.search(self.parm.str[m.end():]) - self.U = int(m.group()) - - # get Fill number - mf = celfill.search(self.parm.str) - if mf : - fillstring = remove_dollar(self.parm.str[mf.end():]) - m = grlnumber.search(fillstring) - self.FILL = int(m.group()) - - # look for transformation after fill card - m = re.search(r" *\(",fillstring) - if m : - if self.parm.str[mf.start()-1] == '*' : - angle = True - else: - angle = False - - fillstring = fillstring[m.end():] - m = re.search(r"\)",fillstring) - string = fillstring[:m.start()] - tr = string.split() - if len(tr) == 1 : - self.TR = int(tr[0]) - else: - self.TR = list(map(float,tr)) - if angle and len(self.TR) > 3 : - self.TR[3:12] = list(map(math.radians,self.TR[3:12] )) - self.TR[3:12] = list(map(math.cos,self.TR[3:12])) - - - def get_stat(self,remove_com=True): - """ Count and return the number of words and hashes on the line.""" - - if remove_com : self.geom.remove_comments() - - words = len(reword.findall(self.geom.str)) - hashcell = len(compcell.findall(self.geom.str)) - hashtot = self.geom.str.count('#') - - self.stat={ 'words' : words, - 'hash' : hashtot, - 'hascell' : hashcell, - 'hashsur' : hashtot-hashcell } - if remove_com : self.geom.restore_comments() - return [words, hashtot, hashcell, hashtot-hashcell] - - def get_lines(self): - """ split string card in the format Cards.lines of Cards object""" - card=self.headstr + self.geom.str + self.parm.str - - # remove blank line introduced during the process - card=re.sub(blnkline,'',card) - - # subtitute comment $ with blank line - card=re.sub(comdollar, r'\nC\g',card) - - # ensure 5 blanks continous line - card=re.sub(contline, r'\n \g',card) - - if (card[-1] == '\n') : card=card[:-1] - return list(map(lambda x: x+'\n' ,card.split('\n'))) - - -def remove_hash(cards,cname,keepComments=True): - def remove(card,cname,keepComments): - """ remove complementary operator and subtitute by complementary cell """ - if "parser.Card" in str(type(card)): - celline=''.join(card.lines) - cardstr = cell_card_string(celline) - else: - cardstr = card - cardstr.get_stat() - cardstr.geom.remove_comments(full=not keepComments) - if (not cardstr.hproc) or (cardstr.stat['hash'] == 0) :return cardstr.geom # no complementary operator or cannot be # cannot be removed - cell=cline(cardstr.geom.str) - # find all operators in the cell and - # substitute all complementary operators - # locate object in list to reverse iteration - hashgroup=[] - start = 0 - - lencel = len(cell.str) - while True: - ic = cell.str.lower().find('c',start) - idol = cell.str.find('$',start) - if idol < 0 : idol = lencel - if ic < 0 : ic = lencel - end = min(idol, ic) - for m in (rehash.finditer(cell.str,start,end)): - hashgroup.append(m) - start = cell.str.find('\n',end) - if (end == lencel) : break - - for m in reversed(hashgroup): - start=m.start() - if m.group(1) == '(': # complementary cell defined as surface intersections - hcell,end=cell.get_hashcell(start) - cellmod=cell.str[0:start] + complementary(hcell) + cell.str[end:] - cell = cline(cellmod) - else: - hcname=int(m.group(1)) # complementary cell defined with other cell index - newdef = remove(cards[hcname],hcname,keepComments) # remove complementary operator in new cell if necessary - end=m.end() - cellmod=cell.str[0:start] \ - + ' '+complementary(newdef)+ ' ' \ - + cell.str[end:] - cell = cline(cellmod) - return cell - - newcell = remove(cards[cname],cname,keepComments) - return cline(newcell.str) +class cell_card_string: + + def __init__(self, card): + self.stat = {"word": None, "hashcell": None, "hashsurf": None, "hash": None} + + self.name = None + self.MAT = None + self.U = None + self.FILL = None + self.TR = None + self.TRCL = None + self.__card_split__(card) + self.__get_data__() + + def __card_split__(self, cardin): + """Split the card string in three parts : + - headstr : string containing the cell name, mat number and density (if mat != 0) of the cell + - geom : cline class containing the part of the geometric definition of the cell + - param : cline class containing the cell parameters part + hproc is true if the complementary operator of the cell can be substituted""" + + m = celmat.match(cardin) + self.name = int(m.group("cel")) + self.hproc = True + self.likeCell = None + if m.group("scnd").lower() == "like": + self.headstr = cardin[: m.start("scnd")] + s = likebut.search(cardin, m.end("scnd")) + self.geom = cline(cardin[m.start("scnd") : s.end()]) + self.parm = cline(cardin[s.end() :]) + self.hproc = False + mc = unsignedint.search(self.geom.str) + self.likeCell = int(mc.group()) + ml = likemat.search(self.parm.str) + if ml: + self.MAT = int(ml.group("mat")) + elif m.group("scnd") == "0": + cstart = m.end("scnd") + self.MAT = 0 + else: + self.MAT = int(m.group("scnd")) + p = grlnumber.search(cardin, m.end("scnd")) + cstart = p.end() + + if self.hproc: + self.headstr = cardin[:cstart] + cellcard = cline(cardin[cstart:]) + cellcard.remove_comments() + m = param.search(cellcard.str) + if m: + linecut = cellcard.str[: m.end(1)].count("\n") + else: + linecut = cellcard.str.count("\n") + + cellcard.restore_comments() + + # look for the last line geometry string + if linecut != 0: + pos = 0 + c = 0 + while c != linecut: + pos = cellcard.str.find("\n", pos) + c += 1 + m = param.search(cellcard.str, pos) + + if m: + start = m.end(1) + self.geom = cline(cellcard.str[:start]) + self.parm = cline(cellcard.str[start:]) + + # look for transformation in cell parameters + self.parm.remove_comments() + m = trans.search(self.parm.str) + if m: + self.hproc = False + self.parm.restore_comments() + else: + self.geom = cline(cellcard.str) + self.parm = cline("") + return + def __get_data__(self): + + mt = celtrsf.search(self.parm.str) + if mt: + string = self.parm.str[mt.end() :] + m = grlnumber.search(string) + + if self.parm.str[mt.start() - 1] == "*": + angle = True + else: + angle = False + + if "(" in string[: m.end()]: + self.TRCL = [] + pos = 0 + while True: + m = trfnumber.search(string, pos) + pos = m.end() + if not m or m.group() == ")": + break + self.TRCL.append(float(m.group())) + if angle and len(self.TRCL) > 3: + self.TRCL[3:12] = list(map(math.radians, self.TRCL[3:12])) + self.TRCL[3:12] = list(map(math.cos, self.TRCL[3:12])) + else: + self.TRCL = int(m.group()) + + # get universe number + m = celuniverse.search(self.parm.str) + if m: + m = grlnumber.search(self.parm.str[m.end() :]) + self.U = int(m.group()) + + # get Fill number + mf = celfill.search(self.parm.str) + if mf: + fillstring = remove_dollar(self.parm.str[mf.end() :]) + m = grlnumber.search(fillstring) + self.FILL = int(m.group()) + + # look for transformation after fill card + m = re.search(r" *\(", fillstring) + if m: + if self.parm.str[mf.start() - 1] == "*": + angle = True + else: + angle = False + + fillstring = fillstring[m.end() :] + m = re.search(r"\)", fillstring) + string = fillstring[: m.start()] + tr = string.split() + if len(tr) == 1: + self.TR = int(tr[0]) + else: + self.TR = list(map(float, tr)) + if angle and len(self.TR) > 3: + self.TR[3:12] = list(map(math.radians, self.TR[3:12])) + self.TR[3:12] = list(map(math.cos, self.TR[3:12])) + + def get_stat(self, remove_com=True): + """Count and return the number of words and hashes on the line.""" + + if remove_com: + self.geom.remove_comments() + + words = len(reword.findall(self.geom.str)) + hashcell = len(compcell.findall(self.geom.str)) + hashtot = self.geom.str.count("#") + + self.stat = { + "words": words, + "hash": hashtot, + "hascell": hashcell, + "hashsur": hashtot - hashcell, + } + if remove_com: + self.geom.restore_comments() + return [words, hashtot, hashcell, hashtot - hashcell] + + def get_lines(self): + """split string card in the format Cards.lines of Cards object""" + card = self.headstr + self.geom.str + self.parm.str + + # remove blank line introduced during the process + card = re.sub(blnkline, "", card) + + # subtitute comment $ with blank line + card = re.sub(comdollar, r"\nC\g", card) + + # ensure 5 blanks continous line + card = re.sub(contline, r"\n \g", card) + + if card[-1] == "\n": + card = card[:-1] + return list(map(lambda x: x + "\n", card.split("\n"))) + + +def remove_hash(cards, cname, keepComments=True): + def remove(card, cname, keepComments): + """remove complementary operator and subtitute by complementary cell""" + if "parser.Card" in str(type(card)): + celline = "".join(card.lines) + cardstr = cell_card_string(celline) + else: + cardstr = card + cardstr.get_stat() + cardstr.geom.remove_comments(full=not keepComments) + if (not cardstr.hproc) or (cardstr.stat["hash"] == 0): + return ( + cardstr.geom + ) # no complementary operator or cannot be # cannot be removed + cell = cline(cardstr.geom.str) + # find all operators in the cell and + # substitute all complementary operators + # locate object in list to reverse iteration + hashgroup = [] + start = 0 + + lencel = len(cell.str) + while True: + ic = cell.str.lower().find("c", start) + idol = cell.str.find("$", start) + if idol < 0: + idol = lencel + if ic < 0: + ic = lencel + end = min(idol, ic) + for m in rehash.finditer(cell.str, start, end): + hashgroup.append(m) + start = cell.str.find("\n", end) + if end == lencel: + break + + for m in reversed(hashgroup): + start = m.start() + if m.group(1) == "(": # complementary cell defined as surface intersections + hcell, end = cell.get_hashcell(start) + cellmod = cell.str[0:start] + complementary(hcell) + cell.str[end:] + cell = cline(cellmod) + else: + hcname = int( + m.group(1) + ) # complementary cell defined with other cell index + newdef = remove( + cards[hcname], hcname, keepComments + ) # remove complementary operator in new cell if necessary + end = m.end() + cellmod = ( + cell.str[0:start] + + " " + + complementary(newdef) + + " " + + cell.str[end:] + ) + cell = cline(cellmod) + return cell + + newcell = remove(cards[cname], cname, keepComments) + return cline(newcell.str) diff --git a/src/geouned/GEOReverse/Modules/splitFunction.py b/src/geouned/GEOReverse/Modules/splitFunction.py index 8dbad941..643ce3ba 100644 --- a/src/geouned/GEOReverse/Modules/splitFunction.py +++ b/src/geouned/GEOReverse/Modules/splitFunction.py @@ -6,76 +6,80 @@ class splitBase: - def __init__(self,base,knownSurf={}): + def __init__(self, base, knownSurf={}): self.base = base self.knownSurf = knownSurf - + + def joinBase(baseList): shape = [] surf = {} removedKeys = [] for b in baseList: - if b.base is not None: shape.append(b.base) - for k,v in b.knownSurf.items(): - if k in removedKeys : continue - if k not in surf.keys(): - surf[k] = v - else: - if surf[k] == v : - continue - else: - surf[k] = None - removedKeys.append(k) + if b.base is not None: + shape.append(b.base) + for k, v in b.knownSurf.items(): + if k in removedKeys: + continue + if k not in surf.keys(): + surf[k] = v + else: + if surf[k] == v: + continue + else: + surf[k] = None + removedKeys.append(k) newbase = FuseSolid(shape) - return splitBase(newbase,surf) - + return splitBase(newbase, surf) - -def SplitSolid(base,surfacesCut,cellObj,solidTool=False,tolerance=0.01): #1e-2 +def SplitSolid(base, surfacesCut, cellObj, solidTool=False, tolerance=0.01): # 1e-2 # split Base (shape Object or list/tuple of shapes) # with selected surfaces (list of surfaces objects) cutting the base(s) (surfacesCut) # cellObj is the CAD object of the working cell to reconstruction. # the function return a list of solids enclosed fully in the cell (fullPart) # and a list of solids not fully enclosed in the cell (cutPart). These lasts # will require more splitting with the others surfaces defining the cell. - + fullPart = [] - cutPart = [] + cutPart = [] # part if several base in input - if type(base) is list or type(base) is tuple : - for b in base : - fullList,cutList = SplitSolid(b,surfacesCut,cellObj,tolerance=tolerance) - fullPart.extend(fullList) - cutPart.extend(cutList) - return fullPart,cutPart - + if type(base) is list or type(base) is tuple: + for b in base: + fullList, cutList = SplitSolid(b, surfacesCut, cellObj, tolerance=tolerance) + fullPart.extend(fullList) + cutPart.extend(cutList) + return fullPart, cutPart + # part if base is shape object - - if solidTool: - Tools = (cellObj.shape,) + + if solidTool: + Tools = (cellObj.shape,) else: - Tools = tuple( s.shape for s in surfacesCut ) - #for s in surfacesCut: + Tools = tuple(s.shape for s in surfacesCut) + # for s in surfacesCut: # print(s.type,s.params,s.id) # s.shape.exportStep('tool{}.stp'.format(s.id)) - #base.base.exportStep('base.stp') - Solids = BOPTools.SplitAPI.slice(base.base,Tools, 'Split',tolerance = tolerance).Solids - if not Solids : Solids = [base.base] - partPositions, partSolids = space_decomposition(Solids,surfacesCut) + # base.base.exportStep('base.stp') + Solids = BOPTools.SplitAPI.slice( + base.base, Tools, "Split", tolerance=tolerance + ).Solids + if not Solids: + Solids = [base.base] + partPositions, partSolids = space_decomposition(Solids, surfacesCut) ii = 0 - for pos,sol in zip(partPositions,partSolids): - #fullPos = updateSurfacesValues(pos,cellObj.surfaces,base.knownSurf) - #inSolid = cellObj.definition.evaluate(fullPos) - + for pos, sol in zip(partPositions, partSolids): + # fullPos = updateSurfacesValues(pos,cellObj.surfaces,base.knownSurf) + # inSolid = cellObj.definition.evaluate(fullPos) - if not solidTool : pos.update(base.knownSurf) + if not solidTool: + pos.update(base.knownSurf) inSolid = cellObj.definition.evaluate(pos) - #if solidTool : + # if solidTool : # ii += 1 # print(solidTool) # print(cellObj.definition) @@ -83,334 +87,341 @@ def SplitSolid(base,surfacesCut,cellObj,solidTool=False,tolerance=0.01): #1e-2 # print('eval',inSolid) # name = str(cellObj.definition) # sol.exportStep('solid_{}{}.stp'.format(name,ii)) - - if inSolid : - fullPart.append(splitBase(sol,pos)) - elif inSolid is None : - cutPart.append(splitBase(sol,pos)) - return fullPart,cutPart + if inSolid: + fullPart.append(splitBase(sol, pos)) + elif inSolid is None: + cutPart.append(splitBase(sol, pos)) + return fullPart, cutPart -def updateSurfacesValues (position,surfaces,knownSurf) : - position.update(knownSurf) + +def updateSurfacesValues(position, surfaces, knownSurf): + position.update(knownSurf) sname = set(surfaces.keys()) pname = set(position.keys()) fullpos = position.copy() - for name in sname.difference(pname) : + for name in sname.difference(pname): fullpos[name] = None - return fullpos + return fullpos + # Get the position of subregion with respect -# all cutting surfaces -def space_decomposition(solids,surfaces): - - component = [] - good_solids = [] - for c in solids: - if c.Volume < 1e-3 : - if abs(c.Volume) < 1e-3 : - continue +# all cutting surfaces +def space_decomposition(solids, surfaces): + + component = [] + good_solids = [] + for c in solids: + if c.Volume < 1e-3: + if abs(c.Volume) < 1e-3: + continue else: c.reverse() - print('Negative solid Volume',c.Volume) - Svalues = {} - point = point_inside(c) - if point == None : + print("Negative solid Volume", c.Volume) + Svalues = {} + point = point_inside(c) + if point == None: continue # point not found in solid (solid is surface or very thin can be source of lost particules in MCNP) - for surf in surfaces : - Svalues[surf.id] = surface_side(point,surf) - - component.append(Svalues) - good_solids.append(c) - return component,good_solids + for surf in surfaces: + Svalues[surf.id] = surface_side(point, surf) + + component.append(Svalues) + good_solids.append(c) + return component, good_solids + # find one point inside a solid (region) def point_inside(solid): - cut_line = 32 - cut_box = 4 - - # no poner boundbox, el punto puente caer en una superficie para geometria triangular - point = solid.CenterOfMass - points = point - if solid.isInside(point,0.0,False) : return point - - v1=solid.Vertexes[0].Point - for vi in range(len(solid.Vertexes)-1,0,-1): - v2=solid.Vertexes[vi].Point - dv= (v2-v1)*0.5 - - n=1 + cut_line = 32 + cut_box = 4 + + # no poner boundbox, el punto puente caer en una superficie para geometria triangular + point = solid.CenterOfMass + points = point + if solid.isInside(point, 0.0, False): + return point + + v1 = solid.Vertexes[0].Point + for vi in range(len(solid.Vertexes) - 1, 0, -1): + v2 = solid.Vertexes[vi].Point + dv = (v2 - v1) * 0.5 + + n = 1 while True: - for i in range(n): - point = v1 + dv *(1 + 0.5*i) - if solid.isInside(point,0.0,False) : return point - n=n*2 - dv=dv*0.5 - if (n > cut_line ) : - break - -# Box_Volume = BBox.XLength*BBox.YLength*BBox.ZLength -# if (solid.Volume < Box_Volume/ math.pow(16,nmax_cut)) : -# print('very small Solid Volume (solid volume, box volume): {},{}'.format(solid.Volume,Box_Volume)) -# return None - BBox = solid.optimalBoundingBox(False) - box = [BBox.XMin,BBox.XMax, - BBox.YMin,BBox.YMax, - BBox.ZMin,BBox.ZMax ] - - boxes,centers = CutBox(box) - n = 0 - - while True : - for p in centers : - pp = FreeCAD.Vector(p[0],p[1],p[2]) - if solid.isInside(pp,0.0,False) : return pp - - subbox = [] - centers = [] - for b in boxes : - btab,ctab = CutBox(b) + for i in range(n): + point = v1 + dv * (1 + 0.5 * i) + if solid.isInside(point, 0.0, False): + return point + n = n * 2 + dv = dv * 0.5 + if n > cut_line: + break + + # Box_Volume = BBox.XLength*BBox.YLength*BBox.ZLength + # if (solid.Volume < Box_Volume/ math.pow(16,nmax_cut)) : + # print('very small Solid Volume (solid volume, box volume): {},{}'.format(solid.Volume,Box_Volume)) + # return None + BBox = solid.optimalBoundingBox(False) + box = [BBox.XMin, BBox.XMax, BBox.YMin, BBox.YMax, BBox.ZMin, BBox.ZMax] + + boxes, centers = CutBox(box) + n = 0 + + while True: + for p in centers: + pp = FreeCAD.Vector(p[0], p[1], p[2]) + if solid.isInside(pp, 0.0, False): + return pp + + subbox = [] + centers = [] + for b in boxes: + btab, ctab = CutBox(b) subbox.extend(btab) centers.extend(ctab) - boxes = subbox - n = n + 1 + boxes = subbox + n = n + 1 + + if n == cut_box: + print("Solid not found in bounding Box (Volume : {})".format(solid.Volume)) + print("Valid Solid : ", solid.isValid()) + return None - if (n == cut_box ) : - print('Solid not found in bounding Box (Volume : {})'.format(solid.Volume)) - print('Valid Solid : ', solid.isValid()) - return None # divide a box into 8 smaller boxes def CutBox(Box): - xmid = (Box[1]+Box[0])*0.5 - ymid = (Box[3]+Box[2])*0.5 - zmid = (Box[5]+Box[4])*0.5 - - - b1 = (Box[0],xmid,Box[2],ymid,Box[4],zmid) - p1 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b2 = (xmid,Box[1],Box[2],ymid,Box[4],zmid) - p2 = (0.5*(xmid+Box[1]), 0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b3 = (Box[0],xmid,ymid,Box[3],Box[4],zmid) - p3 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b4 = (xmid,Box[1],ymid,Box[3],Box[4],zmid) - p4 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b5 = (Box[0],xmid,Box[2],ymid,zmid,Box[5]) - p5 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b6 = (xmid,Box[1],Box[2],ymid,zmid,Box[5]) - p6 = (0.5*(xmid+Box[1]),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b7 = (Box[0],xmid,ymid,Box[3],zmid,Box[5]) - p7 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - b8 = (xmid,Box[1],ymid,Box[3],zmid,Box[5]) - p8 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - return [b1,b2,b3,b4,b5,b6,b7,b8],[p1,p2,p3,p4,p5,p6,p7,p8] + xmid = (Box[1] + Box[0]) * 0.5 + ymid = (Box[3] + Box[2]) * 0.5 + zmid = (Box[5] + Box[4]) * 0.5 + + b1 = (Box[0], xmid, Box[2], ymid, Box[4], zmid) + p1 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b2 = (xmid, Box[1], Box[2], ymid, Box[4], zmid) + p2 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b3 = (Box[0], xmid, ymid, Box[3], Box[4], zmid) + p3 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b4 = (xmid, Box[1], ymid, Box[3], Box[4], zmid) + p4 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b5 = (Box[0], xmid, Box[2], ymid, zmid, Box[5]) + p5 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b6 = (xmid, Box[1], Box[2], ymid, zmid, Box[5]) + p6 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b7 = (Box[0], xmid, ymid, Box[3], zmid, Box[5]) + p7 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + + b8 = (xmid, Box[1], ymid, Box[3], zmid, Box[5]) + p8 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + + return [b1, b2, b3, b4, b5, b6, b7, b8], [p1, p2, p3, p4, p5, p6, p7, p8] # check the position of the point with respect # a surface -def surface_side(p,surf): - if surf.type == 'sphere' : - org,R = surf.params - D = p-org +def surface_side(p, surf): + if surf.type == "sphere": + org, R = surf.params + D = p - org inout = D.Length - R - elif surf.type == 'plane' : - normal,d = surf.params + elif surf.type == "plane": + normal, d = surf.params inout = p.dot(normal) - d - elif surf.type == 'cylinder': - P,v,R = surf.params + elif surf.type == "cylinder": + P, v, R = surf.params - D = p-P - if not surf.truncated: + D = p - P + if not surf.truncated: inout = D.cross(v).Length - R - else: - inCyl = D.cross(v).Length/v.Length - R # <0 in cylinder - inPln = btwPPlanes(p,P,v) # <0 between planes + else: + inCyl = D.cross(v).Length / v.Length - R # <0 in cylinder + inPln = btwPPlanes(p, P, v) # <0 between planes - if (inCyl <0 ) and ( inPln < 0 ) : - inout = -1 # inside the can + if (inCyl < 0) and (inPln < 0): + inout = -1 # inside the can else: - inout = 1 # outside the can - - elif surf.type == 'cone': - if not surf.truncated: - P,v,t,dblsht = surf.params - X = p-P + inout = 1 # outside the can + + elif surf.type == "cone": + if not surf.truncated: + P, v, t, dblsht = surf.params + X = p - P X.normalize() dprod = X.dot(v) - dprod = max(-1,min(1,dprod)) + dprod = max(-1, min(1, dprod)) a = math.acos(dprod) if not dblsht else math.acos(abs(dprod)) inout = a - math.atan(t) - else: - P,v,R1,R2 = surf.params - apex = P + R1/(R1-R2)*v - - X = p-apex + else: + P, v, R1, R2 = surf.params + apex = P + R1 / (R1 - R2) * v + + X = p - apex X.normalize() - dprod = X.dot(-v)/v.Length # -v because reverse axis. in MCNP TRC r1 > r2 - dprod = max(-1,min(1,dprod)) + dprod = X.dot(-v) / v.Length # -v because reverse axis. in MCNP TRC r1 > r2 + dprod = max(-1, min(1, dprod)) a = math.acos(dprod) - t = (R1-R2)/v.Length + t = (R1 - R2) / v.Length inCone = a - math.atan(t) - inPln = btwPPlanes(p,P,v) # <0 between planes + inPln = btwPPlanes(p, P, v) # <0 between planes - if (inCone <0 ) and ( inPln < 0 ) : - inout = -1 # inside the can + if (inCone < 0) and (inPln < 0): + inout = -1 # inside the can else: - inout = 1 # outside the can - - elif surf.type == 'cone_elliptic': - apex,axis,Ra,radii,rAxes,dblsht = surf.params - - r = p-apex - X = r.dot(rAxes[1]) - Y = r.dot(rAxes[0]) - Z = r.dot(axis) - if dblsht : Z = abs(Z) - inout = (X/radii[1])**2 + (Y/radii[0])**2 - Z/Ra - - elif surf.type == 'hyperboloid': - center,axis,radii,rAxes,onesht = surf.params - - r = p-center - rX = r.dot(rAxes[1]) - v = r - (rX*rAxes[1] + center) - d = v.Length - - one = 1 if onesht else -1 - radical = (rX/radii[1])**2 + one - - if radical > 0 : - Y = radii[0] * math.sqrt( radical ) - inout = d-Y - else: - inout = 1 - - elif surf.type == 'ellipsoid': - center,axis,radii,rAxes = surf.params - - r = p-center - rX = r.dot(axis) - rY = r - (rX*axis + center) - - if axis.add(-rAxes[0]).Length < 1e-5 : - radX,radY = radii - else: - radY,radY = radii - - radical = 1-(rX/radX)**2 - if radical > 0 : - Y = radY * math.sqrt( radical ) - inout = rY-Y - else: - inout = 1 - - elif surf.type == 'cylinder_elliptic': - center,axis,radii,rAxes = surf.params - - r = p-center - X = r.dot(rAxes[1]) - Y = r.dot(rAxes[0]) - inout = (X/radii[1])**2 + (Y/radii[0])**2 -1 - - if surf.truncated and inout < 0: - inout = btwPPlanes(p,center,axis) # <0 between planes - - elif surf.type == 'cylinder_hyperbolic': - center,axis,radii,rAxes = surf.params - - r = p-center - X = r.dot(rAxes[1]) - Y = r.dot(rAxes[0]) - inout = (X/radii[1])**2 - (Y/radii[0])**2 -1 - - elif surf.type == 'paraboloid': - center,axis,focal = surf.params - - r = p-center - X = r.dot(axis) - if X < 0 : + inout = 1 # outside the can + + elif surf.type == "cone_elliptic": + apex, axis, Ra, radii, rAxes, dblsht = surf.params + + r = p - apex + X = r.dot(rAxes[1]) + Y = r.dot(rAxes[0]) + Z = r.dot(axis) + if dblsht: + Z = abs(Z) + inout = (X / radii[1]) ** 2 + (Y / radii[0]) ** 2 - Z / Ra + + elif surf.type == "hyperboloid": + center, axis, radii, rAxes, onesht = surf.params + + r = p - center + rX = r.dot(rAxes[1]) + v = r - (rX * rAxes[1] + center) + d = v.Length + + one = 1 if onesht else -1 + radical = (rX / radii[1]) ** 2 + one + + if radical > 0: + Y = radii[0] * math.sqrt(radical) + inout = d - Y + else: inout = 1 - else: - v = r - X*axis + + elif surf.type == "ellipsoid": + center, axis, radii, rAxes = surf.params + + r = p - center + rX = r.dot(axis) + rY = r - (rX * axis + center) + + if axis.add(-rAxes[0]).Length < 1e-5: + radX, radY = radii + else: + radY, radY = radii + + radical = 1 - (rX / radX) ** 2 + if radical > 0: + Y = radY * math.sqrt(radical) + inout = rY - Y + else: + inout = 1 + + elif surf.type == "cylinder_elliptic": + center, axis, radii, rAxes = surf.params + + r = p - center + X = r.dot(rAxes[1]) + Y = r.dot(rAxes[0]) + inout = (X / radii[1]) ** 2 + (Y / radii[0]) ** 2 - 1 + + if surf.truncated and inout < 0: + inout = btwPPlanes(p, center, axis) # <0 between planes + + elif surf.type == "cylinder_hyperbolic": + center, axis, radii, rAxes = surf.params + + r = p - center + X = r.dot(rAxes[1]) + Y = r.dot(rAxes[0]) + inout = (X / radii[1]) ** 2 - (Y / radii[0]) ** 2 - 1 + + elif surf.type == "paraboloid": + center, axis, focal = surf.params + + r = p - center + X = r.dot(axis) + if X < 0: + inout = 1 + else: + v = r - X * axis d = v.Length - Y = math.sqrt(4*focal*X) - inout = d-Y - - elif surf.type == 'torus': - P,v,Ra,Rb,Rc = surf.params - - d = p-P - z = d.dot(v) - rz = d-z*v - inout = (z/Rb)**2 + ((rz.Length-Ra)/Rc)**2 -1 - - elif surf.type == 'box': - P,v1,v2,v3 = surf.params - for v in (v1,v2,v3): - inout = btwPPlanes(p,P,v) # <0 between planes - if inout > 0 : break - - else: - print ('surface type {} not considered'.format(surf[0])) - return - - return inout > 0 - - -def btwPPlanes(p,p0,v): - - p1 = p0 + v - inP0 = v.dot(p-p0) # >0 plane(base plane) side inside the cylinder - inP1 = v.dot(p-p1) # >0 plane(base plane) side inside the cylinder - - if (inP0 >0 ) and (inP1 < 0 ) : - return -1 - else: - return 1 - -#************************************************ + Y = math.sqrt(4 * focal * X) + inout = d - Y + + elif surf.type == "torus": + P, v, Ra, Rb, Rc = surf.params + + d = p - P + z = d.dot(v) + rz = d - z * v + inout = (z / Rb) ** 2 + ((rz.Length - Ra) / Rc) ** 2 - 1 + + elif surf.type == "box": + P, v1, v2, v3 = surf.params + for v in (v1, v2, v3): + inout = btwPPlanes(p, P, v) # <0 between planes + if inout > 0: + break + + else: + print("surface type {} not considered".format(surf[0])) + return + + return inout > 0 + + +def btwPPlanes(p, p0, v): + + p1 = p0 + v + inP0 = v.dot(p - p0) # >0 plane(base plane) side inside the cylinder + inP1 = v.dot(p - p1) # >0 plane(base plane) side inside the cylinder + + if (inP0 > 0) and (inP1 < 0): + return -1 + else: + return 1 + + +# ************************************************ + def FuseSolid(parts): if (len(parts)) <= 1: - if parts : - solid = parts[0] - else: - return None + if parts: + solid = parts[0] + else: + return None else: - try: - fused = parts[0].fuse(parts[1:]) - except: - fused = None - - if fused is not None: - try : - refinedfused = fused.removeSplitter() - except : - refinedfused = fused - - if refinedfused.isValid() : - solid = refinedfused - else : - if fused.isValid(): - solid = fused - else: - solid = Part.makeCompound(parts) - else: - solid = Part.makeCompound(parts) - - if solid.Volume < 0 : solid.reverse() + try: + fused = parts[0].fuse(parts[1:]) + except: + fused = None + + if fused is not None: + try: + refinedfused = fused.removeSplitter() + except: + refinedfused = fused + + if refinedfused.isValid(): + solid = refinedfused + else: + if fused.isValid(): + solid = fused + else: + solid = Part.makeCompound(parts) + else: + solid = Part.makeCompound(parts) + + if solid.Volume < 0: + solid.reverse() return solid - diff --git a/src/geouned/GEOReverse/reverse.py b/src/geouned/GEOReverse/reverse.py index 3b53505d..6ca32ca8 100644 --- a/src/geouned/GEOReverse/reverse.py +++ b/src/geouned/GEOReverse/reverse.py @@ -9,66 +9,66 @@ from .Modules.XMLinput import XMLinput -def reverse(optFile='configRevese.ini') : +def reverse(optFile="configRevese.ini"): - printCodeVersion() + printCodeVersion() - setting = setOptions(optFile) + setting = setOptions(optFile) - geomfile = setting['fileIn'] - outname = setting['fileOut'] - outBox = setting['outBox'] - inFormat = setting['inFormat'] + geomfile = setting["fileIn"] + outname = setting["fileOut"] + outBox = setting["outBox"] + inFormat = setting["inFormat"] - CADselection = { 'Ustart' : setting['UStart'] , - 'levelMax' : setting['levelMax'], - 'cell' : setting['cell'] , - 'mat' : setting['mat'] , - 'format' : setting['inFormat'] - } + CADselection = { + "Ustart": setting["UStart"], + "levelMax": setting["levelMax"], + "cell": setting["cell"], + "mat": setting["mat"], + "format": setting["inFormat"], + } - UnivCell = CADCell() - UnivCell.shape = UnivCell.makeBox(FreeCAD.BoundBox(*outBox)) + UnivCell = CADCell() + UnivCell.shape = UnivCell.makeBox(FreeCAD.BoundBox(*outBox)) - # get geometry definition from MCNP input - if inFormat == 'mcnp': - geom = MCNPinput(geomfile) - elif inFormat == 'openMC_XML': - geom = XMLinput(geomfile) - else: - msg = ( - f'input format type {inFormat} is not supported.' - 'Supported options are "mcnp" or "openMC_XML"' - ) - raise ValueError(msg) + # get geometry definition from MCNP input + if inFormat == "mcnp": + geom = MCNPinput(geomfile) + elif inFormat == "openMC_XML": + geom = XMLinput(geomfile) + else: + msg = ( + f"input format type {inFormat} is not supported." + 'Supported options are "mcnp" or "openMC_XML"' + ) + raise ValueError(msg) - CADCells,fails = buildCAD(UnivCell,geom,CADselection) + CADCells, fails = buildCAD(UnivCell, geom, CADselection) - if fails : print('failed in conversion',fails) + if fails: + print("failed in conversion", fails) - CADdoc=FreeCAD.newDocument("WorkingDoc") - - makeTree(CADdoc,CADCells) - Import.export(CADdoc.Objects[0:1],outname+'.stp' ) - CADdoc.saveAs(outname+'.FCStd') + CADdoc = FreeCAD.newDocument("WorkingDoc") + makeTree(CADdoc, CADCells) + Import.export(CADdoc.Objects[0:1], outname + ".stp") + CADdoc.saveAs(outname + ".FCStd") def printCodeVersion(): - FreeCAD_Version = '{V[0]:}.{V[1]:}.{V[2]:}'.format(V=FreeCAD.Version()) - title = '''\ + FreeCAD_Version = "{V[0]:}.{V[1]:}.{V[2]:}".format(V=FreeCAD.Version()) + title = """\ ######################################################################### # # # GEOReverse version {:<11}{}{:>26} # FreeCAD version {:<11}{:>36} # # -#########################################################################'''.format(GEOReverse_Version,GEOReverse_ReleaseDate,'#',FreeCAD_Version,'#') - print(title) - - -if __name__ == '__main__' : - reverse() - +#########################################################################""".format( + GEOReverse_Version, GEOReverse_ReleaseDate, "#", FreeCAD_Version, "#" + ) + print(title) +if __name__ == "__main__": + reverse() diff --git a/src/geouned/GEOUNED/CodeVersion.py b/src/geouned/GEOUNED/CodeVersion.py index 5579e84e..9af84e16 100644 --- a/src/geouned/GEOUNED/CodeVersion.py +++ b/src/geouned/GEOUNED/CodeVersion.py @@ -1,4 +1,4 @@ -''' Modification from 0.9.5 +""" Modification from 0.9.5 - volInput card name substituted by volSDEF card name - new card volCARD (values : True/False) used to insert the CAD cell volume into the cell definition using the MCNP card VOL. Default value True @@ -58,8 +58,7 @@ - Change tolerance values if BOPTsplit function crash - fix some bugs with Torus (not all) - implementation of the geometry conversion to PHITS code input file (by T. Okano Nissin High Voltage Corporation (NHVC)) -''' +""" - -GEOUNED_Version = '1.0.1' -GEOUNED_ReleaseDate = '19/03/2024' +GEOUNED_Version = "1.0.1" +GEOUNED_ReleaseDate = "19/03/2024" diff --git a/src/geouned/GEOUNED/Conversion/CellDefinition.py b/src/geouned/GEOUNED/Conversion/CellDefinition.py index ca390815..8c8fd8d2 100644 --- a/src/geouned/GEOUNED/Conversion/CellDefinition.py +++ b/src/geouned/GEOUNED/Conversion/CellDefinition.py @@ -9,8 +9,13 @@ from ..Utils import BasicFunctions_part2 as BF from ..Utils import Functions as UF from ..Utils import Geometry_GU as GU -from ..Utils.BasicFunctions_part1 import (isInLine, isOposite, isParallel, - isSameValue, signPlane) +from ..Utils.BasicFunctions_part1 import ( + isInLine, + isOposite, + isParallel, + isSameValue, + signPlane, +) from ..Utils.booleanFunction import BoolSequence, insertInSequence from ..Utils.BooleanSolids import buildCTableFromSolids, removeExtraSurfaces from ..Utils.Functions import GEOUNED_Surface @@ -19,984 +24,1182 @@ def getId(facein, Surfaces): - + surfin = str(facein) - if surfin == '' : - if isParallel(facein.Axis,FreeCAD.Vector(1,0,0),tol.pln_angle) : - P = 'PX' - elif isParallel(facein.Axis,FreeCAD.Vector(0,1,0),tol.pln_angle) : - P = 'PY' - elif isParallel(facein.Axis,FreeCAD.Vector(0,0,1),tol.pln_angle) : - P = 'PZ' + if surfin == "": + if isParallel(facein.Axis, FreeCAD.Vector(1, 0, 0), tol.pln_angle): + P = "PX" + elif isParallel(facein.Axis, FreeCAD.Vector(0, 1, 0), tol.pln_angle): + P = "PY" + elif isParallel(facein.Axis, FreeCAD.Vector(0, 0, 1), tol.pln_angle): + P = "PZ" else: - P = 'P' - - for s in Surfaces[P] : - if BF.isSamePlane(facein,s.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol) : - return s.Index - - elif surfin == '' : - for s in Surfaces['Cyl'] : - if BF.isSameCylinder(facein,s.Surf,dtol=tol.cyl_distance,atol=tol.cyl_angle,relTol=tol.relativeTol) : - return s.Index - - elif surfin == '' : - for s in Surfaces['Cone'] : - if BF.isSameCone(facein,s.Surf,dtol=tol.kne_distance,atol=tol.kne_angle,relTol=tol.relativeTol): - return s.Index - - elif surfin[0:6] == 'Sphere': - for s in Surfaces['Sph'] : - if BF.isSameSphere(facein,s.Surf,tol.sph_distance,relTol=tol.relativeTol): - return s.Index - - elif surfin == '' : - for s in Surfaces['Tor'] : - if BF.isSameTorus(facein,s.Surf,dtol=tol.tor_distance,atol=tol.tor_angle,relTol=tol.relativeTol): - return s.Index - + P = "P" + + for s in Surfaces[P]: + if BF.isSamePlane( + facein, + s.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + ): + return s.Index + + elif surfin == "": + for s in Surfaces["Cyl"]: + if BF.isSameCylinder( + facein, + s.Surf, + dtol=tol.cyl_distance, + atol=tol.cyl_angle, + relTol=tol.relativeTol, + ): + return s.Index + + elif surfin == "": + for s in Surfaces["Cone"]: + if BF.isSameCone( + facein, + s.Surf, + dtol=tol.kne_distance, + atol=tol.kne_angle, + relTol=tol.relativeTol, + ): + return s.Index + + elif surfin[0:6] == "Sphere": + for s in Surfaces["Sph"]: + if BF.isSameSphere( + facein, s.Surf, tol.sph_distance, relTol=tol.relativeTol + ): + return s.Index + + elif surfin == "": + for s in Surfaces["Tor"]: + if BF.isSameTorus( + facein, + s.Surf, + dtol=tol.tor_distance, + atol=tol.tor_angle, + relTol=tol.relativeTol, + ): + return s.Index + return 0 - + + def isInverted(solid): - face=solid.Faces[0] - - #u=(face.Surface.bounds()[0]+face.Surface.bounds()[1])/2.0 # entre 0 y 2pi si es completo - #v=face.Surface.bounds()[0]+(face.Surface.bounds()[3]-face.Surface.bounds()[2])/3.0 # a lo largo del eje - Range=face.ParameterRange - u=(Range[1]+Range[0])/2.0 - v=(Range[3]+Range[2])/2.0 - - if (str(face.Surface)==''): - dist1=face.Surface.value(u,v).distanceToLine(face.Surface.Center,face.Surface.Axis) - dist2=face.Surface.value(u,v).add(face.Surface.normal(u,v).multiply(1.0e-6)).distanceToLine(face.Surface.Center,face.Surface.Axis) - if ((dist2-dist1)<0.0): + face = solid.Faces[0] + + # u=(face.Surface.bounds()[0]+face.Surface.bounds()[1])/2.0 # entre 0 y 2pi si es completo + # v=face.Surface.bounds()[0]+(face.Surface.bounds()[3]-face.Surface.bounds()[2])/3.0 # a lo largo del eje + Range = face.ParameterRange + u = (Range[1] + Range[0]) / 2.0 + v = (Range[3] + Range[2]) / 2.0 + + if str(face.Surface) == "": + dist1 = face.Surface.value(u, v).distanceToLine( + face.Surface.Center, face.Surface.Axis + ) + dist2 = ( + face.Surface.value(u, v) + .add(face.Surface.normal(u, v).multiply(1.0e-6)) + .distanceToLine(face.Surface.Center, face.Surface.Axis) + ) + if (dist2 - dist1) < 0.0: # The normal of the cylinder is going inside return True - elif (str(face.Surface)=='' ): - dist1=face.Surface.value(u,v).distanceToLine(face.Surface.Apex,face.Surface.Axis) - dist2=face.Surface.value(u,v).add(face.Surface.normal(u,v).multiply(1.0e-6)).distanceToLine(face.Surface.Apex,face.Surface.Axis) - if ((dist2-dist1)<0.0): + elif str(face.Surface) == "": + dist1 = face.Surface.value(u, v).distanceToLine( + face.Surface.Apex, face.Surface.Axis + ) + dist2 = ( + face.Surface.value(u, v) + .add(face.Surface.normal(u, v).multiply(1.0e-6)) + .distanceToLine(face.Surface.Apex, face.Surface.Axis) + ) + if (dist2 - dist1) < 0.0: # The normal of the cylinder is going inside return True # MIO - elif str(face.Surface)[0:6]=='Sphere': + elif str(face.Surface)[0:6] == "Sphere": # radii = point - center - radii = face.Surface.value(u,v).add(face.Surface.Center.multiply(-1)) - radiiB = face.Surface.value(u,v).add(face.Surface.normal(u,v).multiply(1.0e-6)).add(face.Surface.Center.multiply(-1)) - #radiiB = radii.add( face.Surface.normal(u,v).multiply(1.0e-6) ) - if ((radiiB.Length-radii.Length)<0.0): + radii = face.Surface.value(u, v).add(face.Surface.Center.multiply(-1)) + radiiB = ( + face.Surface.value(u, v) + .add(face.Surface.normal(u, v).multiply(1.0e-6)) + .add(face.Surface.Center.multiply(-1)) + ) + # radiiB = radii.add( face.Surface.normal(u,v).multiply(1.0e-6) ) + if (radiiB.Length - radii.Length) < 0.0: # An increasing of the radii vector in the normal direction decreases the radii: oposite normal direction return True - - elif (str(face.Surface)==''): - dist1=face.CenterOfMass.distanceToPoint(solid.BoundBox.Center) - dist2=face.CenterOfMass.add(face.normalAt(u,v).multiply(1.0e-6)).distanceToPoint(solid.BoundBox.Center) - point2=face.CenterOfMass.add(face.normalAt(u,v).multiply(1.0e-6)) - if (solid.isInside(point2,1e-7,False)): + + elif str(face.Surface) == "": + dist1 = face.CenterOfMass.distanceToPoint(solid.BoundBox.Center) + dist2 = face.CenterOfMass.add( + face.normalAt(u, v).multiply(1.0e-6) + ).distanceToPoint(solid.BoundBox.Center) + point2 = face.CenterOfMass.add(face.normalAt(u, v).multiply(1.0e-6)) + if solid.isInside(point2, 1e-7, False): return True - + return False - -def GenPlane(face,solid): - """ Generate an additional plane when convex surfaces of second order are presented as a face of the solid """ +def GenPlane(face, solid): + """Generate an additional plane when convex surfaces of second order are presented as a face of the solid""" - surf = face.Surface - if (str(surf) == ''): - return GenPlaneCylinder(face,solid) - if (str(surf) == ''): - return GenPlaneCone(face,solid) - if (str(surf) == 'Sphere'): - return GenPlaneSphere(face,solid) - - + if str(surf) == "": + return GenPlaneCylinder(face, solid) + if str(surf) == "": + return GenPlaneCone(face, solid) + if str(surf) == "Sphere": + return GenPlaneSphere(face, solid) - -def getClosedRanges(solid,face_index): +def getClosedRanges(solid, face_index): - UNodes=[] + UNodes = [] for index in face_index: - URange = solid.Faces[index].ParameterRange - UNodes.append((URange[0],index)) - UNodes.append((URange[1],index)) + URange = solid.Faces[index].ParameterRange + UNodes.append((URange[0], index)) + UNodes.append((URange[1], index)) UNodes.sort() - closedRange = getIntervals(UNodes) - + closedRange = getIntervals(UNodes) + aMin = closedRange[0][0][0] aMax = closedRange[-1][1][0] - - if abs(aMax-aMin-2.0*math.pi) < 1e-2 : - if (len(closedRange) == 1) : - closedFace = True - else: - endPoint = (closedRange[-1][0][0]-2*math.pi, closedRange[-1][0][1]) - closedRange[0][0] = endPoint - closedRange[0][2].update(closedRange[-1][2]) - del (closedRange[-1]) - - if len(closedRange) == 1: - if abs(closedRange[0][1][0]-closedRange[0][0][0]-2.0*math.pi)< 1e-2: - closedFace = True + + if abs(aMax - aMin - 2.0 * math.pi) < 1e-2: + if len(closedRange) == 1: + closedFace = True + else: + endPoint = (closedRange[-1][0][0] - 2 * math.pi, closedRange[-1][0][1]) + closedRange[0][0] = endPoint + closedRange[0][2].update(closedRange[-1][2]) + del closedRange[-1] + + if len(closedRange) == 1: + if ( + abs(closedRange[0][1][0] - closedRange[0][0][0] - 2.0 * math.pi) + < 1e-2 + ): + closedFace = True + else: + closedFace = False else: - closedFace = False - else: - closedFace = False + closedFace = False else: - closedFace = False + closedFace = False return closedRange, closedFace def getIntervals(UNodes): - closedRange = [] + closedRange = [] posMin = dict() posMax = dict() - for i,node in enumerate(UNodes): - if node[1] not in posMin.keys(): - posMin[node[1]] = i - else: - posMax[node[1]] = i - - UMin = UNodes[0 ] - iPos = posMax[UMin[1]] + for i, node in enumerate(UNodes): + if node[1] not in posMin.keys(): + posMin[node[1]] = i + else: + posMax[node[1]] = i + + UMin = UNodes[0] + iPos = posMax[UMin[1]] while True: - x = UNodes[iPos] - end = True - for i in range(iPos+1,len(UNodes)): - nxtInt = UNodes[i][1] - if (UNodes[posMin[nxtInt]][0] -x[0]) < 1e-5: # x pos is > min boundary of the next inteval inside precision 1e-5 - iPos = posMax[nxtInt] - end = False - break - - if end: - UMax = x - closedRange.append([UMin,UMax]) - iPos += 1 - if iPos < len(UNodes) : - UMin = UNodes[iPos] - iPos = posMax[UMin[1]] - else: - break + x = UNodes[iPos] + end = True + for i in range(iPos + 1, len(UNodes)): + nxtInt = UNodes[i][1] + if ( + UNodes[posMin[nxtInt]][0] - x[0] + ) < 1e-5: # x pos is > min boundary of the next inteval inside precision 1e-5 + iPos = posMax[nxtInt] + end = False + break + + if end: + UMax = x + closedRange.append([UMin, UMax]) + iPos += 1 + if iPos < len(UNodes): + UMin = UNodes[iPos] + iPos = posMax[UMin[1]] + else: + break for rnge in closedRange: - index = set() - xmin = rnge[0][0] - xmax = rnge[1][0] - for interval in UNodes: - x = interval[0] - if (xmin - x) < 1.e-5 and (x - xmax) < 1.e-5 : - index.add( interval[1] ) - rnge.append(index) + index = set() + xmin = rnge[0][0] + xmax = rnge[1][0] + for interval in UNodes: + x = interval[0] + if (xmin - x) < 1.0e-5 and (x - xmax) < 1.0e-5: + index.add(interval[1]) + rnge.append(index) return closedRange -def getUValueBoundary(solid,face_index,myIndex): - faceURange,closedFace = getClosedRanges(solid,face_index) - if closedFace : return None,None +def getUValueBoundary(solid, face_index, myIndex): + + faceURange, closedFace = getClosedRanges(solid, face_index) + if closedFace: + return None, None for rnge in faceURange: - if myIndex in rnge[2]: - UMin,UMax = rnge[0:2] - return UMin,UMax - + if myIndex in rnge[2]: + UMin, UMax = rnge[0:2] + return UMin, UMax + -def GenPlaneSphere(face,solid): - Same_Faces=[] +def GenPlaneSphere(face, solid): + Same_Faces = [] Same_Faces.append(face) for f in solid.Faces: - if f.isEqual(face) or str(f.Surface) != 'Sphere' : continue - if (f.Surface.Center == face.Surface.Center and f.Surface.Radius == face.Surface.Radius): - #print 'Warning: coincident sphere faces are the same' - for f2 in Same_Faces : - if f.distToShape(f2)[0] < 1e-6 : - Same_Faces.append(f) - break - - #print Same_Faces - normal = FreeCAD.Vector(0,0,0) + if f.isEqual(face) or str(f.Surface) != "Sphere": + continue + if ( + f.Surface.Center == face.Surface.Center + and f.Surface.Radius == face.Surface.Radius + ): + # print 'Warning: coincident sphere faces are the same' + for f2 in Same_Faces: + if f.distToShape(f2)[0] < 1e-6: + Same_Faces.append(f) + break + + # print Same_Faces + normal = FreeCAD.Vector(0, 0, 0) for f in Same_Faces: - normal += f.Area * (f.CenterOfMass - face.Surface.Center) - - return Part.Plane(face.Surface.Center,normal).toShape() + normal += f.Area * (f.CenterOfMass - face.Surface.Center) + return Part.Plane(face.Surface.Center, normal).toShape() -def GenPlaneCylinder(face,solid): - Surf=face.Surface - rad=Surf.Radius +def GenPlaneCylinder(face, solid): - if (str(Surf)!=''): + Surf = face.Surface + rad = Surf.Radius + + if str(Surf) != "": return None - + myIndex = solid.Faces.index(face) - face_index=[myIndex] + face_index = [myIndex] for i, face2 in enumerate(solid.Faces): - if face2.Area < tol.min_area : - if opt.verbose : print(f'Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) ') - continue - if str(face2.Surface) == '' and not(face2.isEqual(face)): - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Radius == rad and isInLine(face2.Surface.Center,face.Surface.Axis,face.Surface.Center)): - #print 'Warning: coincident cylinder faces are the same' + if face2.Area < tol.min_area: + if opt.verbose: + print( + f"Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) " + ) + continue + if str(face2.Surface) == "" and not (face2.isEqual(face)): + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Radius == rad + and isInLine( + face2.Surface.Center, face.Surface.Axis, face.Surface.Center + ) + ): + # print 'Warning: coincident cylinder faces are the same' face_index.append(i) - UMin,UMax = getUValueBoundary(solid,face_index,myIndex) - if UMin is None : return None + UMin, UMax = getUValueBoundary(solid, face_index, myIndex) + if UMin is None: + return None + + U1, i1 = UMin + U2, i2 = UMax - U1,i1 = UMin - U2,i2 = UMax + V1 = solid.Faces[i1].ParameterRange[2] + V2 = solid.Faces[i2].ParameterRange[2] - V1 = solid.Faces[i1].ParameterRange[2] - V2 = solid.Faces[i2].ParameterRange[2] + P1 = solid.Faces[i1].valueAt(U1, V1) + P2 = solid.Faces[i2].valueAt(U2, V2) - P1 = solid.Faces[i1].valueAt(U1,V1) - P2 = solid.Faces[i2].valueAt(U2,V2) - - if (P1.isEqual(P2,1e-5)): - if opt.verbose : print('Error in the additional place definition') + if P1.isEqual(P2, 1e-5): + if opt.verbose: + print("Error in the additional place definition") return None - - normal=P2.sub(P1).cross(face.Surface.Axis) - plane=Part.Plane(P1,normal).toShape() - + + normal = P2.sub(P1).cross(face.Surface.Axis) + plane = Part.Plane(P1, normal).toShape() + return plane - -def GenPlaneCylinder_old(face,solid): - Surf=face.Surface - rad=Surf.Radius +def GenPlaneCylinder_old(face, solid): - if (str(Surf)!=''): + Surf = face.Surface + rad = Surf.Radius + + if str(Surf) != "": return None - - face_index=[solid.Faces.index(face)] + + face_index = [solid.Faces.index(face)] for i, face2 in enumerate(solid.Faces): - if face2.Area < tol.min_area : - if opt.verbose : print(f'Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) ') - continue - if str(face2.Surface) == '' and not(face2.isEqual(face)): - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Radius == rad and isInLine(face2.Surface.Center,face.Surface.Axis,face.Surface.Center)): - #print 'Warning: coincident cylinder faces are the same' + if face2.Area < tol.min_area: + if opt.verbose: + print( + f"Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) " + ) + continue + if str(face2.Surface) == "" and not (face2.isEqual(face)): + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Radius == rad + and isInLine( + face2.Surface.Center, face.Surface.Axis, face.Surface.Center + ) + ): + # print 'Warning: coincident cylinder faces are the same' face_index.append(i) - AngleRange=0.0 - Uval=[] + AngleRange = 0.0 + Uval = [] for index in face_index: - Range=solid.Faces[index].ParameterRange - AngleRange=AngleRange+abs(Range[1]-Range[0]) - if not(Range[0] in Uval) and not(Range[1] in Uval): + Range = solid.Faces[index].ParameterRange + AngleRange = AngleRange + abs(Range[1] - Range[0]) + if not (Range[0] in Uval) and not (Range[1] in Uval): Uval.append(Range[0]) Uval.append(Range[1]) - if (2.0*math.pi-AngleRange<1e-2): + if 2.0 * math.pi - AngleRange < 1e-2: return None - - UVNodes=[] + + UVNodes = [] for index in face_index: - face2 = solid.Faces[index] - try: - UVNodes.append(face2.getUVNodes()) - except RuntimeError: - tess = face.tessellate(1.0,True) - UVNodes.append(face2.getUVNodes()) - - Uval_str_cl=[] - for i,elem1 in enumerate(Uval): - num_str1='%11.4E' %elem1 - if abs(elem1)<1.0e-5: - num_str1='%11.4E' %0.0 - if not(BF.isDuplicateInList(num_str1,i,Uval)): + face2 = solid.Faces[index] + try: + UVNodes.append(face2.getUVNodes()) + except RuntimeError: + tess = face.tessellate(1.0, True) + UVNodes.append(face2.getUVNodes()) + + Uval_str_cl = [] + for i, elem1 in enumerate(Uval): + num_str1 = "%11.4E" % elem1 + if abs(elem1) < 1.0e-5: + num_str1 = "%11.4E" % 0.0 + if not (BF.isDuplicateInList(num_str1, i, Uval)): Uval_str_cl.append(num_str1) - - face_index_2=[face_index[0],face_index[0]] - - Node_min=UVNodes[0][0] - Node_max=UVNodes[0][1] - - dif1_0=abs(float(Uval_str_cl[0])-Node_min[0]) - dif2_0=abs(float(Uval_str_cl[1])-Node_max[0]) - + + face_index_2 = [face_index[0], face_index[0]] + + Node_min = UVNodes[0][0] + Node_max = UVNodes[0][1] + + dif1_0 = abs(float(Uval_str_cl[0]) - Node_min[0]) + dif2_0 = abs(float(Uval_str_cl[1]) - Node_max[0]) + # searching for minimum and maximum angle points - for j,Nodes in enumerate(UVNodes): + for j, Nodes in enumerate(UVNodes): for elem in Nodes: - val='%11.4E' %elem[0] - dif1=abs(float(Uval_str_cl[0])-elem[0]) - dif2=abs(float(Uval_str_cl[1])-elem[0]) - - if abs(elem[0])<1.0e-5: - val='%11.4E' %0.0 - if (dif1' and not(face2.isEqual(face)): - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Apex.isEqual(face.Surface.Apex,1e-5) and (face2.Surface.SemiAngle-face.Surface.SemiAngle) < 1e-6): + if face2.Area < tol.min_area: + if opt.verbose: + print( + f"Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) " + ) + continue + if str(face2.Surface) == "" and not (face2.isEqual(face)): + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Apex.isEqual(face.Surface.Apex, 1e-5) + and (face2.Surface.SemiAngle - face.Surface.SemiAngle) < 1e-6 + ): face_index.append(i) - - UMin,UMax = getUValueBoundary(solid,face_index,myIndex) - if UMin is None : return None - U1,i1 = UMin - U2,i2 = UMax + UMin, UMax = getUValueBoundary(solid, face_index, myIndex) + if UMin is None: + return None + + U1, i1 = UMin + U2, i2 = UMax + + V1 = solid.Faces[i1].ParameterRange[2] + V2 = solid.Faces[i2].ParameterRange[2] - V1 = solid.Faces[i1].ParameterRange[2] - V2 = solid.Faces[i2].ParameterRange[2] + P1 = solid.Faces[i1].valueAt(U1, V1) + P2 = solid.Faces[i2].valueAt(U2, V2) - P1 = solid.Faces[i1].valueAt(U1,V1) - P2 = solid.Faces[i2].valueAt(U2,V2) - - if (P1.isEqual(P2,1e-5)): - if opt.verbose : print('Error in the additional place definition') + if P1.isEqual(P2, 1e-5): + if opt.verbose: + print("Error in the additional place definition") return None - plane=Part.Plane(P1,P2,face.Surface.Apex).toShape() - + plane = Part.Plane(P1, P2, face.Surface.Apex).toShape() + return plane -def GenPlaneCone_old(face,solid): - Surf=face.Surface - rad=Surf.Radius - Axis=face.Surface.Axis - if (str(Surf)!=''): +def GenPlaneCone_old(face, solid): + + Surf = face.Surface + rad = Surf.Radius + Axis = face.Surface.Axis + if str(Surf) != "": return None - - face_index=[solid.Faces.index(face)] + + face_index = [solid.Faces.index(face)] for i, face2 in enumerate(solid.Faces): - if face2.Area < tol.min_area : - if opt.verbose : print(f'Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) ') - continue - if str(face2.Surface) == '' and not(face2.isEqual(face)): - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Apex.isEqual(face.Surface.Apex,1e-5) and (face2.Surface.SemiAngle-face.Surface.SemiAngle) < 1e-6): + if face2.Area < tol.min_area: + if opt.verbose: + print( + f"Warning: {str(Surf)} surface removed from cell definition. Face area < Min area ({face2.Area} < {tol.min_area}) " + ) + continue + if str(face2.Surface) == "" and not (face2.isEqual(face)): + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Apex.isEqual(face.Surface.Apex, 1e-5) + and (face2.Surface.SemiAngle - face.Surface.SemiAngle) < 1e-6 + ): face_index.append(i) - - AngleRange=0.0 - Uval=[] + + AngleRange = 0.0 + Uval = [] for index in face_index: - Range=solid.Faces[index].ParameterRange - AngleRange=AngleRange+abs(Range[1]-Range[0]) + Range = solid.Faces[index].ParameterRange + AngleRange = AngleRange + abs(Range[1] - Range[0]) Uval.append(Range[0]) Uval.append(Range[1]) - - if (2.0*math.pi-AngleRange<1e-2): + + if 2.0 * math.pi - AngleRange < 1e-2: return None - UVNodes=[] + UVNodes = [] for index in face_index: - face2 = solid.Faces[index] - try: - UVNodes.append(face2.getUVNodes()) - except RuntimeError: - face.tessellate(1.0,True) - UVNodes.append(face2.getUVNodes()) - - Uval_str_cl=[] - - for i,elem1 in enumerate(Uval): - num_str1='%11.4E' %elem1 - if abs(elem1)<1.0e-5: - num_str1='%11.4E' %0.0 - if not(BF.isDuplicateInList(num_str1,i,Uval)): + face2 = solid.Faces[index] + try: + UVNodes.append(face2.getUVNodes()) + except RuntimeError: + face.tessellate(1.0, True) + UVNodes.append(face2.getUVNodes()) + + Uval_str_cl = [] + + for i, elem1 in enumerate(Uval): + num_str1 = "%11.4E" % elem1 + if abs(elem1) < 1.0e-5: + num_str1 = "%11.4E" % 0.0 + if not (BF.isDuplicateInList(num_str1, i, Uval)): Uval_str_cl.append(num_str1) - - face_index_2=[face_index[0],face_index[0]] - - Node_min=UVNodes[0][0] - Node_max=UVNodes[0][1] - dif1_0=abs(float(Uval_str_cl[0])-Node_min[0]) - dif2_0=abs(float(Uval_str_cl[1])-Node_max[0]) - + + face_index_2 = [face_index[0], face_index[0]] + + Node_min = UVNodes[0][0] + Node_max = UVNodes[0][1] + dif1_0 = abs(float(Uval_str_cl[0]) - Node_min[0]) + dif2_0 = abs(float(Uval_str_cl[1]) - Node_max[0]) + # searching for minimum and maximum angle points - for j,Nodes in enumerate(UVNodes): + for j, Nodes in enumerate(UVNodes): for elem in Nodes: - val='%11.4E' %elem[0] - dif1=abs(float(Uval_str_cl[0])-elem[0]) - dif2=abs(float(Uval_str_cl[1])-elem[0]) - if abs(elem[0])<1.0e-5: - val='%11.4E' %0.0 - if (dif1','','Sphere') and orient=='Reversed'): + if ( + surfaceType in ("", "", "Sphere") + and orient == "Reversed" + ): # cone additional plane is added afterward - idFace=getId(face.Surface,Surfaces) - if surfaceType == '' : cones.add(idFace) + idFace = getId(face.Surface, Surfaces) + if surfaceType == "": + cones.add(idFace) if str(idFace) not in SurfPiece: SurfPiece.append(str(idFace)) SurfObj.append(face) try: - plane=GenPlane(face,solid_GU) + plane = GenPlane(face, solid_GU) if plane is not None: - plane=GU.Plane_GU(plane) + plane = GU.Plane_GU(plane) except: - plane=None - if opt.verbose : print('Warning: generation of additional plane has failed') - - if plane is not None : - p = GEOUNED_Surface(('Plane',(plane.Position,plane.Axis,plane.dim1,plane.dim2)),UniverseBox,Face='Build') - - id,exist = Surfaces.addPlane(p) - sign = signPlane(face.CenterOfMass,p) - if exist : - pp = Surfaces.getSurface(id) - if isOposite(p.Surf.Axis,pp.Surf.Axis,tol.angle): - id= -id - id *= sign - - if idFace not in extraPlaneReverse.keys(): - extraPlaneReverse[idFace] = [str(id)] - SurfObj.append(p.shape) - else: - if str(id) not in extraPlaneReverse[idFace] : - extraPlaneReverse[idFace].append(str(id)) - SurfObj.append(p.shape) - - - elif (surfaceType == '') : - - if (isParallel(face.Surface.Axis,FreeCAD.Vector(1,0,0),tol.angle) or \ - isParallel(face.Surface.Axis,FreeCAD.Vector(0,1,0),tol.angle) or \ - isParallel(face.Surface.Axis,FreeCAD.Vector(0,0,1),tol.angle)): - - idT=getId(face.Surface,Surfaces) - - index,Uparams = solid_GU.TorusUParams[iface] - if index == lastTorus : continue + plane = None + if opt.verbose: + print("Warning: generation of additional plane has failed") + + if plane is not None: + p = GEOUNED_Surface( + ("Plane", (plane.Position, plane.Axis, plane.dim1, plane.dim2)), + UniverseBox, + Face="Build", + ) + + id, exist = Surfaces.addPlane(p) + sign = signPlane(face.CenterOfMass, p) + if exist: + pp = Surfaces.getSurface(id) + if isOposite(p.Surf.Axis, pp.Surf.Axis, tol.angle): + id = -id + id *= sign + + if idFace not in extraPlaneReverse.keys(): + extraPlaneReverse[idFace] = [str(id)] + SurfObj.append(p.shape) + else: + if str(id) not in extraPlaneReverse[idFace]: + extraPlaneReverse[idFace].append(str(id)) + SurfObj.append(p.shape) + + elif surfaceType == "": + + if ( + isParallel(face.Surface.Axis, FreeCAD.Vector(1, 0, 0), tol.angle) + or isParallel(face.Surface.Axis, FreeCAD.Vector(0, 1, 0), tol.angle) + or isParallel(face.Surface.Axis, FreeCAD.Vector(0, 0, 1), tol.angle) + ): + + idT = getId(face.Surface, Surfaces) + + index, Uparams = solid_GU.TorusUParams[iface] + if index == lastTorus: + continue lastTorus = index - # add if necesary additional planes following U variable - UClosed,UminMax = Uparams - #UClosed = True - if not UClosed : - planes,ORop = GenTorusAnnexUPlanes(face,UminMax) - plane1,plane2 = planes - - plane = GEOUNED_Surface(('Plane',plane1),UniverseBox,Face='Build') - id1,exist = Surfaces.addPlane(plane) - if exist : + UClosed, UminMax = Uparams + # UClosed = True + if not UClosed: + planes, ORop = GenTorusAnnexUPlanes(face, UminMax) + plane1, plane2 = planes + + plane = GEOUNED_Surface( + ("Plane", plane1), UniverseBox, Face="Build" + ) + id1, exist = Surfaces.addPlane(plane) + if exist: p = Surfaces.getSurface(id1) - if isOposite(plane.Surf.Axis,p.Surf.Axis,tol.pln_angle): - id1=-id1 - - if plane2 is None : - UVar = '%i' %id1 - else: - plane = GEOUNED_Surface(('Plane',plane2),UniverseBox,Face='Build') - id2,exist = Surfaces.addPlane(plane) - if exist : - p = Surfaces.getSurface(id2) - if isOposite(plane.Surf.Axis,p.Surf.Axis,tol.pln_angle): - id2=-id2 - - UVar = '(%i : %i)' %(id1,id2) if ORop else '%i %i' %(id1,id2) - - + if isOposite(plane.Surf.Axis, p.Surf.Axis, tol.pln_angle): + id1 = -id1 + + if plane2 is None: + UVar = "%i" % id1 + else: + plane = GEOUNED_Surface( + ("Plane", plane2), UniverseBox, Face="Build" + ) + id2, exist = Surfaces.addPlane(plane) + if exist: + p = Surfaces.getSurface(id2) + if isOposite( + plane.Surf.Axis, p.Surf.Axis, tol.pln_angle + ): + id2 = -id2 + + UVar = ( + "(%i : %i)" % (id1, id2) + if ORop + else "%i %i" % (id1, id2) + ) + else: - UVar = '' + UVar = "" - # add if necesary additional surface following V variable - if (orient == 'Forward'): - VVar = '-%i' %idT + if orient == "Forward": + VVar = "-%i" % idT else: - index,Vparams = solid_GU.TorusVParams[iface] - VClosed,VminMax = Vparams - if VClosed : - VVar = '%i' %idT + index, Vparams = solid_GU.TorusVParams[iface] + VClosed, VminMax = Vparams + if VClosed: + VVar = "%i" % idT else: - surfParams,surfType,inSurf = GenTorusAnnexVSurface(face,VminMax,opt.forceCylinder) - - if surfType == 'Cone' : - cone = GEOUNED_Surface(('Cone',surfParams),UniverseBox,Face='Build') - id2,exist = Surfaces.addCone(cone) - - elif surfType == 'Cylinder' : - cyl = GEOUNED_Surface(('Cylinder',surfParams),UniverseBox,Face='Build') - id2,exist = Surfaces.addCylinder(cyl) - - elif surfType == 'Plane' : - plane = GEOUNED_Surface(('Plane',surfParams),UniverseBox,Face='Build') - id2,exist = Surfaces.addPlane(plane) - if exist : - p = Surfaces.getSurface(id2) - if isOposite(plane.Surf.Axis,p.Surf.Axis,tol.pln_angle): - id2=-id2 - - VVar = '%i %i' %(idT,-id2 if inSurf else id2) - - var = VVar if UClosed else ' '.join((VVar,UVar)) - if (var not in SurfPiece): + surfParams, surfType, inSurf = GenTorusAnnexVSurface( + face, VminMax, opt.forceCylinder + ) + + if surfType == "Cone": + cone = GEOUNED_Surface( + ("Cone", surfParams), UniverseBox, Face="Build" + ) + id2, exist = Surfaces.addCone(cone) + + elif surfType == "Cylinder": + cyl = GEOUNED_Surface( + ("Cylinder", surfParams), UniverseBox, Face="Build" + ) + id2, exist = Surfaces.addCylinder(cyl) + + elif surfType == "Plane": + plane = GEOUNED_Surface( + ("Plane", surfParams), UniverseBox, Face="Build" + ) + id2, exist = Surfaces.addPlane(plane) + if exist: + p = Surfaces.getSurface(id2) + if isOposite( + plane.Surf.Axis, p.Surf.Axis, tol.pln_angle + ): + id2 = -id2 + + VVar = "%i %i" % (idT, -id2 if inSurf else id2) + + var = VVar if UClosed else " ".join((VVar, UVar)) + if var not in SurfPiece: SurfPiece.append(var) SurfObj.append(face) else: - if opt.verbose : print('Only Torus with axis along X, Y , Z axis can be reproduced') + if opt.verbose: + print( + "Only Torus with axis along X, Y , Z axis can be reproduced" + ) else: - id=getId(face.Surface,Surfaces) - if surfaceType == '' : cones.add(-id) + id = getId(face.Surface, Surfaces) + if surfaceType == "": + cones.add(-id) surf = face if id == 0: - if opt.verbose : print('Warning: ', surfaceType, ' not found in surface list') - if surfaceType == '' : - dim1 = face.ParameterRange[1]-face.ParameterRange[0] - dim2 = face.ParameterRange[3]-face.ParameterRange[2] - plane = GEOUNED_Surface(('Plane',(face.Surface.Position,face.Surface.Axis,dim1,dim2)),UniverseBox,Face='Build') - id,exist = Surfaces.addPlane(plane) - surf = plane.shape - elif surfaceType == '': - dimL = face.ParameterRange[3]-face.ParameterRange[2] - cylinder = GEOUNED_Surface(('Cylinder',(face.Surface.Center,face.Surface.Axis,face.Surface.Radius,dimL)),UniverseBox,Face='Build') - id,exist = Surfaces.addCylinder(cylinder) - surf = cylinder.shape - - if orient == 'Reversed': - var=id - elif orient == 'Forward': - var=-id - - if surfaceType == '': - s = Surfaces.getSurface(id) - if isOposite(face.Surface.Axis,s.Surf.Axis,tol.pln_angle) : - var=-var - - if str(var) in SurfPiece: continue + if opt.verbose: + print("Warning: ", surfaceType, " not found in surface list") + if surfaceType == "": + dim1 = face.ParameterRange[1] - face.ParameterRange[0] + dim2 = face.ParameterRange[3] - face.ParameterRange[2] + plane = GEOUNED_Surface( + ( + "Plane", + (face.Surface.Position, face.Surface.Axis, dim1, dim2), + ), + UniverseBox, + Face="Build", + ) + id, exist = Surfaces.addPlane(plane) + surf = plane.shape + elif surfaceType == "": + dimL = face.ParameterRange[3] - face.ParameterRange[2] + cylinder = GEOUNED_Surface( + ( + "Cylinder", + ( + face.Surface.Center, + face.Surface.Axis, + face.Surface.Radius, + dimL, + ), + ), + UniverseBox, + Face="Build", + ) + id, exist = Surfaces.addCylinder(cylinder) + surf = cylinder.shape + + if orient == "Reversed": + var = id + elif orient == "Forward": + var = -id + + if surfaceType == "": + s = Surfaces.getSurface(id) + if isOposite(face.Surface.Axis, s.Surf.Axis, tol.pln_angle): + var = -var + + if str(var) in SurfPiece: + continue SurfPiece.append(str(var)) SurfObj.append(surf) - if extraPlaneReverse : - for extra in extraPlaneReverse.values() : - if len(extra) ==1 : - if extra[0] not in SurfPiece: - SurfPiece.append(extra[0]) - else: - SurfPiece.append('({})'.format(':'.join(extra))) + if extraPlaneReverse: + for extra in extraPlaneReverse.values(): + if len(extra) == 1: + if extra[0] not in SurfPiece: + SurfPiece.append(extra[0]) + else: + SurfPiece.append("({})".format(":".join(extra))) - SurfPieceBool = BoolSequence(' '.join(SurfPiece)) + SurfPieceBool = BoolSequence(" ".join(SurfPiece)) # possible expresion for e # i1 # i1 i2SurfPiece # i1 i2 i3 # (i1:i2) # i1 (i2:i3) - - # semi = e.find(':') - # blk = e.find(' ') - # print (e) - # if semi != -1 : - # orTerm = expOR(int(e[1:semi]),int(e[semi+1:-1])) - # SurfPieceBool.add(orTerm) - # elif blk != -1 : - # SurfPieceBool.add(int(e[1:blk]),int(e[blk+1:-1])) - # else : - # SurfPieceBool.add(int(e)) - - if SurfPieceBool.elements : - PieceDef.append(SurfPieceBool) - PieceObj.append(SurfObj) + + # semi = e.find(':') + # blk = e.find(' ') + # print (e) + # if semi != -1 : + # orTerm = expOR(int(e[1:semi]),int(e[semi+1:-1])) + # SurfPieceBool.add(orTerm) + # elif blk != -1 : + # SurfPieceBool.add(int(e[1:blk]),int(e[blk+1:-1])) + # else : + # SurfPieceBool.add(int(e)) + + if SurfPieceBool.elements: + PieceDef.append(SurfPieceBool) + PieceObj.append(SurfObj) else: - delList.append(isol) + delList.append(isol) - for isol in reversed(delList) : - del metaObj.Solids[isol] + for isol in reversed(delList): + del metaObj.Solids[isol] metaObj.setDefinition(PieceDef) metaObj.setFaces(PieceObj) return tuple(cones) - -def getSurfValue(Definition,reverse = False): +def getSurfValue(Definition, reverse=False): if Definition.level == 0: - if reverse : - surf = { -i for i in Definition.elements} - else: - surf = set(Definition.elements) + if reverse: + surf = {-i for i in Definition.elements} + else: + surf = set(Definition.elements) else: - surf = set() - for e in Definition.elements: - if e.operator == 'AND': - if reverse : - surf = { -i for i in e.elements} - else: - surf = set(e.elements) - break + surf = set() + for e in Definition.elements: + if e.operator == "AND": + if reverse: + surf = {-i for i in e.elements} + else: + surf = set(e.elements) + break return surf +def appendComp(newCell, cellDef, cellCAD, metaComplementary): -def appendComp(newCell,cellDef,cellCAD,metaComplementary): - surfCell = getSurfValue(cellDef, True) - if metaComplementary.Definition.operator == 'AND': - if not cellCAD.BoundBox.intersect(metaComplementary.CADSolid.BoundBox) : return False - Seq = metaComplementary.Definition - surfComp = getSurfValue(Seq, False) - if len(surfComp & surfCell) > 0 : return False - newCell.append(Seq.getComplementary()) - return True + if metaComplementary.Definition.operator == "AND": + if not cellCAD.BoundBox.intersect(metaComplementary.CADSolid.BoundBox): + return False + Seq = metaComplementary.Definition + surfComp = getSurfValue(Seq, False) + if len(surfComp & surfCell) > 0: + return False + newCell.append(Seq.getComplementary()) + return True else: - append = False - for i,compPart in enumerate(metaComplementary.Solids) : - if not cellCAD.BoundBox.intersect(compPart.BoundBox) : continue - Seq = metaComplementary.Definition.elements[i] - surfComp = getSurfValue(Seq, False) - if len(surfComp & surfCell) > 0 : continue - append = True - newCell.append(Seq.getComplementary()) - return append + append = False + for i, compPart in enumerate(metaComplementary.Solids): + if not cellCAD.BoundBox.intersect(compPart.BoundBox): + continue + Seq = metaComplementary.Definition.elements[i] + surfComp = getSurfValue(Seq, False) + if len(surfComp & surfCell) > 0: + continue + append = True + newCell.append(Seq.getComplementary()) + return append - - -def noOverlappingCell(metaList,Surfaces): +def noOverlappingCell(metaList, Surfaces): Surfs = {} for lst in Surfaces.values(): for s in lst: - Surfs[s.Index] = s + Surfs[s.Index] = s newDefinitionList = [] metaList[0].setCADSolid() - for i,m in enumerate(metaList[1:]): + for i, m in enumerate(metaList[1:]): m.setCADSolid() - if m.Definition.operator == 'AND' : - newDef = BoolSequence(operator= 'AND') + if m.Definition.operator == "AND": + newDef = BoolSequence(operator="AND") newDef.append(m.Definition.copy()) simplify = False - for mm in metaList[:i+1] : - simp = appendComp(newDef,m.Definition,m.CADSolid,mm) - if simp : simplify = True + for mm in metaList[: i + 1]: + simp = appendComp(newDef, m.Definition, m.CADSolid, mm) + if simp: + simplify = True simpTerm = [simplify] else: - newDef = BoolSequence(operator= 'OR') + newDef = BoolSequence(operator="OR") simpTerm = [] - for j,partSolid in enumerate(m.Solids): - subDef = BoolSequence(operator= 'AND') - subDef.append(m.Definition.elements[j].copy()) - simplify = False - for mm in metaList[:i+1] : - simp = appendComp(subDef,m.Definition.elements[j],partSolid,mm) - if simp : simplify = True - simpTerm.append(simplify) - newDef.append(subDef) - newDefinitionList.append((newDef,simpTerm)) - - - for m,tDef in zip(metaList[1:],newDefinitionList): - Def,simplify = tDef - if True in simplify : - print(f'reduce cell {m.__id__}') - Box = UF.getBox(m) - - # evaluate only diagonal elements of the Constraint Table (fastest) and remove surface not - # crossing in the solid boundBox - CT = buildCTableFromSolids(Box,(tuple(Def.getSurfacesNumbers()),Surfs),option='diag') - - newDef = removeExtraSurfaces(Def,CT) - - # evaluate full constraint Table with less surfaces involved - CT = buildCTableFromSolids(Box,(tuple(newDef.getSurfacesNumbers()),Surfs),option='full') - - if newDef.operator == 'AND' : - newDef.simplify(CT) - newDef.clean() - else: - for i,s in enumerate(simplify): - if not s : continue - comp = newDef.elements[i] - comp.simplify(CT) - comp.clean() - - m.setDefinition(newDef) - m.Definition.joinOperators() - m.Definition.levelUpdate() - - -def ExtraPlaneCylFace(face,Box,Surfaces): - wire = face.OuterWire - planesId = [] - for e in wire.OrderedEdges : - curve = str(e.Curve) - if (curve[0:6] == 'Circle' or curve == '' ): - dir = e.Curve.Axis - center = e.Curve.Center - if curve == '' : - dim1 = e.Curve.MinorRadius - dim2 = e.Curve.MajorRadius - else: - dim1 = e.Curve.Radius - dim2 = e.Curve.Radius - plane = GEOUNED_Surface(('Plane',(center,dir,dim1,dim2)),Box,Face='Build') - sign = signPlane(face.CenterOfMass,plane) - id,exist = Surfaces.addPlane(plane) - if exist : - pp = Surfaces.getSurface(id) - if isOposite(plane.Surf.Axis,pp.Surf.Axis,tol.pln_angle): - id=-id - planesId.append(id) - return planesId - -def addConePlane(Definition, conesList, Surfaces, UniverseBox): - x_axis = FreeCAD.Vector(1,0,0) - y_axis = FreeCAD.Vector(0,1,0) - z_axis = FreeCAD.Vector(0,0,1) + for j, partSolid in enumerate(m.Solids): + subDef = BoolSequence(operator="AND") + subDef.append(m.Definition.elements[j].copy()) + simplify = False + for mm in metaList[: i + 1]: + simp = appendComp(subDef, m.Definition.elements[j], partSolid, mm) + if simp: + simplify = True + simpTerm.append(simplify) + newDef.append(subDef) + newDefinitionList.append((newDef, simpTerm)) + + for m, tDef in zip(metaList[1:], newDefinitionList): + Def, simplify = tDef + if True in simplify: + print(f"reduce cell {m.__id__}") + Box = UF.getBox(m) + + # evaluate only diagonal elements of the Constraint Table (fastest) and remove surface not + # crossing in the solid boundBox + CT = buildCTableFromSolids( + Box, (tuple(Def.getSurfacesNumbers()), Surfs), option="diag" + ) + + newDef = removeExtraSurfaces(Def, CT) + + # evaluate full constraint Table with less surfaces involved + CT = buildCTableFromSolids( + Box, (tuple(newDef.getSurfacesNumbers()), Surfs), option="full" + ) + + if newDef.operator == "AND": + newDef.simplify(CT) + newDef.clean() + else: + for i, s in enumerate(simplify): + if not s: + continue + comp = newDef.elements[i] + comp.simplify(CT) + comp.clean() - for cid in conesList: - cone = Surfaces.getSurface(abs(cid)) - if isParallel(cone.Surf.Axis,x_axis,tol.angle) or \ - isParallel(cone.Surf.Axis,y_axis,tol.angle) or \ - isParallel(cone.Surf.Axis,z_axis,tol.angle) : continue + m.setDefinition(newDef) + m.Definition.joinOperators() + m.Definition.levelUpdate() - plane = GEOUNED_Surface(('Plane',(cone.Surf.Apex,cone.Surf.Axis,1,1)),UniverseBox,Face='Build') - pid,exist = Surfaces.addPlane(plane) - if exist : - p = Surfaces.getSurface(pid) - if isOposite(plane.Surf.Axis,p.Surf.Axis,tol.pln_angle): - pid= -pid +def ExtraPlaneCylFace(face, Box, Surfaces): + wire = face.OuterWire + planesId = [] + for e in wire.OrderedEdges: + curve = str(e.Curve) + if curve[0:6] == "Circle" or curve == "": + dir = e.Curve.Axis + center = e.Curve.Center + if curve == "": + dim1 = e.Curve.MinorRadius + dim2 = e.Curve.MajorRadius + else: + dim1 = e.Curve.Radius + dim2 = e.Curve.Radius + plane = GEOUNED_Surface( + ("Plane", (center, dir, dim1, dim2)), Box, Face="Build" + ) + sign = signPlane(face.CenterOfMass, plane) + id, exist = Surfaces.addPlane(plane) + if exist: + pp = Surfaces.getSurface(id) + if isOposite(plane.Surf.Axis, pp.Surf.Axis, tol.pln_angle): + id = -id + planesId.append(id) + return planesId - if cid > 0 : - insertInSequence(Definition,cid,-pid,'OR') +def addConePlane(Definition, conesList, Surfaces, UniverseBox): + x_axis = FreeCAD.Vector(1, 0, 0) + y_axis = FreeCAD.Vector(0, 1, 0) + z_axis = FreeCAD.Vector(0, 0, 1) + + for cid in conesList: + cone = Surfaces.getSurface(abs(cid)) + if ( + isParallel(cone.Surf.Axis, x_axis, tol.angle) + or isParallel(cone.Surf.Axis, y_axis, tol.angle) + or isParallel(cone.Surf.Axis, z_axis, tol.angle) + ): + continue + + plane = GEOUNED_Surface( + ("Plane", (cone.Surf.Apex, cone.Surf.Axis, 1, 1)), UniverseBox, Face="Build" + ) + pid, exist = Surfaces.addPlane(plane) + + if exist: + p = Surfaces.getSurface(pid) + if isOposite(plane.Surf.Axis, p.Surf.Axis, tol.pln_angle): + pid = -pid + + if cid > 0: + insertInSequence(Definition, cid, -pid, "OR") else: - insertInSequence(Definition,cid,pid,'AND') - + insertInSequence(Definition, cid, pid, "AND") diff --git a/src/geouned/GEOUNED/Cuboid/translate.py b/src/geouned/GEOUNED/Cuboid/translate.py index 9db5881c..b07a6d61 100644 --- a/src/geouned/GEOUNED/Cuboid/translate.py +++ b/src/geouned/GEOUNED/Cuboid/translate.py @@ -10,137 +10,154 @@ from ..Utils.Options.Classes import Tolerances as tol -def commonEdge(face1,face2): - for e1 in face1.Edges: - for e2 in face2.Edges: - if e1.isSame(e2): - return e1 - return None - -def isConvex(face1,face2,edge): +def commonEdge(face1, face2): + for e1 in face1.Edges: + for e2 in face2.Edges: + if e1.isSame(e2): + return e1 + return None + + +def isConvex(face1, face2, edge): de = 0.1 - tol = 1.e-5 - e = edge.Vertexes[1].Point-edge.Vertexes[0].Point + tol = 1.0e-5 + e = edge.Vertexes[1].Point - edge.Vertexes[0].Point e.normalize() V = e.cross(face2.Surface.Axis) - P = edge.CenterOfMass + de*V - if not face2.__face__.isInside(P,tol,True) : - V = -V - + P = edge.CenterOfMass + de * V + if not face2.__face__.isInside(P, tol, True): + V = -V convex = False - if face1.Surface.Axis.dot(V) < 0 : - if face1.Orientation == 'Forward' : - convex = True + if face1.Surface.Axis.dot(V) < 0: + if face1.Orientation == "Forward": + convex = True else: - if face1.Orientation == 'Reversed' : - convex = True + if face1.Orientation == "Reversed": + convex = True return convex -def removeElement(Faces,idf): - for i,f in enumerate(Faces): - if f[0] == idf: - del(Faces[i]) - break + +def removeElement(Faces, idf): + for i, f in enumerate(Faces): + if f[0] == idf: + del Faces[i] + break + def isInverted(solid): face = solid.Faces[0] - Range=face.ParameterRange - u=(Range[1]+Range[0])/2.0 - v=(Range[3]+Range[2])/2.0 + Range = face.ParameterRange + u = (Range[1] + Range[0]) / 2.0 + v = (Range[3] + Range[2]) / 2.0 - point2=face.CenterOfMass.add(face.normalAt(u,v).multiply(1.0e-6)) + point2 = face.CenterOfMass.add(face.normalAt(u, v).multiply(1.0e-6)) - if (solid.isInside(point2,1e-7,False)): - return True - else: - return False + if solid.isInside(point2, 1e-7, False): + return True + else: + return False def getId(facein, Surfaces): - - if isParallel(facein.Axis,FreeCAD.Vector(1,0,0),tol.pln_angle) : - P = 'PX' - elif isParallel(facein.Axis,FreeCAD.Vector(0,1,0),tol.pln_angle) : - P = 'PY' - elif isParallel(facein.Axis,FreeCAD.Vector(0,0,1),tol.pln_angle) : - P = 'PZ' + + if isParallel(facein.Axis, FreeCAD.Vector(1, 0, 0), tol.pln_angle): + P = "PX" + elif isParallel(facein.Axis, FreeCAD.Vector(0, 1, 0), tol.pln_angle): + P = "PY" + elif isParallel(facein.Axis, FreeCAD.Vector(0, 0, 1), tol.pln_angle): + P = "PZ" else: - P = 'P' + P = "P" + + for s in Surfaces[P]: + if BF.isSamePlane( + facein, + s.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + ): + return s.Index - for s in Surfaces[P] : - if BF.isSamePlane(facein,s.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol) : - return s.Index - return 0 -def translate(MetaList,Surfaces,UniverseBox,setting): + +def translate(MetaList, Surfaces, UniverseBox, setting): totsolid = len(MetaList) - for i,m in enumerate(MetaList): - if m.IsEnclosure: continue - print('Decomposing solid: {}/{} '.format(i,totsolid)) - if setting['debug'] : + for i, m in enumerate(MetaList): + if m.IsEnclosure: + continue + print("Decomposing solid: {}/{} ".format(i, totsolid)) + if setting["debug"]: print(m.Comments) - if m.IsEnclosure : - m.Solids[0].exportStep('origEnclosure_{}.stp'.format(i)) - else: - m.Solids[0].exportStep('origSolid_{}.stp'.format(i)) - - Surfaces.extend(Decom.ExtractSurfaces(Part.makeCompound(m.Solids),'Plane3Pts',UniverseBox,MakeObj=False)) - setDefinition(m,Surfaces) - - -def setDefinition(metaObj,Surfaces): - solids = metaObj.Solids - sDef = BoolSequence(operator='OR') - - for sol in solids : - subSol = BoolSequence(operator='AND') - flag_inv=isInverted(sol) - solid_GU=GU.solid_GU(sol,plane3Pts=True) - - - Faces = [] - for face in solid_GU.Faces : - if abs(face.Area) < 1e-2 : continue - if face.Area < 0 : - if opt.verbose : print('Warning : Negative surface Area') - if str(face.Surface) != '' : - print('Warning : All surfaces must be plane') - continue - if face.Orientation not in ('Forward','Reversed') : continue - - id=getId(face.Surface,Surfaces) - s = Surfaces.getSurface(id) - if isOposite(face.Surface.Axis,s.Surf.Axis,tol.pln_angle) : id = -id - if face.Orientation == 'Forward' : id = -id - if flag_inv : id = -id - Faces.append((id,face)) - - - while len(Faces) > 0 : - id1,face1 = Faces[0] - noConvex = [] - for id2,face2 in Faces[1:] : - edge = commonEdge(face1,face2) - if edge is None : continue - if not isConvex(face1,face2,edge) : - noConvex.append(id2) - - if noConvex != [] : - noConvex.insert(0,id1) - for i in noConvex : - removeElement(Faces,i) - orPlanes = BoolSequence(operator='OR') - orPlanes.append(*noConvex) - subSol.append(orPlanes) - else: - removeElement(Faces,id1) - subSol.append(id1) - - sDef.append(subSol) - - - metaObj.setDefinition(sDef) - + if m.IsEnclosure: + m.Solids[0].exportStep("origEnclosure_{}.stp".format(i)) + else: + m.Solids[0].exportStep("origSolid_{}.stp".format(i)) + + Surfaces.extend( + Decom.ExtractSurfaces( + Part.makeCompound(m.Solids), "Plane3Pts", UniverseBox, MakeObj=False + ) + ) + setDefinition(m, Surfaces) + + +def setDefinition(metaObj, Surfaces): + solids = metaObj.Solids + sDef = BoolSequence(operator="OR") + + for sol in solids: + subSol = BoolSequence(operator="AND") + flag_inv = isInverted(sol) + solid_GU = GU.solid_GU(sol, plane3Pts=True) + + Faces = [] + for face in solid_GU.Faces: + if abs(face.Area) < 1e-2: + continue + if face.Area < 0: + if opt.verbose: + print("Warning : Negative surface Area") + if str(face.Surface) != "": + print("Warning : All surfaces must be plane") + continue + if face.Orientation not in ("Forward", "Reversed"): + continue + + id = getId(face.Surface, Surfaces) + s = Surfaces.getSurface(id) + if isOposite(face.Surface.Axis, s.Surf.Axis, tol.pln_angle): + id = -id + if face.Orientation == "Forward": + id = -id + if flag_inv: + id = -id + Faces.append((id, face)) + + while len(Faces) > 0: + id1, face1 = Faces[0] + noConvex = [] + for id2, face2 in Faces[1:]: + edge = commonEdge(face1, face2) + if edge is None: + continue + if not isConvex(face1, face2, edge): + noConvex.append(id2) + + if noConvex != []: + noConvex.insert(0, id1) + for i in noConvex: + removeElement(Faces, i) + orPlanes = BoolSequence(operator="OR") + orPlanes.append(*noConvex) + subSol.append(orPlanes) + else: + removeElement(Faces, id1) + subSol.append(id1) + + sDef.append(subSol) + + metaObj.setDefinition(sDef) diff --git a/src/geouned/GEOUNED/Decompose/Decom_one.py b/src/geouned/GEOUNED/Decompose/Decom_one.py index f0f57bf3..bc3167e3 100644 --- a/src/geouned/GEOUNED/Decompose/Decom_one.py +++ b/src/geouned/GEOUNED/Decompose/Decom_one.py @@ -1,4 +1,4 @@ -# Conversion to MCNP v0.0 +# Conversion to MCNP v0.0 # Only one solid and planar surfaces # @@ -11,14 +11,14 @@ from ..Conversion import CellDefinition as CD from ..Utils import Functions as UF from ..Utils import Geometry_GU as GU -from ..Utils.BasicFunctions_part1 import (isInLine, isInPlane, isParallel, - isSameValue) +from ..Utils.BasicFunctions_part1 import isInLine, isInPlane, isParallel, isSameValue from ..Utils.BasicFunctions_part2 import isDuplicateInList from ..Utils.Options.Classes import Options as opt from ..Utils.Options.Classes import Tolerances as tol -twoPi = math.pi*2 - +twoPi = math.pi * 2 + + def splitFullCylinder(solid): explode = [] Bases = [solid] @@ -30,381 +30,424 @@ def splitFullCylinder(solid): explode.extend(cutSolids) else: newBases.extend(cutSolids) - if len(newBases) == 0 : + if len(newBases) == 0: break else: Bases = newBases - + return Part.makeCompound(explode) + def cutFullCylinder(solid): solid_GU = GU.solid_GU(solid) - Surfaces=UF.Surfaces_dict() + Surfaces = UF.Surfaces_dict() flag_inv = CD.isInverted(solid_GU.solid) UniverseBox = solid.BoundBox for face in solid_GU.Faces: - surf = str(face.Surface) - if surf == '' : - if (flag_inv): - orient = 'Reversed' if face.Orientation =='Forward' else 'Forward' - else: - orient=face.Orientation - - u1,u2,v1,v2 = face.ParameterRange - angle = abs(u2-u1) - - # closed convex cylinder - if abs(angle%twoPi) < 1e-2 and orient=='Forward': - dir = face.Surface.Axis - orig = face.Surface.Center - rad = face.Surface.Radius - dimL = face.ParameterRange[3]-face.ParameterRange[2] - cylinder = UF.GEOUNED_Surface(('Cylinder',(orig,dir,rad,dimL)),UniverseBox) - cylinder.buildSurface() - Surfaces.addCylinder(cylinder,False) - - #add planes if cylinder axis is cut by a plane (plane quasi perpedicular to axis) - for p in CylBoundPlanes(face,UniverseBox) : - p.buildSurface() - Surfaces.addPlane(p,False) - break - - Planes = [] - for P in ('PX','PY','PZ','P') : Planes.extend(Surfaces[P]) - Planes = sortPlanes(Planes,True) - - - if len(Planes) == 0 : return [solid] - if len(Planes[-1]) < opt.nPlaneReverse : Planes.reverse() + surf = str(face.Surface) + if surf == "": + if flag_inv: + orient = "Reversed" if face.Orientation == "Forward" else "Forward" + else: + orient = face.Orientation + + u1, u2, v1, v2 = face.ParameterRange + angle = abs(u2 - u1) + + # closed convex cylinder + if abs(angle % twoPi) < 1e-2 and orient == "Forward": + dir = face.Surface.Axis + orig = face.Surface.Center + rad = face.Surface.Radius + dimL = face.ParameterRange[3] - face.ParameterRange[2] + cylinder = UF.GEOUNED_Surface( + ("Cylinder", (orig, dir, rad, dimL)), UniverseBox + ) + cylinder.buildSurface() + Surfaces.addCylinder(cylinder, False) + + # add planes if cylinder axis is cut by a plane (plane quasi perpedicular to axis) + for p in CylBoundPlanes(face, UniverseBox): + p.buildSurface() + Surfaces.addPlane(p, False) + break + + Planes = [] + for P in ("PX", "PY", "PZ", "P"): + Planes.extend(Surfaces[P]) + Planes = sortPlanes(Planes, True) + + if len(Planes) == 0: + return [solid] + if len(Planes[-1]) < opt.nPlaneReverse: + Planes.reverse() cut = False - for pp in Planes : - # cut with more external parallel planes - pp[0].buildSurface() - if len(pp) != 1: - pp[-1].buildSurface() - tools = (pp[0].shape, pp[-1].shape) - else: - tools = (pp[0].shape,) - - try : - comsolid = UF.splitBOP(solid,tools,opt.splitTolerance) - except : - comsolid = solid - if len(comsolid.Solids) > 1 : - outSolid = comsolid.Solids - cut = True - break - - if cut : return outSolid - - tool = (Surfaces['Cyl'][0].shape,) - try : - comsolid = UF.splitBOP(solid,tool,opt.splitTolerance) - except : - comsolid = solid - - if len(comsolid.Solids) > 1 : - outSolid = comsolid.Solids + for pp in Planes: + # cut with more external parallel planes + pp[0].buildSurface() + if len(pp) != 1: + pp[-1].buildSurface() + tools = (pp[0].shape, pp[-1].shape) + else: + tools = (pp[0].shape,) + + try: + comsolid = UF.splitBOP(solid, tools, opt.splitTolerance) + except: + comsolid = solid + if len(comsolid.Solids) > 1: + outSolid = comsolid.Solids + cut = True + break + + if cut: + return outSolid + + tool = (Surfaces["Cyl"][0].shape,) + try: + comsolid = UF.splitBOP(solid, tool, opt.splitTolerance) + except: + comsolid = solid + + if len(comsolid.Solids) > 1: + outSolid = comsolid.Solids else: - outSolid = [solid] + outSolid = [solid] - return outSolid + return outSolid -def GenPlane(pos,normal,diag): - plane = Part.makePlane(diag,diag,pos,normal) - vec_on_plane= plane.Vertexes[3].Point.sub(plane.Vertexes[0].Point) +def GenPlane(pos, normal, diag): + plane = Part.makePlane(diag, diag, pos, normal) + vec_on_plane = plane.Vertexes[3].Point.sub(plane.Vertexes[0].Point) new_pos = plane.Vertexes[0].Point.sub(vec_on_plane) - plane_center = Part.makePlane(2.0*diag,2.0*diag,new_pos,normal) + plane_center = Part.makePlane(2.0 * diag, 2.0 * diag, new_pos, normal) return plane_center -def CylBoundPlanes(face,boundBox): - Edges=face.OuterWire.Edges + +def CylBoundPlanes(face, boundBox): + Edges = face.OuterWire.Edges planes = [] for e in Edges: - try: - curve = str(e.Curve) - except: - curve = 'none' - - if curve[0:6] == 'Circle' : - dir = e.Curve.Axis - center = e.Curve.Center - dim1 = e.Curve.Radius - dim2 = e.Curve.Radius - plane = UF.GEOUNED_Surface(('Plane',(center,dir,dim1,dim2)),boundBox) - planes.append(plane) - - elif curve == '' : - dir = e.Curve.Axis - center = e.Curve.Center - dim1 = e.Curve.MinorRadius - dim2 = e.Curve.MajorRadius - plane = UF.GEOUNED_Surface(('Plane',(center,dir,dim1,dim2)),boundBox) - planes.append(plane) + try: + curve = str(e.Curve) + except: + curve = "none" + + if curve[0:6] == "Circle": + dir = e.Curve.Axis + center = e.Curve.Center + dim1 = e.Curve.Radius + dim2 = e.Curve.Radius + plane = UF.GEOUNED_Surface(("Plane", (center, dir, dim1, dim2)), boundBox) + planes.append(plane) + + elif curve == "": + dir = e.Curve.Axis + center = e.Curve.Center + dim1 = e.Curve.MinorRadius + dim2 = e.Curve.MajorRadius + plane = UF.GEOUNED_Surface(("Plane", (center, dir, dim1, dim2)), boundBox) + planes.append(plane) return planes -def TorusBoundPlanes(face,boundBox): +def TorusBoundPlanes(face, boundBox): params = face.ParameterRange planes = [] - if isSameValue(params[1]-params[0],twoPi,tol.value) : return planes - - Edges=face.OuterWire.Edges - + if isSameValue(params[1] - params[0], twoPi, tol.value): + return planes + + Edges = face.OuterWire.Edges + for e in Edges: - try: - curve = str(e.Curve) - except: - curve = 'none' - - if curve[0:6] == 'Circle' : - dir = e.Curve.Axis - if not isParallel (dir,face.Surface.Axis,tol.angle) : + try: + curve = str(e.Curve) + except: + curve = "none" + + if curve[0:6] == "Circle": + dir = e.Curve.Axis + if not isParallel(dir, face.Surface.Axis, tol.angle): + center = e.Curve.Center + dim1 = e.Curve.Radius + dim2 = e.Curve.Radius + plane = UF.GEOUNED_Surface( + ("Plane", (center, dir, dim1, dim2)), boundBox + ) + planes.append(plane) + + elif curve == "": + dir = e.Curve.Axis center = e.Curve.Center - dim1 = e.Curve.Radius - dim2 = e.Curve.Radius - plane = UF.GEOUNED_Surface(('Plane',(center,dir,dim1,dim2)),boundBox) + dim1 = e.Curve.MinorRadius + dim2 = e.Curve.MajorRadius + plane = UF.GEOUNED_Surface(("Plane", (center, dir, dim1, dim2)), boundBox) planes.append(plane) - - elif curve == '' : - dir = e.Curve.Axis - center = e.Curve.Center - dim1 = e.Curve.MinorRadius - dim2 = e.Curve.MajorRadius - plane = UF.GEOUNED_Surface(('Plane',(center,dir,dim1,dim2)),boundBox) - planes.append(plane) - - elif curve == '' : - planeParams = PlaneSplineCurve(e) - if planeParams is not None: - plane = UF.GEOUNED_Surface(('Plane',planeParams),boundBox) - planes.append(plane) + + elif curve == "": + planeParams = PlaneSplineCurve(e) + if planeParams is not None: + plane = UF.GEOUNED_Surface(("Plane", planeParams), boundBox) + planes.append(plane) return planes + def PlaneSplineCurve(edge): normal = edge.derivative1At(0).cross(edge.derivative1At(0.5)) normal.normalize() curve2D = True - for p in (0.25,0.75,1) : - # check if derivative orthogonal to curve normal vector - if abs(normal.dot(edge.derivative1At(p))) > tol.value : - curve2D = False - break - - r = edge.valueAt(0.25)-edge.valueAt(0.75) - if curve2D: - return (edge.valueAt(0),normal,r.Length,r.Length) + for p in (0.25, 0.75, 1): + # check if derivative orthogonal to curve normal vector + if abs(normal.dot(edge.derivative1At(p))) > tol.value: + curve2D = False + break + + r = edge.valueAt(0.25) - edge.valueAt(0.75) + if curve2D: + return (edge.valueAt(0), normal, r.Length, r.Length) else: - return None + return None -def ExtractSurfaces(solid,kind,UniverseBox,MakeObj=False): - if kind == 'All': - fuzzy = True - solidParts = [] - for s in solid.Solids: - solidParts.append(GU.solid_GU(s)) +def ExtractSurfaces(solid, kind, UniverseBox, MakeObj=False): + if kind == "All": + fuzzy = True + solidParts = [] + for s in solid.Solids: + solidParts.append(GU.solid_GU(s)) else: fuzzy = False - if kind == 'Plane3Pts' : - P3P = True + if kind == "Plane3Pts": + P3P = True else: - P3P = False - solidParts = [GU.solid_GU(solid,P3P)] + P3P = False + solidParts = [GU.solid_GU(solid, P3P)] - ex = FreeCAD.Vector(1,0,0) - ey = FreeCAD.Vector(0,1,0) - ez = FreeCAD.Vector(0,0,1) - Surfaces=UF.Surfaces_dict() + ex = FreeCAD.Vector(1, 0, 0) + ey = FreeCAD.Vector(0, 1, 0) + ez = FreeCAD.Vector(0, 0, 1) + Surfaces = UF.Surfaces_dict() for solid_GU in solidParts: - flag_inv = CD.isInverted(solid_GU.solid) - - # Get the parameter of all faces of the solid - # Add auxillary planes for Cylinders and Cones - for face in solid_GU.Faces: - surf = str(face.Surface) - if surf == '' and kind in ['Planes','All'] : - normal = face.Surface.Axis - pos=face.CenterOfMass - dim1 = face.ParameterRange[1]-face.ParameterRange[0] - dim2 = face.ParameterRange[3]-face.ParameterRange[2] - plane = UF.GEOUNED_Surface(('Plane',(pos,normal,dim1,dim2)),UniverseBox) - if MakeObj : plane.buildSurface() - Surfaces.addPlane(plane,fuzzy) - - elif surf == '' : - dir = face.Surface.Axis - orig = face.Surface.Center - rad = face.Surface.Radius - dimL = face.ParameterRange[3]-face.ParameterRange[2] - if kind in ['Cyl','All'] : - cylinder = UF.GEOUNED_Surface(('Cylinder',(orig,dir,rad,dimL)),UniverseBox) - if MakeObj : cylinder.buildSurface() - Surfaces.addCylinder(cylinder,fuzzy) - - if kind in ['Planes','All'] : - #add planes if cylinder axis is cut by a plane (plane quasi perpedicular to axis) - for p in CylBoundPlanes(face,UniverseBox) : - if MakeObj : p.buildSurface() - Surfaces.addPlane(p) - - elif ( surf == '') : - dir = face.Surface.Axis - apex = face.Surface.Apex - halfAngle = face.Surface.SemiAngle - dimL = face.ParameterRange[3]-face.ParameterRange[2] - dimR = face.Surface.Radius - if kind in ['Cone','All'] : - cone = UF.GEOUNED_Surface(('Cone',(apex,dir,halfAngle,dimL,dimR)),UniverseBox) - if MakeObj : cone.buildSurface() - Surfaces.addCone(cone) - - if kind in ['Planes','All'] : - for p in CylBoundPlanes(face,UniverseBox) : - if MakeObj : p.buildSurface() - Surfaces.addPlane(p) - - elif surf[0:6] == 'Sphere' and kind in ['Sph','All']: - rad = face.Surface.Radius - pnt = face.Surface.Center - sphere = UF.GEOUNED_Surface(('Sphere',(pnt,rad)),UniverseBox) - if MakeObj : sphere.buildSurface() - Surfaces.addSphere(sphere) - - if kind in ['Planes','All'] : - for p in CylBoundPlanes(face,UniverseBox) : - if MakeObj : p.buildSurface() - Surfaces.addPlane(p) - - elif (surf == ''): - if kind in ['Tor','All']: - radMaj = face.Surface.MajorRadius - radMin = face.Surface.MinorRadius - center = face.Surface.Center - dir = face.Surface.Axis - torus = UF.GEOUNED_Surface(('Torus',(center,dir,radMaj,radMin)),UniverseBox) - if MakeObj : torus.buildSurface() - Surfaces.addTorus(torus) - - if kind in ['Planes','All'] : - for p in TorusBoundPlanes(face,UniverseBox) : - if MakeObj : p.buildSurface() - Surfaces.addPlane(p) - - elif surf == '' and kind == 'Plane3Pts' : - pos=face.CenterOfMass - normal = face.Surface.Axis - dim1 = face.ParameterRange[1]-face.ParameterRange[0] - dim2 = face.ParameterRange[3]-face.ParameterRange[2] - points = tuple(v.Point for v in face.Vertexes) - - plane = UF.GEOUNED_Surface(('Plane3Pts',(pos,normal,dim1,dim2,points)),UniverseBox) - if MakeObj : plane.buildSurface() - Surfaces.addPlane(plane,fuzzy) - - return Surfaces - - -def isAlreadyInPlanes(plane,Array): + flag_inv = CD.isInverted(solid_GU.solid) + + # Get the parameter of all faces of the solid + # Add auxillary planes for Cylinders and Cones + for face in solid_GU.Faces: + surf = str(face.Surface) + if surf == "" and kind in ["Planes", "All"]: + normal = face.Surface.Axis + pos = face.CenterOfMass + dim1 = face.ParameterRange[1] - face.ParameterRange[0] + dim2 = face.ParameterRange[3] - face.ParameterRange[2] + plane = UF.GEOUNED_Surface( + ("Plane", (pos, normal, dim1, dim2)), UniverseBox + ) + if MakeObj: + plane.buildSurface() + Surfaces.addPlane(plane, fuzzy) + + elif surf == "": + dir = face.Surface.Axis + orig = face.Surface.Center + rad = face.Surface.Radius + dimL = face.ParameterRange[3] - face.ParameterRange[2] + if kind in ["Cyl", "All"]: + cylinder = UF.GEOUNED_Surface( + ("Cylinder", (orig, dir, rad, dimL)), UniverseBox + ) + if MakeObj: + cylinder.buildSurface() + Surfaces.addCylinder(cylinder, fuzzy) + + if kind in ["Planes", "All"]: + # add planes if cylinder axis is cut by a plane (plane quasi perpedicular to axis) + for p in CylBoundPlanes(face, UniverseBox): + if MakeObj: + p.buildSurface() + Surfaces.addPlane(p) + + elif surf == "": + dir = face.Surface.Axis + apex = face.Surface.Apex + halfAngle = face.Surface.SemiAngle + dimL = face.ParameterRange[3] - face.ParameterRange[2] + dimR = face.Surface.Radius + if kind in ["Cone", "All"]: + cone = UF.GEOUNED_Surface( + ("Cone", (apex, dir, halfAngle, dimL, dimR)), UniverseBox + ) + if MakeObj: + cone.buildSurface() + Surfaces.addCone(cone) + + if kind in ["Planes", "All"]: + for p in CylBoundPlanes(face, UniverseBox): + if MakeObj: + p.buildSurface() + Surfaces.addPlane(p) + + elif surf[0:6] == "Sphere" and kind in ["Sph", "All"]: + rad = face.Surface.Radius + pnt = face.Surface.Center + sphere = UF.GEOUNED_Surface(("Sphere", (pnt, rad)), UniverseBox) + if MakeObj: + sphere.buildSurface() + Surfaces.addSphere(sphere) + + if kind in ["Planes", "All"]: + for p in CylBoundPlanes(face, UniverseBox): + if MakeObj: + p.buildSurface() + Surfaces.addPlane(p) + + elif surf == "": + if kind in ["Tor", "All"]: + radMaj = face.Surface.MajorRadius + radMin = face.Surface.MinorRadius + center = face.Surface.Center + dir = face.Surface.Axis + torus = UF.GEOUNED_Surface( + ("Torus", (center, dir, radMaj, radMin)), UniverseBox + ) + if MakeObj: + torus.buildSurface() + Surfaces.addTorus(torus) + + if kind in ["Planes", "All"]: + for p in TorusBoundPlanes(face, UniverseBox): + if MakeObj: + p.buildSurface() + Surfaces.addPlane(p) + + elif surf == "" and kind == "Plane3Pts": + pos = face.CenterOfMass + normal = face.Surface.Axis + dim1 = face.ParameterRange[1] - face.ParameterRange[0] + dim2 = face.ParameterRange[3] - face.ParameterRange[2] + points = tuple(v.Point for v in face.Vertexes) + + plane = UF.GEOUNED_Surface( + ("Plane3Pts", (pos, normal, dim1, dim2, points)), UniverseBox + ) + if MakeObj: + plane.buildSurface() + Surfaces.addPlane(plane, fuzzy) + + return Surfaces + + +def isAlreadyInPlanes(plane, Array): for elem in Array: - if (plane.Surface.Axis.cross(elem.Surface.Axis)==FreeCAD.Vector(0,0,0) and isInPlane(plane.Surface.Position,elem.Surface)): + if plane.Surface.Axis.cross(elem.Surface.Axis) == FreeCAD.Vector( + 0, 0, 0 + ) and isInPlane(plane.Surface.Position, elem.Surface): return True - + return False - + + # # # Check if to faces are joint -# -def ContiguousFace(face1,face2): +# +def ContiguousFace(face1, face2): return face1.distToShape(face2)[0] < tol.distance - + + def SameFaces(Faces): - Connection=OrderedDict() - if len(Faces)==1: + Connection = OrderedDict() + if len(Faces) == 1: return [] - + for i, face1 in enumerate(Faces): - Couples=[] - if not Faces[i+1:]: + Couples = [] + if not Faces[i + 1 :]: continue - for j, face2 in enumerate(Faces[i+1:]): - if ContiguousFace(face1,face2): - - Couples.append(i+1+j) - - Connection[i]=Couples - - lista=Connection[0] + for j, face2 in enumerate(Faces[i + 1 :]): + if ContiguousFace(face1, face2): + + Couples.append(i + 1 + j) + + Connection[i] = Couples + + lista = Connection[0] Connection.popitem(0) - - if len(Connection)==0: # solo los elementos de la lista de la superficie 0 + + if len(Connection) == 0: # solo los elementos de la lista de la superficie 0 return lista - - if not lista: # ninguna face está conecta conecta con la superficie 0 + + if not lista: # ninguna face está conecta conecta con la superficie 0 return lista - + for elem in Connection: - if elem in lista: # que la key esta en lista implica que sus dependencias estan + if elem in lista: # que la key esta en lista implica que sus dependencias estan lista.extend(Connection[elem]) else: for elem2 in Connection[elem]: - if elem2 in lista: # si una de sus dependencias esta en lista lo esta la clave + if ( + elem2 in lista + ): # si una de sus dependencias esta en lista lo esta la clave lista.append(elem) return list(set(lista)) - + + # Tolerance in this function are not the general once # function should be reviewed -def GenPlaneCylinder(face,solid): - Surf=face.Surface - rad=Surf.Radius +def GenPlaneCylinder(face, solid): + Surf = face.Surface + rad = Surf.Radius if face.Area < 1e-2: return None - - UVNodes=[] - face_index_0=[solid.Faces.index(face)] + + UVNodes = [] + face_index_0 = [solid.Faces.index(face)] try: face.tessellate(0.1) UVNodes.append(face.getUVNodes()) except RuntimeError: - PR=face.ParameterRange - UVNode1=(PR[0],PR[2]) - UVNode2=(PR[1],PR[3]) - UVNodes.append([UVNode1,UVNode2]) - - + PR = face.ParameterRange + UVNode1 = (PR[0], PR[2]) + UVNode2 = (PR[1], PR[3]) + UVNodes.append([UVNode1, UVNode2]) + for i, face2 in enumerate(solid.Faces): - - if str(face2.Surface) == '' and not(face2.isEqual(face)): - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Radius == rad and isInLine(face2.Surface.Center,face.Surface.Axis,face.Surface.Center)): + + if str(face2.Surface) == "" and not (face2.isEqual(face)): + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Radius == rad + and isInLine( + face2.Surface.Center, face.Surface.Axis, face.Surface.Center + ) + ): face_index_0.append(i) - + # prueba SameFaces, parece ok - Faces_p=[] + Faces_p = [] for ind in face_index_0: Faces_p.append(solid.Faces[ind]) - - face_index=[face_index_0[0]] # la face de entrada + + face_index = [face_index_0[0]] # la face de entrada for k in SameFaces(Faces_p): face_index.append(face_index_0[k]) - - # commented to let plane cut rounded corner + + # commented to let plane cut rounded corner # if len(face_index_0)==len(face_index): #Esto evita un corte creo!!! no debería ser así en conversion # return None - + for ind in reversed(face_index[1:]): - if solid.Faces[ind].Area<=1e-3: + if solid.Faces[ind].Area <= 1e-3: face_index.remove(ind) else: @@ -413,123 +456,130 @@ def GenPlaneCylinder(face,solid): face2.tessellate(0.1) UVNodes.append(face2.getUVNodes()) except RuntimeError: - PR=face2.ParameterRange - UVNode1=(PR[0],PR[2]) - UVNode2=(PR[1],PR[3]) - UVNodes.append([UVNode1,UVNode2]) - - AngleRange=0.0 - - Uval=[] + PR = face2.ParameterRange + UVNode1 = (PR[0], PR[2]) + UVNode2 = (PR[1], PR[3]) + UVNodes.append([UVNode1, UVNode2]) + + AngleRange = 0.0 + + Uval = [] for index in face_index: - Range=solid.Faces[index].ParameterRange - AngleRange=AngleRange+abs(Range[1]-Range[0]) - #if not(Range[0] in Uval) and not(Range[1] in Uval): + Range = solid.Faces[index].ParameterRange + AngleRange = AngleRange + abs(Range[1] - Range[0]) + # if not(Range[0] in Uval) and not(Range[1] in Uval): Uval.append(Range[0]) Uval.append(Range[1]) - - if (twoPi-AngleRange < 1.e-2 or AngleRange < 1.e-2): + + if twoPi - AngleRange < 1.0e-2 or AngleRange < 1.0e-2: return None - - Uval_str_cl=[] - - for i,elem1 in enumerate(Uval): - num_str1='%11.4E' %elem1 - if abs(elem1)<1.0e-5: - num_str1='%11.4E' %0.0 - - if not(isDuplicateInList(num_str1,i,Uval)): + + Uval_str_cl = [] + + for i, elem1 in enumerate(Uval): + num_str1 = "%11.4E" % elem1 + if abs(elem1) < 1.0e-5: + num_str1 = "%11.4E" % 0.0 + + if not (isDuplicateInList(num_str1, i, Uval)): Uval_str_cl.append(num_str1) - + if len(Uval_str_cl) < 2: - if opt.verbose : print ('GenPlaneCylinder : Uval_str_cl should no be void ') + if opt.verbose: + print("GenPlaneCylinder : Uval_str_cl should no be void ") return None - face_index_2=[face_index[0],face_index[0]] - - Node_min=UVNodes[0][0] - Node_max=UVNodes[0][1] - - dif1_0=abs(float(Uval_str_cl[0])-Node_min[0]) - dif2_0=abs(float(Uval_str_cl[1])-Node_max[0]) - + face_index_2 = [face_index[0], face_index[0]] + + Node_min = UVNodes[0][0] + Node_max = UVNodes[0][1] + + dif1_0 = abs(float(Uval_str_cl[0]) - Node_min[0]) + dif2_0 = abs(float(Uval_str_cl[1]) - Node_max[0]) + # searching for minimum and maximum angle points - - for j,Nodes in enumerate(UVNodes): + + for j, Nodes in enumerate(UVNodes): for elem in Nodes: - val='%11.4E' %elem[0] - dif1=abs(float(Uval_str_cl[0])-elem[0]) - dif2=abs(float(Uval_str_cl[1])-elem[0]) - - if abs(elem[0])<1.0e-5: - val='%11.4E' %0.0 - if (dif1' and not(face2.isEqual(face)): - - if (face2.Surface.Axis.isEqual(face.Surface.Axis,1e-5) and face2.Surface.Apex.isEqual(face.Surface.Apex,1e-5) and (face2.Surface.SemiAngle-face.Surface.SemiAngle) < 1e-6): + + if str(face2.Surface) == "" and not (face2.isEqual(face)): + + if ( + face2.Surface.Axis.isEqual(face.Surface.Axis, 1e-5) + and face2.Surface.Apex.isEqual(face.Surface.Apex, 1e-5) + and (face2.Surface.SemiAngle - face.Surface.SemiAngle) < 1e-6 + ): face_index_0.append(i) - - Faces_p=[] + + Faces_p = [] for ind in face_index_0: Faces_p.append(solid.Faces[ind]) - - face_index=[face_index_0[0]] # la face de entrada - + + face_index = [face_index_0[0]] # la face de entrada + for k in SameFaces(Faces_p): face_index.append(face_index_0[k]) - - # same as cylinder commennt - #if len(face_index_0)==len(face_index): + + # same as cylinder commennt + # if len(face_index_0)==len(face_index): # return None - + for ind in reversed(face_index[1:]): - if solid.Faces[ind].Area<=1e-3: + if solid.Faces[ind].Area <= 1e-3: face_index.remove(ind) else: face2 = solid.Faces[ind] @@ -537,355 +587,385 @@ def GenPlaneCone(face,solid): face2.tessellate(0.1) UVNodes.append(face2.getUVNodes()) except RuntimeError: - PR=face2.ParameterRange - UVNode1=(PR[0],PR[2]) - UVNode2=(PR[1],PR[3]) - UVNodes.append([UVNode1,UVNode2]) - - AngleRange=0.0 - - Uval=[] - + PR = face2.ParameterRange + UVNode1 = (PR[0], PR[2]) + UVNode2 = (PR[1], PR[3]) + UVNodes.append([UVNode1, UVNode2]) + + AngleRange = 0.0 + + Uval = [] + for index in face_index: - Range=solid.Faces[index].ParameterRange - AngleRange=AngleRange+abs(Range[1]-Range[0]) + Range = solid.Faces[index].ParameterRange + AngleRange = AngleRange + abs(Range[1] - Range[0]) Uval.append(Range[0]) Uval.append(Range[1]) - if (twoPi-AngleRange < 1.e-2 or AngleRange<1e-2): + if twoPi - AngleRange < 1.0e-2 or AngleRange < 1e-2: return None - - Uval_str_cl=[] - - for i,elem1 in enumerate(Uval): - num_str1='%11.4E' %elem1 - if abs(elem1)<1.0e-5: - num_str1='%11.4E' %0.0 - if not(isDuplicateInList(num_str1,i,Uval)): + + Uval_str_cl = [] + + for i, elem1 in enumerate(Uval): + num_str1 = "%11.4E" % elem1 + if abs(elem1) < 1.0e-5: + num_str1 = "%11.4E" % 0.0 + if not (isDuplicateInList(num_str1, i, Uval)): Uval_str_cl.append(num_str1) - + if len(Uval_str_cl) < 2: - if opt.verbose : print ('GenPlaneCone : Uval_str_cl should no be void ') + if opt.verbose: + print("GenPlaneCone : Uval_str_cl should no be void ") return None - face_index_2=[face_index[0],face_index[0]] - - Node_min=UVNodes[0][0] - Node_max=UVNodes[0][1] - dif1_0=abs(float(Uval_str_cl[0])-Node_min[0]) - dif2_0=abs(float(Uval_str_cl[1])-Node_max[0]) - + face_index_2 = [face_index[0], face_index[0]] + + Node_min = UVNodes[0][0] + Node_max = UVNodes[0][1] + dif1_0 = abs(float(Uval_str_cl[0]) - Node_min[0]) + dif2_0 = abs(float(Uval_str_cl[1]) - Node_max[0]) + # searching for minimum and maximum angle points - for j,Nodes in enumerate(UVNodes): + for j, Nodes in enumerate(UVNodes): for elem in Nodes: - val='%11.4E' %elem[0] - dif1=abs(float(Uval_str_cl[0])-elem[0]) - dif2=abs(float(Uval_str_cl[1])-elem[0]) - - if abs(elem[0])<1.0e-5: - val='%11.4E' %0.0 - if (dif1': - pp = GenPlaneCylinder(face,solid_GU) - elif str(face.Surface) == '': - pp = GenPlaneCone(face,solid_GU) - if pp is not None : - planes.append(pp) - #elif str(face.Surface)[0:6] == 'Sphere': - # return GenPlaneSphere(face,solid_GU) + if face is None: + for face in solid_GU.Faces: + if flag_inv: + orient_temp = face.Orientation + if orient_temp == "Forward": + orient = "Reversed" + elif orient_temp == "Reversed": + orient = "Forward" + else: + orient = face.Orientation + + if convex and orient == "Reversed": # convex face condition + pp = None + if str(face.Surface) == "": + pp = GenPlaneCylinder(face, solid_GU) + elif str(face.Surface) == "": + pp = GenPlaneCone(face, solid_GU) + if pp is not None: + planes.append(pp) + # elif str(face.Surface)[0:6] == 'Sphere': + # return GenPlaneSphere(face,solid_GU) else: - if (flag_inv): - orient_temp=face.Orientation - if orient_temp=='Forward': - orient='Reversed' - elif orient_temp=='Reversed': - orient='Forward' - else: - orient=face.Orientation - - if not convex and orient=='Forward': - if str(face.Surface) == '': - pp = GenPlaneCylinder(face,solid_GU) - elif str(face.Surface) == '': - pp = GenPlaneCone(face,solid_GU) - if pp is not None : - planes.append(pp) + if flag_inv: + orient_temp = face.Orientation + if orient_temp == "Forward": + orient = "Reversed" + elif orient_temp == "Reversed": + orient = "Forward" + else: + orient = face.Orientation + + if not convex and orient == "Forward": + if str(face.Surface) == "": + pp = GenPlaneCylinder(face, solid_GU) + elif str(face.Surface) == "": + pp = GenPlaneCone(face, solid_GU) + if pp is not None: + planes.append(pp) return planes -def SplitPlanes(Solids,UniverseBox,newVersion=True): - if newVersion : - return SplitPlanes_new(Solids,UniverseBox) + +def SplitPlanes(Solids, UniverseBox, newVersion=True): + if newVersion: + return SplitPlanes_new(Solids, UniverseBox) else: - return SplitPlanes_org(Solids,UniverseBox) + return SplitPlanes_org(Solids, UniverseBox) + -def SplitPlanes_new(Solids,UniverseBox): +def SplitPlanes_new(Solids, UniverseBox): Bases = Solids[:] simpleSolid = [] # Cut with real planes defining solid faces - while True: - newBases = [] - for base in Bases: - cutSolids = splitPPlanes_new(base,UniverseBox) - if len(cutSolids) == 1: - simpleSolid.extend(cutSolids) - else: - newBases.extend(cutSolids) - if len(newBases) == 0 : - break - else: - Bases = newBases - - return simpleSolid,0 - - -def SplitPlanes_org(Solids,UniverseBox): + while True: + newBases = [] + for base in Bases: + cutSolids = splitPPlanes_new(base, UniverseBox) + if len(cutSolids) == 1: + simpleSolid.extend(cutSolids) + else: + newBases.extend(cutSolids) + if len(newBases) == 0: + break + else: + Bases = newBases + + return simpleSolid, 0 + + +def SplitPlanes_org(Solids, UniverseBox): Bases = [] - icount=0 - err =0 - for sol in Solids : - Bases.append((sol,[])) - -# Loop 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 -# order x y z x z y y x z y z x z x y z y x -# index 0 0 0 0 1 0 1 0 0 1 1 0 2 0 0 2 1 0 + icount = 0 + err = 0 + for sol in Solids: + Bases.append((sol, [])) + + # Loop 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 + # order x y z x z y y x z y z x z x y z y x + # index 0 0 0 0 1 0 1 0 0 1 1 0 2 0 0 2 1 0 # planes orthogonal to X,Y,Z axis - for iplane in range(3) : - newBase =[] - for item in Bases : - - base = item[0] - index = item[1] - SPlanes = ExtractSurfaces(base,'Planes',UniverseBox,MakeObj=True) - Planes = [SPlanes['PX'],SPlanes['PY'],SPlanes['PZ']] - for i in index : - del(Planes[i]) - pmin = len(Planes[0]) - imin = 0 - for i in range(2-iplane): - if pmin > len(Planes[i+1]) : - pmin = len(Planes[i+1]) - imin = i+1 - - if len(Planes[imin]) != 0: - Tools = [] - for p in Planes[imin] : - p.buildSurface() - Tools.append(p.shape) - comsolid = UF.splitBOP(base,Tools,opt.splitTolerance) - if len(comsolid.Solids) == 1 : - if abs(comsolid.Solids[0].Volume-base.Volume)/base.Volume > tol.relativePrecision : - if opt.verbose : print('Warning. Part of the split object is missing original base is used instead',\ - abs(comsolid.Solids[0].Volume-base.Volume)/base.Volume,comsolid.Solids[0].Volume,base.Volume) - base.exportStep('tmp_base.stp') - s = Part.Shape() - s.read('tmp_base.stp') - solid_list = s.Solids - err=1 - else: - solid_list = comsolid.Solids - elif len(comsolid.Solids)> 1 : - solid_list = comsolid.Solids + for iplane in range(3): + newBase = [] + for item in Bases: + + base = item[0] + index = item[1] + SPlanes = ExtractSurfaces(base, "Planes", UniverseBox, MakeObj=True) + Planes = [SPlanes["PX"], SPlanes["PY"], SPlanes["PZ"]] + for i in index: + del Planes[i] + pmin = len(Planes[0]) + imin = 0 + for i in range(2 - iplane): + if pmin > len(Planes[i + 1]): + pmin = len(Planes[i + 1]) + imin = i + 1 + + if len(Planes[imin]) != 0: + Tools = [] + for p in Planes[imin]: + p.buildSurface() + Tools.append(p.shape) + comsolid = UF.splitBOP(base, Tools, opt.splitTolerance) + if len(comsolid.Solids) == 1: + if ( + abs(comsolid.Solids[0].Volume - base.Volume) / base.Volume + > tol.relativePrecision + ): + if opt.verbose: + print( + "Warning. Part of the split object is missing original base is used instead", + abs(comsolid.Solids[0].Volume - base.Volume) + / base.Volume, + comsolid.Solids[0].Volume, + base.Volume, + ) + base.exportStep("tmp_base.stp") + s = Part.Shape() + s.read("tmp_base.stp") + solid_list = s.Solids + err = 1 + else: + solid_list = comsolid.Solids + elif len(comsolid.Solids) > 1: + solid_list = comsolid.Solids + else: + solid_list = [base] else: - solid_list = [base] - else : - solid_list = [base] + solid_list = [base] - newindex = index[:] - newindex.append(imin) - for sol in solid_list: - newBase.append((sol,newindex)) - Bases = newBase + newindex = index[:] + newindex.append(imin) + for sol in solid_list: + newBase.append((sol, newindex)) + Bases = newBase XYZBases = [] - for ii,s in enumerate(Bases): - XYZBases.append(s[0]) + for ii, s in enumerate(Bases): + XYZBases.append(s[0]) simpleSolid = [] Bases = XYZBases # other planes - while True: - newBases = [] - for base in Bases: - cutSolids = splitPPlanes_org(base,UniverseBox) - if len(cutSolids) == 1: - simpleSolid.extend(cutSolids) - else: - newBases.extend(cutSolids) - if len(newBases) == 0 : - break - else: - Bases = newBases - return simpleSolid,err + while True: + newBases = [] + for base in Bases: + cutSolids = splitPPlanes_org(base, UniverseBox) + if len(cutSolids) == 1: + simpleSolid.extend(cutSolids) + else: + newBases.extend(cutSolids) + if len(newBases) == 0: + break + else: + Bases = newBases + return simpleSolid, err class parallelPlanes: - def __init__(self,plane): - self.Axis = plane.Surf.Axis - self.elements = [plane] - self.count = 1 - - def append(self,plane): - if isParallel(plane.Surf.Axis,self.Axis,0.1): - self.elements.append(plane) - self.count += 1 - return True - else: - return False + def __init__(self, plane): + self.Axis = plane.Surf.Axis + self.elements = [plane] + self.count = 1 + + def append(self, plane): + if isParallel(plane.Surf.Axis, self.Axis, 0.1): + self.elements.append(plane) + self.count += 1 + return True + else: + return False def sort(self): - pos=[] - for i,p in enumerate(self.elements): - d = self.Axis.dot(p.Surf.Position) - pos.append((d,i)) - pos.sort() - - sort = [] - for p in pos: - sort.append(self.elements[p[1]]) - self.elements = sort - - -def sortPlanes(PlaneList,sortElements=False): - if not PlaneList : return [] + pos = [] + for i, p in enumerate(self.elements): + d = self.Axis.dot(p.Surf.Position) + pos.append((d, i)) + pos.sort() + + sort = [] + for p in pos: + sort.append(self.elements[p[1]]) + self.elements = sort + + +def sortPlanes(PlaneList, sortElements=False): + if not PlaneList: + return [] newList = [parallelPlanes(PlaneList[0])] for p in PlaneList[1:]: - found = False - for pp in newList: - if pp.append(p) : - found = True - break - if not found : - newList.append(parallelPlanes(p)) + found = False + for pp in newList: + if pp.append(p): + found = True + break + if not found: + newList.append(parallelPlanes(p)) lenList = [] - for i,pp in enumerate(newList): - if sortElements : pp.sort() - lenList.append((pp.count,i)) + for i, pp in enumerate(newList): + if sortElements: + pp.sort() + lenList.append((pp.count, i)) lenList.sort() - sortedPlanes=[] + sortedPlanes = [] for l in lenList: - sortedPlanes.append(newList[l[1]].elements) - + sortedPlanes.append(newList[l[1]].elements) + return sortedPlanes - -def splitPPlanes_new(solid,UniverseBox): - SPlanes = ExtractSurfaces(solid,'Planes',UniverseBox) - - Planes = [] - for P in ('PX','PY','PZ','P'): - Planes.extend(SPlanes[P]) + + +def splitPPlanes_new(solid, UniverseBox): + SPlanes = ExtractSurfaces(solid, "Planes", UniverseBox) + + Planes = [] + for P in ("PX", "PY", "PZ", "P"): + Planes.extend(SPlanes[P]) Planes = sortPlanes(Planes) - - if len(Planes) == 0 : return [solid] - if len(Planes[-1]) < opt.nPlaneReverse : Planes.reverse() + + if len(Planes) == 0: + return [solid] + if len(Planes[-1]) < opt.nPlaneReverse: + Planes.reverse() outSolid = [solid] - for pp in Planes : - for p in pp : p.buildSurface() - tools = tuple( p.shape for p in pp) - comsolid = UF.splitBOP(solid,tools,opt.splitTolerance) - - if len(comsolid.Solids) > 1 : - outSolid = comsolid.Solids - break - return outSolid - -def splitPPlanes_org(solid,UniverseBox): - SPlanes = ExtractSurfaces(solid,'Planes',UniverseBox) - - if len(SPlanes['P']) == 0 : return [solid] + for pp in Planes: + for p in pp: + p.buildSurface() + tools = tuple(p.shape for p in pp) + comsolid = UF.splitBOP(solid, tools, opt.splitTolerance) + + if len(comsolid.Solids) > 1: + outSolid = comsolid.Solids + break + return outSolid + + +def splitPPlanes_org(solid, UniverseBox): + SPlanes = ExtractSurfaces(solid, "Planes", UniverseBox) + + if len(SPlanes["P"]) == 0: + return [solid] outSolid = [solid] - for p in SPlanes['P'] : - p.buildSurface() - comsolid = UF.splitBOP(solid,[p.shape],opt.splitTolerance) - if len(comsolid.Solids) > 1 : - outSolid = comsolid.Solids - break - return outSolid - -def Split2ndOrder(Solids,UniverseBox): + for p in SPlanes["P"]: + p.buildSurface() + comsolid = UF.splitBOP(solid, [p.shape], opt.splitTolerance) + if len(comsolid.Solids) > 1: + outSolid = comsolid.Solids + break + return outSolid + + +def Split2ndOrder(Solids, UniverseBox): err = 0 Base = Solids - for kind in ['Cyl','Cone','Sph','Tor'] : - kindBase = [] - while True : - cutBase=[] - for solid in Base : - Surfaces = ExtractSurfaces(solid,kind,UniverseBox) - if len(Surfaces[kind]) == 0 : - kindBase.append(solid) - else: - simple = True - for s in Surfaces[kind]: - s.buildSurface() - try : - comsolid = UF.splitBOP(solid,[s.shape],opt.splitTolerance) - solidsInCom = [] - for s in comsolid.Solids : - if s.Volume > 1e-9 : solidsInCom.append(s) - - if len(solidsInCom) > 1 : - simple =False - cutBase.extend(solidsInCom) - break - except : - if opt.verbose : print('Failed split base with {} surface'.format(s.shape.Faces[0].Surface)) - err += 2 - - if simple : - kindBase.append(solid) - - if len(cutBase) == 0 : - Base = kindBase - break - else: - Base = cutBase + for kind in ["Cyl", "Cone", "Sph", "Tor"]: + kindBase = [] + while True: + cutBase = [] + for solid in Base: + Surfaces = ExtractSurfaces(solid, kind, UniverseBox) + if len(Surfaces[kind]) == 0: + kindBase.append(solid) + else: + simple = True + for s in Surfaces[kind]: + s.buildSurface() + try: + comsolid = UF.splitBOP(solid, [s.shape], opt.splitTolerance) + solidsInCom = [] + for s in comsolid.Solids: + if s.Volume > 1e-9: + solidsInCom.append(s) + + if len(solidsInCom) > 1: + simple = False + cutBase.extend(solidsInCom) + break + except: + if opt.verbose: + print( + "Failed split base with {} surface".format( + s.shape.Faces[0].Surface + ) + ) + err += 2 + + if simple: + kindBase.append(solid) + + if len(cutBase) == 0: + Base = kindBase + break + else: + Base = cutBase + + return Base, err + - return Base,err - def Split2ndOrderPlanes(Solids): err = 0 simpleSolid = [] @@ -893,97 +973,110 @@ def Split2ndOrderPlanes(Solids): while True: newBases = [] for base in Bases: - cutSolids,err = split2ndOPlane(base) + cutSolids, err = split2ndOPlane(base) if len(cutSolids) == 1: simpleSolid.extend(cutSolids) else: newBases.extend(cutSolids) - if len(newBases) == 0 : + if len(newBases) == 0: break else: Bases = newBases - - return simpleSolid,err - + + return simpleSolid, err + + def split2ndOPlane(solid): - Planes=[] + Planes = [] err = 0 - flag_inv=CD.isInverted(solid) - solid_GU=GU.solid_GU(solid) - planes = Plane2ndOrder(solid_GU,None,flag_inv,convex=True) - if not planes : return [solid],err + flag_inv = CD.isInverted(solid) + solid_GU = GU.solid_GU(solid) + planes = Plane2ndOrder(solid_GU, None, flag_inv, convex=True) + if not planes: + return [solid], err for p in planes: - comsolid = UF.splitBOP(solid,[p],opt.splitTolerance) - if not comsolid.Solids: - comsolid=solid - continue - if len(comsolid.Solids) > 1 : - removed, err = removeSolids(comsolid.Solids) - comsolid=Part.makeCompound(removed) - if len(removed) > 1: break - - return comsolid.Solids,err - + comsolid = UF.splitBOP(solid, [p], opt.splitTolerance) + if not comsolid.Solids: + comsolid = solid + continue + if len(comsolid.Solids) > 1: + removed, err = removeSolids(comsolid.Solids) + comsolid = Part.makeCompound(removed) + if len(removed) > 1: + break + + return comsolid.Solids, err + + def removeSolids(Solids): err = 0 - Vol_tol=1e-2 - Solids_Clean=[] + Vol_tol = 1e-2 + Solids_Clean = [] for solid in Solids: if solid.Volume <= Vol_tol: - if opt.verbose : print('Warning: removeSolids degenerated solids are produced',solid.Volume) - err=2 + if opt.verbose: + print( + "Warning: removeSolids degenerated solids are produced", + solid.Volume, + ) + err = 2 continue Solids_Clean.append(solid) - - return Solids_Clean,err - -def splitComponent(solidShape,UniverseBox): - err = 0 + + return Solids_Clean, err + + +def splitComponent(solidShape, UniverseBox): + err = 0 err2 = 0 - Volini=solidShape.Volume - Solids=solidShape.Solids + Volini = solidShape.Volume + Solids = solidShape.Solids # Split with explicit planes bounding the solid and # implicit planes interface of two 2nd order surfaces - split0,err = SplitPlanes(Solids,UniverseBox,opt.newSplitPlane) + split0, err = SplitPlanes(Solids, UniverseBox, opt.newSplitPlane) # Split with explicit 2nd order surfaces bounding the solid - - split1,err1 = Split2ndOrder(split0,UniverseBox) + + split1, err1 = Split2ndOrder(split0, UniverseBox) err += err1 - split,err2 = Split2ndOrderPlanes(split1) + split, err2 = Split2ndOrderPlanes(split1) err += err2 Pieces = [] for part in split: - if part.Volume <= 1e-10: - if opt.verbose : print('Warning: splitComponent degenerated solids are produced',part.Volume) - err += 2 - continue - Pieces.append(part) - - comsolid=Part.makeCompound(Pieces) - - Volend=comsolid.Volume - Volch=(Volini-Volend)/Volini - - if (abs(Volch)>1e-2): # 1% of Volume change - if opt.verbose : print('Warning: Volume has changed after decomposition: %11.4E' %Volch) + if part.Volume <= 1e-10: + if opt.verbose: + print( + "Warning: splitComponent degenerated solids are produced", + part.Volume, + ) + err += 2 + continue + Pieces.append(part) + + comsolid = Part.makeCompound(Pieces) + + Volend = comsolid.Volume + Volch = (Volini - Volend) / Volini + + if abs(Volch) > 1e-2: # 1% of Volume change + if opt.verbose: + print("Warning: Volume has changed after decomposition: %11.4E" % Volch) err += 4 return comsolid, err - -def SplitSolid(solidShape,UniverseBox): + + +def SplitSolid(solidShape, UniverseBox): solidParts = [] - for solid in solidShape.Solids : - - explode = splitFullCylinder(solid) - piece, err = splitComponent(explode,UniverseBox) - solidParts.append(piece) - - - return Part.makeCompound(solidParts) ,err - + for solid in solidShape.Solids: + + explode = splitFullCylinder(solid) + piece, err = splitComponent(explode, UniverseBox) + solidParts.append(piece) + + return Part.makeCompound(solidParts), err diff --git a/src/geouned/GEOUNED/LoadFile/LoadFunctions.py b/src/geouned/GEOUNED/LoadFile/LoadFunctions.py index 45c942b5..3aac03ac 100644 --- a/src/geouned/GEOUNED/LoadFile/LoadFunctions.py +++ b/src/geouned/GEOUNED/LoadFile/LoadFunctions.py @@ -7,86 +7,94 @@ def GetLabel(label): - """ Deleting the last word of the string if this is a number - Only if the option delLastNumber is True""" - if not opt.delLastNumber: return label + """Deleting the last word of the string if this is a number + Only if the option delLastNumber is True""" + if not opt.delLastNumber: + return label wrd = label.split() try: - val=float(wrd[-1]) - new_label = ' '.join(wrd[:-1]) + val = float(wrd[-1]) + new_label = " ".join(wrd[:-1]) return new_label - except: return label + except: + return label + def getCommentTree(obj): recursiveList = [] cObj = obj - while cObj.InList : - label = GetLabel(cObj.InList[0].Label) - recursiveList.append( label ) - cObj = cObj.InList[0] + while cObj.InList: + label = GetLabel(cObj.InList[0].Label) + recursiveList.append(label) + cObj = cObj.InList[0] + + comment = "" + for label in reversed(recursiveList): + comment += "/" + label + return comment - comment = '' - for label in reversed(recursiveList): - comment += '/' + label - return comment def joinEnvelopes(MetaList): - joinList=[] - oldID = -1 - newlist=[] - for i,m in enumerate(MetaList): - if m.CellType != 'envelope' : continue - if m.EnclosureID != oldID: - joinList.append(newlist) - newlist = [i] - oldID = m.EnclosureID - else: - newlist.append(i) - - joinList.append(newlist) - del joinList[0] - - for IDlist in joinList: - fuseMetaObj(MetaList,IDlist[0],IDlist[-1]+1) - -def fuseMetaObj(MetaList,init,end): - if end-init == 1 : - MetaList[init].__id__ = init+1 - return - solids=[] - for m in MetaList[init:end]: - solids.extend(m.Solids) - - newMeta = GEOUNED_Solid(init+1,solids) - newMeta.EnclosureID = MetaList[init].EnclosureID - newMeta.ParentEnclosureID = MetaList[init].ParentEnclosureID - newMeta.IsEnclosure = MetaList[init].IsEnclosure - newMeta.CellType = MetaList[init].CellType - - del MetaList[init:end] - MetaList.insert(init,newMeta) - + joinList = [] + oldID = -1 + newlist = [] + for i, m in enumerate(MetaList): + if m.CellType != "envelope": + continue + if m.EnclosureID != oldID: + joinList.append(newlist) + newlist = [i] + oldID = m.EnclosureID + else: + newlist.append(i) + + joinList.append(newlist) + del joinList[0] + + for IDlist in joinList: + fuseMetaObj(MetaList, IDlist[0], IDlist[-1] + 1) + + +def fuseMetaObj(MetaList, init, end): + if end - init == 1: + MetaList[init].__id__ = init + 1 + return + solids = [] + for m in MetaList[init:end]: + solids.extend(m.Solids) + + newMeta = GEOUNED_Solid(init + 1, solids) + newMeta.EnclosureID = MetaList[init].EnclosureID + newMeta.ParentEnclosureID = MetaList[init].ParentEnclosureID + newMeta.IsEnclosure = MetaList[init].IsEnclosure + newMeta.CellType = MetaList[init].CellType + + del MetaList[init:end] + MetaList.insert(init, newMeta) + # Paco mod def checkCADFileMaterial(Material, mdict): """Function to check that if a component in the CAD file has a material, it exist in the material file""" - templist = [ elem for elem in set(Material) if elem not in mdict ] + templist = [elem for elem in set(Material) if elem not in mdict] if templist: raise ValueError( - 'At least one material in the CAD model is not present in the material file\n' - f'List of not present materials:{templist}\n' - 'Code STOPS\n' + "At least one material in the CAD model is not present in the material file\n" + f"List of not present materials:{templist}\n" + "Code STOPS\n" ) return + # Paco mod def setEnclosureSolidList(MetaList): """Function to define DataList list.""" - return [ elem for elem in MetaList if elem.IsEnclosure ] + return [elem for elem in MetaList if elem.IsEnclosure] + def RemoveEnclosure(MetaList): """This function removes Enclosure solid and actualises __id__ attributes to take into account the removal from MetaList list of nested enclosures originally loaded from CAD model.""" - + # update id of solids lenMetaList = len(MetaList) icount = 0 @@ -95,257 +103,274 @@ def RemoveEnclosure(MetaList): icount += 1 else: MetaList[i].__id__ -= icount - + # remove Enclosure solids from metaList - for i in range(lenMetaList-1,-1,-1): - if MetaList[i].IsEnclosure : + for i in range(lenMetaList - 1, -1, -1): + if MetaList[i].IsEnclosure: MetaList.pop(i) - + def setEnclosureLevels(EnclosureList): - nestedList = [[0],[]] + nestedList = [[0], []] nestedEnclosure = [[]] parentLevel = 0 tempList = EnclosureList[:] - - while len(tempList) > 0 : - remove = [] - for i,encl in enumerate(tempList): - if encl.ParentEnclosureID in nestedList[parentLevel] : - nestedList[parentLevel+1].append(encl.EnclosureID) - nestedEnclosure[parentLevel].append(encl) - remove.append(i) - - nestedList.append([]) - nestedEnclosure.append([]) - parentLevel += 1 - remove.reverse() - for i in remove: - del tempList[i] - - nestedEnclosureList = [] - for Level in nestedEnclosure : - temp=[] - for i,encl in enumerate(Level): - temp.append((encl.ParentEnclosureID,i)) - temp.sort() - - grouped = [] - for t in temp: - grouped.append(Level[t[1]]) - nestedEnclosureList.append(grouped) - - for i,Level in enumerate(nestedEnclosureList[0:-1]) : + + while len(tempList) > 0: + remove = [] + for i, encl in enumerate(tempList): + if encl.ParentEnclosureID in nestedList[parentLevel]: + nestedList[parentLevel + 1].append(encl.EnclosureID) + nestedEnclosure[parentLevel].append(encl) + remove.append(i) + + nestedList.append([]) + nestedEnclosure.append([]) + parentLevel += 1 + remove.reverse() + for i in remove: + del tempList[i] + + nestedEnclosureList = [] + for Level in nestedEnclosure: + temp = [] + for i, encl in enumerate(Level): + temp.append((encl.ParentEnclosureID, i)) + temp.sort() + + grouped = [] + for t in temp: + grouped.append(Level[t[1]]) + nestedEnclosureList.append(grouped) + + for i, Level in enumerate(nestedEnclosureList[0:-1]): for encl in Level: - childList = [] - for child in nestedEnclosureList[i+1]: - if child.ParentEnclosureID == encl.EnclosureID : - childList.append(child) - encl.SonEnclosures = childList[:] - - return nestedEnclosureList + childList = [] + for child in nestedEnclosureList[i + 1]: + if child.ParentEnclosureID == encl.EnclosureID: + childList.append(child) + encl.SonEnclosures = childList[:] + + return nestedEnclosureList -def checkEnclosure(FreeCAD_doc,EnclosureList): +def checkEnclosure(FreeCAD_doc, EnclosureList): stop = False # check all enclosure labels have an associated solid TempList = [] for elem in FreeCAD_doc.Objects: - if (elem.TypeId=='Part::Feature'): - if elem.Shape.Solids: - if elem.InList: - templabel = re.search('enclosure(?P[0-9]+)_(?P[0-9]+)_', elem.InList[0].Label) - if templabel is not None: - if elem.TypeId == 'Part::Feature' and len(elem.Shape.Solids) == 0 : - TempList.append(elem) + if elem.TypeId == "Part::Feature": + if elem.Shape.Solids: + if elem.InList: + templabel = re.search( + "enclosure(?P[0-9]+)_(?P[0-9]+)_", + elem.InList[0].Label, + ) + if templabel is not None: + if ( + elem.TypeId == "Part::Feature" + and len(elem.Shape.Solids) == 0 + ): + TempList.append(elem) if TempList: - stop = True - print('One or more nested enclosure labels in CAD solid tree view/structure tree do not have any CAD solid.\n',\ - 'Each nested enclosure must have only one solid.\nCode STOPS.',\ - '\nList of problematic nested enclosure labels:') - for elem in TempList: - print(elem.EnclosureID) - + stop = True + print( + "One or more nested enclosure labels in CAD solid tree view/structure tree do not have any CAD solid.\n", + "Each nested enclosure must have only one solid.\nCode STOPS.", + "\nList of problematic nested enclosure labels:", + ) + for elem in TempList: + print(elem.EnclosureID) + # check enclosure Labels don't make loops # 1) check at leat one 0 is in Parent enclosure label # 2) check 0 is not in child enclosure label # 3) check child enclosure label is not repeated - + SIDList = [] - PIDSet = set() + PIDSet = set() repeatedID = set() for encl in EnclosureList: - PIDSet.add(encl.ParentEnclosureID) - if encl.EnclosureID in SIDList: - repeatedID.add(encl.EnclosureID) - else: - SIDList.append(encl.EnclosureID) + PIDSet.add(encl.ParentEnclosureID) + if encl.EnclosureID in SIDList: + repeatedID.add(encl.EnclosureID) + else: + SIDList.append(encl.EnclosureID) - if 0 in SIDList : + if 0 in SIDList: stop = True - print ('"0" cannot be label on child Enclosure') - if 0 not in PIDSet : + print('"0" cannot be label on child Enclosure') + if 0 not in PIDSet: stop = True - print (' "0" should parent label of most external enclosure(s)') + print(' "0" should parent label of most external enclosure(s)') if repeatedID: stop = True - print('Child label cannot be repeated.\nRepeated labels :') + print("Child label cannot be repeated.\nRepeated labels :") for lab in repeatedID: print(lab) # this stop should not be move to the end of routine # if previous point not satisfied point 4) may lead to infinite loop - if stop : raise ValueError('Exiting to avoid infinite loop') + if stop: + raise ValueError("Exiting to avoid infinite loop") # 4) look for explicit loops enclDict = dict() for encl in EnclosureList: if encl.ParentEnclosureID in enclDict.keys(): enclDict[encl.ParentEnclosureID].append(encl.EnclosureID) - else: + else: enclDict[encl.ParentEnclosureID] = [encl.EnclosureID] parent = [0] cont = True while cont: - cont = False - nextParent = [] - for p in parent: - if p in enclDict.keys(): - cont = True - nextParent.extend(enclDict[p]) - del enclDict[p] - parent = nextParent + cont = False + nextParent = [] + for p in parent: + if p in enclDict.keys(): + cont = True + nextParent.extend(enclDict[p]) + del enclDict[p] + parent = nextParent if enclDict.keys(): - print('Following enclosure produce loop') + print("Following enclosure produce loop") for p in enclDict.keys(): - for s in enclDict[p] : - print ('{}_{}'.format(s,p)) - raise ValueError('GEOUNED.LoadFunctions.checkEnclosure failed') + for s in enclDict[p]: + print("{}_{}".format(s, p)) + raise ValueError("GEOUNED.LoadFunctions.checkEnclosure failed") # check enclosures solids are correctly nested and don't overlap each other nestedLevels = setEnclosureLevels(EnclosureList) overlap = [] - enclTree = [[0]] - for level in nestedLevels : - enclTree = updateTree(enclTree,level) + enclTree = [[0]] + for level in nestedLevels: + enclTree = updateTree(enclTree, level) for encl in level: - sameParent= dict() - if encl.ParentEnclosureID in sameParent.keys(): - sameParent[encl.ParentEnclosureID].append(encl.EnclosureID) - else: - sameParent[encl.ParentEnclosureID] = [encl.EnclosureID] + sameParent = dict() + if encl.ParentEnclosureID in sameParent.keys(): + sameParent[encl.ParentEnclosureID].append(encl.EnclosureID) + else: + sameParent[encl.ParentEnclosureID] = [encl.EnclosureID] for encl in sameParent.values(): overlap.extend(checkOverlap(encl)) notEmbedded = [] - for chain in enclTree : - up = chain[0] + for chain in enclTree: + up = chain[0] for low in chain[1:]: - inter = up.checkIntersection(low.CADSolid) - if inter != -2 : - notEmbedded.append((low.EnclosureID,up.EnclosureID)) - - if notEmbedded : - stop = True - print ( ' Following enclosures are not fully embedded in Parent enclosure') - for elemt in notEmbedded: - print('{}_{}').format(elemt[0],elemt[1]) - - if overlap : - stop = True - print ( ' Following enclosures overlapping ') - for elemt in overlap: - print('{}_{}').format(elemt[0],elemt[1]) - - if stop : raise ValueError('GEOUNED.LoadFunctions.checkEnclosure failed') - + inter = up.checkIntersection(low.CADSolid) + if inter != -2: + notEmbedded.append((low.EnclosureID, up.EnclosureID)) + + if notEmbedded: + stop = True + print(" Following enclosures are not fully embedded in Parent enclosure") + for elemt in notEmbedded: + print("{}_{}").format(elemt[0], elemt[1]) + + if overlap: + stop = True + print(" Following enclosures overlapping ") + for elemt in overlap: + print("{}_{}").format(elemt[0], elemt[1]) + + if stop: + raise ValueError("GEOUNED.LoadFunctions.checkEnclosure failed") + + def checkOverlap(enclosures): - overlap = [] - for i,enc1 in enumerate(enclosures): - for enc2 in enclosures[i+1:]: - inter = enc1.checkIntersection(enc2.CADSolid) - if inter != 1: - overlap.append((enc1.EnclosureID,enc2.EnclosureID)) - return overlap - -def updateTree(Tree,level): + overlap = [] + for i, enc1 in enumerate(enclosures): + for enc2 in enclosures[i + 1 :]: + inter = enc1.checkIntersection(enc2.CADSolid) + if inter != 1: + overlap.append((enc1.EnclosureID, enc2.EnclosureID)) + return overlap + + +def updateTree(Tree, level): newTree = [] - for encl in level : - for lst in Tree: - if lst[-1] == encl.ParentEnclosureID : - newTree.append(lst + [encl.EnclosureID]) - continue - return newTree + for encl in level: + for lst in Tree: + if lst[-1] == encl.ParentEnclosureID: + newTree.append(lst + [encl.EnclosureID]) + continue + return newTree + def set_docOptions(): # set import step document options for FreeCAD version >0.18 compatible with FreeCAD0.18 opening options p0 = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Import") - p0.SetBool("UseLinkGroup",False) - p0.SetBool("ReduceObjects",False) - p0.SetBool("ExpandCompound",False) - + p0.SetBool("UseLinkGroup", False) + p0.SetBool("ReduceObjects", False) + p0.SetBool("ExpandCompound", False) + p1 = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Import/hSTEP") - p1.SetBool("UseLinkGroup",False) - p1.SetBool("ReadShapeCompoundMode",True) - + p1.SetBool("UseLinkGroup", False) + p1.SetBool("ReadShapeCompoundMode", True) + -# functions not used in the code -def checkIndex(docList,index,returnObject=False): +# functions not used in the code +def checkIndex(docList, index, returnObject=False): subList = docList.ElementList for i in index[:-1]: - if len(subList) > i : - subList = subList[i] - if subList.TypeId != 'App::LinkGroup' : return None - subList=subList.ElementList + if len(subList) > i: + subList = subList[i] + if subList.TypeId != "App::LinkGroup": + return None + subList = subList.ElementList + else: + return None + + if len(subList) > index[-1]: + if subList[index[-1]].TypeId == "App::LinkGroup": + return "Link" else: - return None - - if len(subList) > index[-1] : - if subList[index[-1]].TypeId == 'App::LinkGroup' : - return 'Link' - else: - if returnObject : - return subList[ index[-1]] - else: - return 'Feature' + if returnObject: + return subList[index[-1]] + else: + return "Feature" else: - return None - -def nextIndex(docList,lastIndex=None): + return None + + +def nextIndex(docList, lastIndex=None): if lastIndex is None: - lastIndex = [0] - while checkIndex(docList,lastIndex) != 'Feature' : - lastIndex.append(0) - else: - return lastIndex + lastIndex = [0] + while checkIndex(docList, lastIndex) != "Feature": + lastIndex.append(0) + else: + return lastIndex tmp = lastIndex[:] move = True while True: - if move: - tmp[-1] = tmp[-1]+1 - obj = checkIndex(docList,tmp) - if obj == 'Feature' : - return tmp - elif obj == 'Link' : - tmp.append(0) - move = False - else: - tmp =tmp[0:-1] - move = True - if len(tmp) == 0 : return None - - -def solidGenerator(doclist) : - last = None - while True: - last = nextIndex(doclist,last) - if last is None : break - yield checkIndex(doclist,last,True) + if move: + tmp[-1] = tmp[-1] + 1 + obj = checkIndex(docList, tmp) + if obj == "Feature": + return tmp + elif obj == "Link": + tmp.append(0) + move = False + else: + tmp = tmp[0:-1] + move = True + if len(tmp) == 0: + return None + + +def solidGenerator(doclist): + last = None + while True: + last = nextIndex(doclist, last) + if last is None: + break + yield checkIndex(doclist, last, True) diff --git a/src/geouned/GEOUNED/LoadFile/LoadSTEP.py b/src/geouned/GEOUNED/LoadFile/LoadSTEP.py index 9deaa28b..a1098d73 100644 --- a/src/geouned/GEOUNED/LoadFile/LoadSTEP.py +++ b/src/geouned/GEOUNED/LoadFile/LoadSTEP.py @@ -16,40 +16,43 @@ def extractMaterials(filename): rhoreal = [] namestr = [] - mdict = {} #_ Material dictionary - with open(filename,"rt") as file: - for line in file: - vals = line.split() - if vals[0].startswith("#"): continue - matlabel = int(vals[0]) - rhoreal = -float(vals[1]) - matname = " ".join(vals[2:]) - mdict[matlabel] = (rhoreal,matname) + mdict = {} # _ Material dictionary + with open(filename, "rt") as file: + for line in file: + vals = line.split() + if vals[0].startswith("#"): + continue + matlabel = int(vals[0]) + rhoreal = -float(vals[1]) + matname = " ".join(vals[2:]) + mdict[matlabel] = (rhoreal, matname) return mdict -def LoadCAD(filename,matfilename,defaultMat=[],compSolids=True): - # Set document solid tree options when opening CAD differing from version 0.18 - if int(FreeCAD.Version()[1]) > 18 : LF.set_docOptions() - - CAD_simplificado_doc=FreeCAD.newDocument("CAD_simplificado") - Import.insert(filename,"CAD_simplificado") +def LoadCAD(filename, matfilename, defaultMat=[], compSolids=True): - if matfilename != '' : - if os.path.exists(matfilename): - mdict = extractMaterials(matfilename) - else: - print('Material definition file {} does not exist.'.format(matfilename)) - mdict = {} + # Set document solid tree options when opening CAD differing from version 0.18 + if int(FreeCAD.Version()[1]) > 18: + LF.set_docOptions() + + CAD_simplificado_doc = FreeCAD.newDocument("CAD_simplificado") + Import.insert(filename, "CAD_simplificado") + + if matfilename != "": + if os.path.exists(matfilename): + mdict = extractMaterials(matfilename) + else: + print("Material definition file {} does not exist.".format(matfilename)) + mdict = {} else: - mdict = {} - - s=Part.Shape() + mdict = {} + + s = Part.Shape() s.read(filename) - Solids=s.Solids + Solids = s.Solids MetaList = [] - for i,s in enumerate(Solids) : - MetaList.append(UF.GEOUNED_Solid(i+1,s)) + for i, s in enumerate(Solids): + MetaList.append(UF.GEOUNED_Solid(i + 1, s)) isolid = 0 missingMat = set() @@ -57,122 +60,136 @@ def LoadCAD(filename,matfilename,defaultMat=[],compSolids=True): docObjects = CAD_simplificado_doc.Objects for elem in docObjects: - if (elem.TypeId == 'Part::Feature'): - comment = LF.getCommentTree(elem) - if not elem.Shape.Solids: - print('Warning: Element {:} has no associated solid'.format(comment+'/'+elem.Label)) - continue - else: - tempremat = None - tempredil = None - - # MIO: lightly modification of label if required - label = LF.GetLabel(elem.Label) - comment=comment+'/'+label - if elem.InList: - # MIO: lightly modification of label if required - label_inList = LF.GetLabel(elem.InList[0].Label) - enclLabel = re.search('enclosure(?P[0-9]+)_(?P[0-9]+)_', label_inList) - if not enclLabel : - enclLabel = re.search('enclosure(?P[0-9]+)_(?P[0-9]+)_', label) - - envelLabel = re.search('envelope(?P[0-9]+)_(?P[0-9]+)_', label_inList) - if not envelLabel : - envelLabel = re.search('envelope(?P[0-9]+)_(?P[0-9]+)_', label) - - #tempremat = re.search("(m(?P\d+)_)",elem.Label) - #if not tempremat : - # tempremat = re.search("(m(?P\d+)_)",elem.InList[0].Label) - - #tempredil = re.search("(_d(?P\d*\.\d*)_)",elem.Label) - #if not tempredil : - # tempredil = re.search("(_d(?P\d*\.\d*)_)",elem.InList[0].Label) - - # Paco modifications - # Search for material definition in tree - xelem = [elem] - while xelem and not tempremat: - # MIO: Modification of label if required - temp_label = LF.GetLabel(xelem[0].Label) - tempremat = re.search("_m(?P\d+)_","_"+temp_label ) - xelem = xelem[0].InList - - # Search for dilution definition in tree - xelem = [elem] - while xelem and not tempredil: - # MIO: Modification of label if required - temp_label = LF.GetLabel(xelem[0].Label) - tempredil = re.search("_d(?P\d*\.\d*)_",temp_label) - xelem = xelem[0].InList - # Paco end - else: - enclLabel = None - envelLabel = None - - # compSolid Diferent solid of the same cell are stored in the same metaObject (compSolid) - # enclosures and envelopes are always stored as compound - if compSolids or enclLabel or envelLabel : - - init = isolid - end = isolid+len(elem.Shape.Solids) - LF.fuseMetaObj(MetaList,init,end) - nsolids = 1 - else: - nsolids = len(elem.Shape.Solids) - - for i in range(nsolids): - MetaList[isolid].setComments('{}{}'.format(comment,(i+1))) - MetaList[isolid].setCADSolid() - - if tempremat: - matlabel = int(tempremat.group('mat')) - if matlabel in mdict.keys() : - MetaList[isolid].setMaterial(matlabel,mdict[matlabel][0],mdict[matlabel][1]) - else: - if matlabel == 0 : - MetaList[isolid].setMaterial(matlabel,0,0) - else: - MetaList[isolid].setMaterial(matlabel,-100,'Missing material density information') - missingMat.add(matlabel) - else: - #print('Warning : No material label associated to solid {}.\nDefault material used instead.'.format(comment)) - if defaultMat: - MetaList[isolid].setMaterial(*defaultMat) - if tempredil: - MetaList[isolid].setDilution(float(tempredil.group('dil'))) - - if enclLabel is not None: - MetaList[isolid].EnclosureID = int(enclLabel.group('encl')) - MetaList[isolid].ParentEnclosureID = int(enclLabel.group('parent')) - MetaList[isolid].IsEnclosure = True - MetaList[isolid].CellType = 'void' - - if envelLabel is not None: - MetaList[isolid].EnclosureID = int(envelLabel.group('env')) - MetaList[isolid].ParentEnclosureID = int(envelLabel.group('parent')) - MetaList[isolid].IsEnclosure = True - MetaList[isolid].CellType = 'envelope' - isolid += 1 + if elem.TypeId == "Part::Feature": + comment = LF.getCommentTree(elem) + if not elem.Shape.Solids: + print( + "Warning: Element {:} has no associated solid".format( + comment + "/" + elem.Label + ) + ) + continue + else: + tempremat = None + tempredil = None + + # MIO: lightly modification of label if required + label = LF.GetLabel(elem.Label) + comment = comment + "/" + label + if elem.InList: + # MIO: lightly modification of label if required + label_inList = LF.GetLabel(elem.InList[0].Label) + enclLabel = re.search( + "enclosure(?P[0-9]+)_(?P[0-9]+)_", label_inList + ) + if not enclLabel: + enclLabel = re.search( + "enclosure(?P[0-9]+)_(?P[0-9]+)_", label + ) + + envelLabel = re.search( + "envelope(?P[0-9]+)_(?P[0-9]+)_", label_inList + ) + if not envelLabel: + envelLabel = re.search( + "envelope(?P[0-9]+)_(?P[0-9]+)_", label + ) + + # tempremat = re.search("(m(?P\d+)_)",elem.Label) + # if not tempremat : + # tempremat = re.search("(m(?P\d+)_)",elem.InList[0].Label) + + # tempredil = re.search("(_d(?P\d*\.\d*)_)",elem.Label) + # if not tempredil : + # tempredil = re.search("(_d(?P\d*\.\d*)_)",elem.InList[0].Label) + + # Paco modifications + # Search for material definition in tree + xelem = [elem] + while xelem and not tempremat: + # MIO: Modification of label if required + temp_label = LF.GetLabel(xelem[0].Label) + tempremat = re.search("_m(?P\d+)_", "_" + temp_label) + xelem = xelem[0].InList + + # Search for dilution definition in tree + xelem = [elem] + while xelem and not tempredil: + # MIO: Modification of label if required + temp_label = LF.GetLabel(xelem[0].Label) + tempredil = re.search("_d(?P\d*\.\d*)_", temp_label) + xelem = xelem[0].InList + # Paco end + else: + enclLabel = None + envelLabel = None + + # compSolid Diferent solid of the same cell are stored in the same metaObject (compSolid) + # enclosures and envelopes are always stored as compound + if compSolids or enclLabel or envelLabel: + + init = isolid + end = isolid + len(elem.Shape.Solids) + LF.fuseMetaObj(MetaList, init, end) + nsolids = 1 + else: + nsolids = len(elem.Shape.Solids) + + for i in range(nsolids): + MetaList[isolid].setComments("{}{}".format(comment, (i + 1))) + MetaList[isolid].setCADSolid() + + if tempremat: + matlabel = int(tempremat.group("mat")) + if matlabel in mdict.keys(): + MetaList[isolid].setMaterial( + matlabel, mdict[matlabel][0], mdict[matlabel][1] + ) + else: + if matlabel == 0: + MetaList[isolid].setMaterial(matlabel, 0, 0) + else: + MetaList[isolid].setMaterial( + matlabel, + -100, + "Missing material density information", + ) + missingMat.add(matlabel) + else: + # print('Warning : No material label associated to solid {}.\nDefault material used instead.'.format(comment)) + if defaultMat: + MetaList[isolid].setMaterial(*defaultMat) + if tempredil: + MetaList[isolid].setDilution(float(tempredil.group("dil"))) + + if enclLabel is not None: + MetaList[isolid].EnclosureID = int(enclLabel.group("encl")) + MetaList[isolid].ParentEnclosureID = int( + enclLabel.group("parent") + ) + MetaList[isolid].IsEnclosure = True + MetaList[isolid].CellType = "void" + + if envelLabel is not None: + MetaList[isolid].EnclosureID = int(envelLabel.group("env")) + MetaList[isolid].ParentEnclosureID = int( + envelLabel.group("parent") + ) + MetaList[isolid].IsEnclosure = True + MetaList[isolid].CellType = "envelope" + isolid += 1 LF.joinEnvelopes(MetaList) - if missingMat : - print('Warning!! At least one material in the CAD model is not present in the material file') - print('List of not present materials:', missingMat) + if missingMat: + print( + "Warning!! At least one material in the CAD model is not present in the material file" + ) + print("List of not present materials:", missingMat) EnclosureList = LF.setEnclosureSolidList(MetaList) if EnclosureList: - LF.checkEnclosure(CAD_simplificado_doc,EnclosureList) + LF.checkEnclosure(CAD_simplificado_doc, EnclosureList) # LF.RemoveEnclosure(MetaList) - return MetaList,EnclosureList + return MetaList, EnclosureList else: - return MetaList,[] - - - - - - - - - - + return MetaList, [] diff --git a/src/geouned/GEOUNED/Utils/BasicFunctions_part1.py b/src/geouned/GEOUNED/Utils/BasicFunctions_part1.py index 0b455fa4..f5ccfc99 100644 --- a/src/geouned/GEOUNED/Utils/BasicFunctions_part1.py +++ b/src/geouned/GEOUNED/Utils/BasicFunctions_part1.py @@ -6,193 +6,228 @@ import FreeCAD -def isSameValue(v1,v2,tolerance=1e-6): - return abs(v1-v2) < tolerance +def isSameValue(v1, v2, tolerance=1e-6): + return abs(v1 - v2) < tolerance -def isOposite(Vector1,Vector2,tolerance=1e-6): +def isOposite(Vector1, Vector2, tolerance=1e-6): return abs(Vector1.getAngle(-Vector2)) < tolerance - -def isParallel(Vector1,Vector2,tolerance=1e-6): + +def isParallel(Vector1, Vector2, tolerance=1e-6): angle = abs(Vector1.getAngle(Vector2)) - return (angle < tolerance or isSameValue(angle,math.pi,tolerance) ) + return angle < tolerance or isSameValue(angle, math.pi, tolerance) -def isInLine(Point,Dir,Pnt_line,tolerance=1e-6): +def isInLine(Point, Dir, Pnt_line, tolerance=1e-6): r12 = Point - Pnt_line - return (isParallel(Dir,r12) or (r12.Length < tolerance)) + return isParallel(Dir, r12) or (r12.Length < tolerance) + - -def isInPoints(point,Points,tolerance=1e-5): - if len(Points)>0: +def isInPoints(point, Points, tolerance=1e-5): + if len(Points) > 0: for P in Points: - if point.isEqual(P,tolerance): + if point.isEqual(P, tolerance): return True - return False + return False + -def isInEdge(Edge1,Edge2,tolerance=1e-8): - Ver1=Edge1.Vertexes - Ver2=Edge2.Vertexes - con1 = Ver1[0].Point.isEqual(Ver2[0].Point,tolerance) or Ver1[0].Point.isEqual(Ver2[1].Point,tolerance) - con2 = Ver1[1].Point.isEqual(Ver2[0].Point,tolerance) or Ver1[1].Point.isEqual(Ver2[1].Point,tolerance) - return (con1 and con2) +def isInEdge(Edge1, Edge2, tolerance=1e-8): + Ver1 = Edge1.Vertexes + Ver2 = Edge2.Vertexes + con1 = Ver1[0].Point.isEqual(Ver2[0].Point, tolerance) or Ver1[0].Point.isEqual( + Ver2[1].Point, tolerance + ) + con2 = Ver1[1].Point.isEqual(Ver2[0].Point, tolerance) or Ver1[1].Point.isEqual( + Ver2[1].Point, tolerance + ) + return con1 and con2 -def isInPlane(Point,plane,dtolerance=1e-7): - return abs(Point.distanceToPlane(plane.Surf.Position,plane.Surf.Axis)) < dtolerance +def isInPlane(Point, plane, dtolerance=1e-7): + return abs(Point.distanceToPlane(plane.Surf.Position, plane.Surf.Axis)) < dtolerance -def isInTolerance(val,tol,fuzzyLow,fuzzyHigh): - if abs(val) < fuzzyLow : - return True,False # 1) isintolerance 2) fuzzy - elif abs(val) < tol : - return True,True - elif abs(val) > fuzzyHigh : - return False,False +def isInTolerance(val, tol, fuzzyLow, fuzzyHigh): + if abs(val) < fuzzyLow: + return True, False # 1) isintolerance 2) fuzzy + elif abs(val) < tol: + return True, True + elif abs(val) > fuzzyHigh: + return False, False else: - return False,True + return False, True -def signPlane(Point,plane): - value = plane.Surf.Axis.dot(Point-plane.Surf.Position) - if (value>=0.0): - sign=1 + +def signPlane(Point, plane): + value = plane.Surf.Axis.dot(Point - plane.Surf.Position) + if value >= 0.0: + sign = 1 else: - sign=-1 + sign = -1 return sign + def pointsToCoeffs(Points): - p1,p2,p3 = Points[0:3] - scf = (p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z) + p1, p2, p3 = Points[0:3] + scf = (p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z) # mcnp implementation to convert 3 point plane to # plane parameters - tpp = [0]*4 - for i in range(1,4) : - j = i%3 + 1 - k = 6 -i -j - k -= 1 - j -= 1 - tpp[i-1] = scf[j ]*(scf[k+3]-scf[k+6]) \ - +scf[j+3]*(scf[k+6]-scf[k ]) \ - +scf[j+6]*(scf[k ]-scf[k+3]) - tpp[3] += scf[i-1]*(scf[j+3]*scf[k+6]-scf[j+6]*scf[k+3]) + tpp = [0] * 4 + for i in range(1, 4): + j = i % 3 + 1 + k = 6 - i - j + k -= 1 + j -= 1 + tpp[i - 1] = ( + scf[j] * (scf[k + 3] - scf[k + 6]) + + scf[j + 3] * (scf[k + 6] - scf[k]) + + scf[j + 6] * (scf[k] - scf[k + 3]) + ) + tpp[3] += scf[i - 1] * (scf[j + 3] * scf[k + 6] - scf[j + 6] * scf[k + 3]) xm = 0 - coeff = [0]*4 - for i in range(1,5): - if xm == 0 and tpp[4-i] != 0 : xm = 1/tpp[4-i] - coeff[4-i] = tpp[4-i]*xm - - Axis = FreeCAD.Vector(coeff[0:3]) - Distance = coeff[3]/Axis.Length + coeff = [0] * 4 + for i in range(1, 5): + if xm == 0 and tpp[4 - i] != 0: + xm = 1 / tpp[4 - i] + coeff[4 - i] = tpp[4 - i] * xm + + Axis = FreeCAD.Vector(coeff[0:3]) + Distance = coeff[3] / Axis.Length Axis.normalize() - return Axis,Distance + return Axis, Distance class Plane3PtsParams: - def __init__(self,params,real=True): - self.Position = params[0] - self.Axis = params[1] - self.dimL1 = params[2] - self.dimL2 = params[3] - self.Points = params[4] - self.real = real - self.pointDef = True - - - def __str__(self): -# outstr = '''Plane : -# Point 1 : {P1[0]} {P1[1]} {P1[2]} -# Point 2 : {P2[0]} {P2[1]} {P2[2]} -# Point 3 : {P3[0]} {P3[1]} {P3[2]} '''.format(P1=self.Points[0], P2=self.Points[1], P3=self.Points[2]) - pos = self.Axis.dot(self.Position) - outstr = '''Plane : + def __init__(self, params, real=True): + self.Position = params[0] + self.Axis = params[1] + self.dimL1 = params[2] + self.dimL2 = params[3] + self.Points = params[4] + self.real = real + self.pointDef = True + + def __str__(self): + # outstr = '''Plane : + # Point 1 : {P1[0]} {P1[1]} {P1[2]} + # Point 2 : {P2[0]} {P2[1]} {P2[2]} + # Point 3 : {P3[0]} {P3[1]} {P3[2]} '''.format(P1=self.Points[0], P2=self.Points[1], P3=self.Points[2]) + pos = self.Axis.dot(self.Position) + outstr = """Plane : Axis : {} {} {} - Position : {} '''.format(self.Axis.x ,self.Axis.y ,self.Axis.z, pos) - return outstr + Position : {} """.format( + self.Axis.x, self.Axis.y, self.Axis.z, pos + ) + return outstr + class PlaneParams: - def __init__(self,params,real=True): - self.Position = params[0] - self.Axis = params[1] - self.dimL1 = params[2] - self.dimL2 = params[3] - self.real = real - self.pointDef = False - - - def __str__(self): - pos = self.Axis.dot(self.Position) - outstr = '''Plane : + def __init__(self, params, real=True): + self.Position = params[0] + self.Axis = params[1] + self.dimL1 = params[2] + self.dimL2 = params[3] + self.real = real + self.pointDef = False + + def __str__(self): + pos = self.Axis.dot(self.Position) + outstr = """Plane : Axis : {} {} {} - Position : {} '''.format(self.Axis.x ,self.Axis.y ,self.Axis.z, pos) - return outstr + Position : {} """.format( + self.Axis.x, self.Axis.y, self.Axis.z, pos + ) + return outstr + class CylinderParams: - def __init__(self,params,real=True): - self.Center = params[0] - self.Axis = params[1] - self.Radius = params[2] - self.dimL = params[3] - self.real = real - - def __str__(self): - outstr = '''Cylinder : + def __init__(self, params, real=True): + self.Center = params[0] + self.Axis = params[1] + self.Radius = params[2] + self.dimL = params[3] + self.real = real + + def __str__(self): + outstr = """Cylinder : Axis : {} {} {} Center : {} {} {} - Radius : {} '''.format(self.Axis.x ,self.Axis.y ,self.Axis.z,\ - self.Center.x,self.Center.y,self.Center.z,\ - self.Radius) - return outstr + Radius : {} """.format( + self.Axis.x, + self.Axis.y, + self.Axis.z, + self.Center.x, + self.Center.y, + self.Center.z, + self.Radius, + ) + return outstr + class ConeParams: - def __init__(self,params,real=True): - self.Apex = params[0] - self.Axis = params[1] - self.SemiAngle = params[2] - self.dimL = params[3] - self.dimR = params[4] - self.real = real - - def __str__(self): - outstr = '''Cone : + def __init__(self, params, real=True): + self.Apex = params[0] + self.Axis = params[1] + self.SemiAngle = params[2] + self.dimL = params[3] + self.dimR = params[4] + self.real = real + + def __str__(self): + outstr = """Cone : Axis : {} {} {} Center : {} {} {} - SemiAngle: {} '''.format(self.Axis.x ,self.Axis.y ,self.Axis.z,\ - self.Apex.x,self.Apex.y,self.Apex.z,\ - self.SemiAngle) - return outstr + SemiAngle: {} """.format( + self.Axis.x, + self.Axis.y, + self.Axis.z, + self.Apex.x, + self.Apex.y, + self.Apex.z, + self.SemiAngle, + ) + return outstr class SphereParams: - def __init__(self,params): - self.Center = params[0] - self.Radius = params[1] + def __init__(self, params): + self.Center = params[0] + self.Radius = params[1] - def __str__(self): - outstr = '''Sphere : + def __str__(self): + outstr = """Sphere : Center : {} {} {} - Radius : {} '''.format(self.Center.x,self.Center.y,self.Center.z,\ - self.Radius) - return outstr + Radius : {} """.format( + self.Center.x, self.Center.y, self.Center.z, self.Radius + ) + return outstr + class TorusParams: - def __init__(self,params): - self.Center = params[0] - self.Axis = params[1] - self.MajorRadius = params[2] - self.MinorRadius = params[3] + def __init__(self, params): + self.Center = params[0] + self.Axis = params[1] + self.MajorRadius = params[2] + self.MinorRadius = params[3] def __str__(self): - outstr = '''Torus : + outstr = """Torus : Axis : {} {} {} Center : {} {} {} MajorRadius: {} - MinorRadius: {} '''.format(self.Axis.x ,self.Axis.y ,self.Axis.z,\ - self.Center.x,self.Center.y,self.Center.z,\ - self.MajorRadius,self.MinorRadius) - return outstr - + MinorRadius: {} """.format( + self.Axis.x, + self.Axis.y, + self.Axis.z, + self.Center.x, + self.Center.y, + self.Center.z, + self.MajorRadius, + self.MinorRadius, + ) + return outstr diff --git a/src/geouned/GEOUNED/Utils/BasicFunctions_part2.py b/src/geouned/GEOUNED/Utils/BasicFunctions_part2.py index b80b322e..5fbb84d3 100644 --- a/src/geouned/GEOUNED/Utils/BasicFunctions_part2.py +++ b/src/geouned/GEOUNED/Utils/BasicFunctions_part2.py @@ -5,280 +5,328 @@ import FreeCAD -from ..Utils.BasicFunctions_part1 import (isInLine, isInPlane, isInTolerance, - isOposite, isParallel, isSameValue) +from ..Utils.BasicFunctions_part1 import ( + isInLine, + isInPlane, + isInTolerance, + isOposite, + isParallel, + isSameValue, +) from ..Write.Functions import MCNPSurface -sameSurfFic = open('fuzzySurfaces','w') -def Fuzzy(index,dtype,surf1,surf2,val,tol): - - same = val <= tol - - if dtype == 'plane': - p1str = MCNPSurface(index,'Plane',surf1) - p2str = MCNPSurface(0,'Plane',surf2) - line = 'Same surface : {}\nPlane distance / Tolerance : {} {}\n {}\n {}\n\n'.format(same,val,tol,p1str,p2str) - sameSurfFic.write(line) - - elif dtype == 'cylRad': - cyl1str = MCNPSurface(index,'Cylinder',surf1) - cyl2str = MCNPSurface(0,'Cylinder',surf2) - line = 'Same surface : {}\nDiff Radius / Tolerance: {} {}\n {}\n {}\n\n'.format(same,val,tol,cyl1str,cyl2str) - sameSurfFic.write(line) - - elif dtype == 'cylAxs': - cyl1str = MCNPSurface(index,'Cylinder',surf1) - cyl2str = MCNPSurface(0,'Cylinder',surf2) - c12 = surf1.Center - surf2.Center - line = 'Same surface : {}\nDist Axis / Tolerance: {} {}\n {}\n {}\n\n'.format(same,val,tol,cyl1str,cyl2str) - sameSurfFic.write(line) - -def isSamePlane(p1,p2,dtol=1e-6,atol=1e-6,relTol=True,fuzzy=(False,0)): - if isParallel(p1.Axis,p2.Axis,atol): - d1 = p1.Axis.dot(p1.Position) - d2 = p2.Axis.dot(p2.Position) - if isOposite(p1.Axis,p2.Axis,atol) : d2 = -d2 - d = abs(d1-d2) - if relTol : - tol = dtol * max(p2.dim1,p2.dim2) - else : - tol = dtol - - isSame,isFuzzy = isInTolerance(d,tol,0.5*tol,2*tol) - if isFuzzy and fuzzy[0]: Fuzzy(fuzzy[1],'plane',p2,p1,d,tol) - return isSame - return False - - -def isSameCylinder(cyl1,cyl2,dtol=1e-6, atol=1e-6, relTol=True, fuzzy=(False,0)): - if relTol : - rtol = dtol * max(cyl2.Radius,cyl1.Radius) +sameSurfFic = open("fuzzySurfaces", "w") + + +def Fuzzy(index, dtype, surf1, surf2, val, tol): + + same = val <= tol + + if dtype == "plane": + p1str = MCNPSurface(index, "Plane", surf1) + p2str = MCNPSurface(0, "Plane", surf2) + line = "Same surface : {}\nPlane distance / Tolerance : {} {}\n {}\n {}\n\n".format( + same, val, tol, p1str, p2str + ) + sameSurfFic.write(line) + + elif dtype == "cylRad": + cyl1str = MCNPSurface(index, "Cylinder", surf1) + cyl2str = MCNPSurface(0, "Cylinder", surf2) + line = "Same surface : {}\nDiff Radius / Tolerance: {} {}\n {}\n {}\n\n".format( + same, val, tol, cyl1str, cyl2str + ) + sameSurfFic.write(line) + + elif dtype == "cylAxs": + cyl1str = MCNPSurface(index, "Cylinder", surf1) + cyl2str = MCNPSurface(0, "Cylinder", surf2) + c12 = surf1.Center - surf2.Center + line = "Same surface : {}\nDist Axis / Tolerance: {} {}\n {}\n {}\n\n".format( + same, val, tol, cyl1str, cyl2str + ) + sameSurfFic.write(line) + + +def isSamePlane(p1, p2, dtol=1e-6, atol=1e-6, relTol=True, fuzzy=(False, 0)): + if isParallel(p1.Axis, p2.Axis, atol): + d1 = p1.Axis.dot(p1.Position) + d2 = p2.Axis.dot(p2.Position) + if isOposite(p1.Axis, p2.Axis, atol): + d2 = -d2 + d = abs(d1 - d2) + if relTol: + tol = dtol * max(p2.dim1, p2.dim2) + else: + tol = dtol + + isSame, isFuzzy = isInTolerance(d, tol, 0.5 * tol, 2 * tol) + if isFuzzy and fuzzy[0]: + Fuzzy(fuzzy[1], "plane", p2, p1, d, tol) + return isSame + return False + + +def isSameCylinder(cyl1, cyl2, dtol=1e-6, atol=1e-6, relTol=True, fuzzy=(False, 0)): + if relTol: + rtol = dtol * max(cyl2.Radius, cyl1.Radius) else: - rtol = dtol - - isSameRad,isFuzzy = isInTolerance(cyl2.Radius-cyl1.Radius,rtol,0.5*rtol,2*rtol) - if isFuzzy and fuzzy[0]: Fuzzy(fuzzy[1],'cylRad',cyl2,cyl1,abs(cyl2.Radius-cyl1.Radius),rtol) - - if isSameRad : - if isParallel(cyl1.Axis,cyl2.Axis,atol): - c12 = cyl1.Center-cyl2.Center - d = cyl1.Axis.cross(c12).Length - - if relTol: - tol = dtol * max(cyl1.Center.Length,cyl2.Center.Length) - else: - tol = dtol - - isSameCenter,isFuzzy = isInTolerance(d,tol,0.5*tol,2*tol) - if isFuzzy and fuzzy[0]: Fuzzy(fuzzy[1],'cylAxs',cyl1,cyl2,d,tol) - - return isSameCenter + rtol = dtol + + isSameRad, isFuzzy = isInTolerance( + cyl2.Radius - cyl1.Radius, rtol, 0.5 * rtol, 2 * rtol + ) + if isFuzzy and fuzzy[0]: + Fuzzy(fuzzy[1], "cylRad", cyl2, cyl1, abs(cyl2.Radius - cyl1.Radius), rtol) + + if isSameRad: + if isParallel(cyl1.Axis, cyl2.Axis, atol): + c12 = cyl1.Center - cyl2.Center + d = cyl1.Axis.cross(c12).Length + + if relTol: + tol = dtol * max(cyl1.Center.Length, cyl2.Center.Length) + else: + tol = dtol + + isSameCenter, isFuzzy = isInTolerance(d, tol, 0.5 * tol, 2 * tol) + if isFuzzy and fuzzy[0]: + Fuzzy(fuzzy[1], "cylAxs", cyl1, cyl2, d, tol) + + return isSameCenter return False -def isSameCone (cone1,cone2, dtol=1e-6, atol=1e-6, relTol=True): - if isSameValue(cone1.SemiAngle,cone2.SemiAngle,atol) : - if isParallel(cone1.Axis,cone2.Axis,atol) : - if relTol : - tol = dtol * max(cone1.Apex.Length,cone2.Apex.Length) - else: - tol = dtol - return cone1.Apex.isEqual(cone2.Apex,tol) - return False - - -def isSameSphere (sph1,sph2,tolerance=1e-6,relTol=True): - if relTol : - rtol = tolerance * max(sph2.Radius,sph1.Radius) +def isSameCone(cone1, cone2, dtol=1e-6, atol=1e-6, relTol=True): + if isSameValue(cone1.SemiAngle, cone2.SemiAngle, atol): + if isParallel(cone1.Axis, cone2.Axis, atol): + if relTol: + tol = dtol * max(cone1.Apex.Length, cone2.Apex.Length) + else: + tol = dtol + return cone1.Apex.isEqual(cone2.Apex, tol) + return False + + +def isSameSphere(sph1, sph2, tolerance=1e-6, relTol=True): + if relTol: + rtol = tolerance * max(sph2.Radius, sph1.Radius) else: - rtol = tolerance + rtol = tolerance if isSameValue(sph1.Radius, sph2.Radius, rtol): - if relTol : - ctol = tolerance * max(sph2.Center.Length,sph1.Center.Length) - else: - ctol = tolerance - return sph1.Center.isEqual(sph2.Center,ctol) + if relTol: + ctol = tolerance * max(sph2.Center.Length, sph1.Center.Length) + else: + ctol = tolerance + return sph1.Center.isEqual(sph2.Center, ctol) return False -def isSameTorus (tor1,tor2,dtol=1e-6,atol=1e-6,relTol=True): - if isParallel(tor1.Axis,tor2.Axis,atol) : - if tor1.Axis.dot(tor2.Axis) < 0 : return False # Assume same cone with oposite axis as different - if relTol : - Rtol = dtol * max(tor1.MajorRadius, tor2.MajorRadius) - rtol = dtol * max(tor1.MinorRadius, tor2.MinorRadius) - else: - Rtol = dtol - rtol = dtol - - if isSameValue(tor1.MajorRadius, tor2.MajorRadius, Rtol) and \ - isSameValue(tor1.MinorRadius, tor2.MinorRadius, rtol) : - if relTol : - ctol = dtol * max(tor1.Center.Length, tor2.Center.Length) - else: - ctol = dtol - return tor1.Center.isEqual(tor2.Center,ctol) +def isSameTorus(tor1, tor2, dtol=1e-6, atol=1e-6, relTol=True): + if isParallel(tor1.Axis, tor2.Axis, atol): + if tor1.Axis.dot(tor2.Axis) < 0: + return False # Assume same cone with oposite axis as different + if relTol: + Rtol = dtol * max(tor1.MajorRadius, tor2.MajorRadius) + rtol = dtol * max(tor1.MinorRadius, tor2.MinorRadius) + else: + Rtol = dtol + rtol = dtol + + if isSameValue(tor1.MajorRadius, tor2.MajorRadius, Rtol) and isSameValue( + tor1.MinorRadius, tor2.MinorRadius, rtol + ): + if relTol: + ctol = dtol * max(tor1.Center.Length, tor2.Center.Length) + else: + ctol = dtol + return tor1.Center.isEqual(tor2.Center, ctol) return False -def isDuplicateInList(num_str1,i,lista): - for j,elem2 in enumerate(lista): - if (i == j ) : continue - num_str2='%11.4E' %(elem2) - num_str3='%11.4E' %(elem2+2.0*math.pi) - num_str4='%11.4E' %(elem2-2.0*math.pi) - - if abs(float(num_str2))<1.0e-5: - num_str2='%11.4E' %0.0 - - if abs(float(num_str3))<1.0e-5: - num_str3='%11.4E' %0.0 - - if abs(float(num_str4))<1.0e-5: - num_str4='%11.4E' %0.0 - - if (num_str1 == num_str2 or num_str1 == num_str3 or num_str1 == num_str4): + +def isDuplicateInList(num_str1, i, lista): + for j, elem2 in enumerate(lista): + if i == j: + continue + num_str2 = "%11.4E" % (elem2) + num_str3 = "%11.4E" % (elem2 + 2.0 * math.pi) + num_str4 = "%11.4E" % (elem2 - 2.0 * math.pi) + + if abs(float(num_str2)) < 1.0e-5: + num_str2 = "%11.4E" % 0.0 + + if abs(float(num_str3)) < 1.0e-5: + num_str3 = "%11.4E" % 0.0 + + if abs(float(num_str4)) < 1.0e-5: + num_str4 = "%11.4E" % 0.0 + + if num_str1 == num_str2 or num_str1 == num_str3 or num_str1 == num_str4: return True return False - -def isInFaces(face,Faces): - if (Faces==[]): + +def isInFaces(face, Faces): + + if Faces == []: return False - vector_nulo=FreeCAD.Vector(0,0,0) - surface=face.Surface - kind_surf=str(face.Surface) - if kind_surf=='': - Axis=surface.Axis - Position=surface.Position - - elif kind_surf=='': - Axis=surface.Axis - Radius=surface.Radius - Center=surface.Center - - elif kind_surf=='': - Axis=surface.Axis - Apex=surface.Apex - SemiAngle=surface.SemiAngle - - elif kind_surf[0:6] == 'Sphere': - Center=surface.Center - Radius=surface.Radius - - elif kind_surf=='': - Axis =surface.Axis - Center =surface.Center - MajorRadius =surface.MajorRadius - MinorRadius =surface.MinorRadius - + vector_nulo = FreeCAD.Vector(0, 0, 0) + surface = face.Surface + kind_surf = str(face.Surface) + if kind_surf == "": + Axis = surface.Axis + Position = surface.Position + + elif kind_surf == "": + Axis = surface.Axis + Radius = surface.Radius + Center = surface.Center + + elif kind_surf == "": + Axis = surface.Axis + Apex = surface.Apex + SemiAngle = surface.SemiAngle + + elif kind_surf[0:6] == "Sphere": + Center = surface.Center + Radius = surface.Radius + + elif kind_surf == "": + Axis = surface.Axis + Center = surface.Center + MajorRadius = surface.MajorRadius + MinorRadius = surface.MinorRadius + for elem in Faces: - surf=elem.Surface + surf = elem.Surface ##print surf - if (str(surf) == '' and kind_surf == ''): - vector_cross=Axis.cross(surf.Axis) - if (vector_cross == vector_nulo and isInPlane(Position,surf)): + if str(surf) == "" and kind_surf == "": + vector_cross = Axis.cross(surf.Axis) + if vector_cross == vector_nulo and isInPlane(Position, surf): return True - elif (str(surf) == '' and kind_surf == ''): + elif str(surf) == "" and kind_surf == "": dir = surf.Axis rad = surf.Radius pnt = surf.Center - vector_cross=Axis.cross(surf.Axis) - if (vector_cross == vector_nulo and Radius == rad and isInLine(Center,dir,pnt)): + vector_cross = Axis.cross(surf.Axis) + if ( + vector_cross == vector_nulo + and Radius == rad + and isInLine(Center, dir, pnt) + ): return True - elif (str(surf) == '' and kind_surf ==''): + elif str(surf) == "" and kind_surf == "": # corresponding logic for cone dir = surf.Axis punta = surf.Apex - semiangle=surf.SemiAngle - if (Axis.isEqual(dir,1e-5) and Apex.isEqual(punta,1e-5) and (SemiAngle-semiangle)<1e-6): + semiangle = surf.SemiAngle + if ( + Axis.isEqual(dir, 1e-5) + and Apex.isEqual(punta, 1e-5) + and (SemiAngle - semiangle) < 1e-6 + ): return True - elif (str(surf)[0:6] == 'Sphere' and kind_surf[0:6] == 'Sphere'): + elif str(surf)[0:6] == "Sphere" and kind_surf[0:6] == "Sphere": # corresponding logic for sphere rad = surf.Radius pnt = surf.Center - if (Center == pnt and Radius == rad): + if Center == pnt and Radius == rad: return True - elif (str(surf) == '' and kind_surf ==''): + elif str(surf) == "" and kind_surf == "": # corresponding logic for Torus radMaj = surf.MajorRadius radMin = surf.MinorRadius - pnt = surf.Center - dir = surf.Axis - if (Axis.isEqual(dir,1e-5) and Center.isEqual(pnt,1e-5) and - (MajorRadius-radMaj)<1e-6) and(MinorRadius-radMin)<1e-6 : + pnt = surf.Center + dir = surf.Axis + if ( + Axis.isEqual(dir, 1e-5) + and Center.isEqual(pnt, 1e-5) + and (MajorRadius - radMaj) < 1e-6 + ) and (MinorRadius - radMin) < 1e-6: return True - + return False -def isInFaces2(face,Faces): - if (Faces==[]): +def isInFaces2(face, Faces): + + if Faces == []: return False - vector_nulo=FreeCAD.Vector(0,0,0) - surface=face - kind_surf=face.type - if kind_surf=='': - Axis=surface.Axis - Position=surface.Position - - elif kind_surf=='': - Axis=surface.Axis - Radius=surface.Radius - Center=surface.Center - - elif kind_surf=='': - Axis=surface.Axis - Apex=surface.Apex - SemiAngle=surface.SemiAngle - - elif kind_surf[0:6] == 'Sphere': - Center=surface.Center - Radius=surface.Radius - - elif kind_surf=='': - Axis =surface.Axis - Center =surface.Center - MajorRadius =surface.MajorRadius - MinorRadius =surface.MinorRadius - + vector_nulo = FreeCAD.Vector(0, 0, 0) + surface = face + kind_surf = face.type + if kind_surf == "": + Axis = surface.Axis + Position = surface.Position + + elif kind_surf == "": + Axis = surface.Axis + Radius = surface.Radius + Center = surface.Center + + elif kind_surf == "": + Axis = surface.Axis + Apex = surface.Apex + SemiAngle = surface.SemiAngle + + elif kind_surf[0:6] == "Sphere": + Center = surface.Center + Radius = surface.Radius + + elif kind_surf == "": + Axis = surface.Axis + Center = surface.Center + MajorRadius = surface.MajorRadius + MinorRadius = surface.MinorRadius + for elem in Faces: ##print surf - if (elem.type == '' and kind_surf == ''): - vector_cross=Axis.cross(elem.Axis) - if (vector_cross == vector_nulo and isInPlane(Position,elem.Surface)): - #if (isParallel(elem.Axis,elem.Surface.Axis) and isInPlane(Position,elem.Surface)): + if elem.type == "" and kind_surf == "": + vector_cross = Axis.cross(elem.Axis) + if vector_cross == vector_nulo and isInPlane(Position, elem.Surface): + # if (isParallel(elem.Axis,elem.Surface.Axis) and isInPlane(Position,elem.Surface)): return True - elif (elem.type == '' and kind_surf == ''): + elif elem.type == "" and kind_surf == "": dir = elem.Axis rad = elem.Radius pnt = elem.Center - vector_cross=Axis.cross(elem.Axis) - if (vector_cross == vector_nulo and Radius == rad and isInLine(Center,dir,pnt)): + vector_cross = Axis.cross(elem.Axis) + if ( + vector_cross == vector_nulo + and Radius == rad + and isInLine(Center, dir, pnt) + ): return True - elif (elem.type == '' and kind_surf ==''): + elif elem.type == "" and kind_surf == "": # corresponding logic for cone dir = elem.Axis punta = elem.Apex - semiangle=elem.SemiAngle - if (Axis.isEqual(dir,1e-5) and Apex.isEqual(punta,1e-5) and (SemiAngle-semiangle)<1e-6): + semiangle = elem.SemiAngle + if ( + Axis.isEqual(dir, 1e-5) + and Apex.isEqual(punta, 1e-5) + and (SemiAngle - semiangle) < 1e-6 + ): return True - elif (elem.type == 'Sphere' and kind_surf == 'Sphere'): + elif elem.type == "Sphere" and kind_surf == "Sphere": # corresponding logic for sphere rad = elem.Radius pnt = elem.Center - if (Center == pnt and Radius == rad): + if Center == pnt and Radius == rad: return True - elif (elem.type == '' and kind_surf ==''): + elif elem.type == "" and kind_surf == "": # corresponding logic for Torus radMaj = elem.MajorRadius radMin = elem.MinorRadius - pnt = elem.Center - dir = elem.Axis - if (Axis.isEqual(dir,1e-5) and Center.isEqual(pnt,1e-5) and - (MajorRadius-radMaj)<1e-6) and(MinorRadius-radMin)<1e-6 : - return True + pnt = elem.Center + dir = elem.Axis + if ( + Axis.isEqual(dir, 1e-5) + and Center.isEqual(pnt, 1e-5) + and (MajorRadius - radMaj) < 1e-6 + ) and (MinorRadius - radMin) < 1e-6: + return True return False - diff --git a/src/geouned/GEOUNED/Utils/BooleanSolids.py b/src/geouned/GEOUNED/Utils/BooleanSolids.py index 60ab1380..3fb4735e 100644 --- a/src/geouned/GEOUNED/Utils/BooleanSolids.py +++ b/src/geouned/GEOUNED/Utils/BooleanSolids.py @@ -1,5 +1,5 @@ # -# Conversion to MCNP v0.0 +# Conversion to MCNP v0.0 # Only one solid and planar surfaces # import math @@ -10,543 +10,592 @@ from ..Utils.Functions import GEOUNED_Surface, splitBOP from ..Utils.Options.Classes import Options as opt -BoolVals = (None,True,False) +BoolVals = (None, True, False) + class CTelement: - def __init__(self,val=None,S1=None,S2=None): - self.diagonal = False - self.S1 = S1 - self.S2 = S2 - if val is None : - self.val = None - else: - if type(val) is int : - self.diagonal = True - self.type = None - else: - self.type = val.count(0) - self.val = val - - def getTranspose(self): - if self.diagonal : return self.val - return CTelement((self.val[0],self.val[3],self.val[2],self.val[1]),self.S2,self.S1) - - def getDependence(self): - if self.diagonal : - if self.val == 0 : return True,False - elif self.val == -1 : return 'Null',False - else : return True,'Null' - - Ones = sum(self.val) - if Ones == 4 : return None,None - elif Ones == 3 : - ind = self.val.index(0) - if ind == 0 : return False,None - elif ind == 1 : return True ,None - elif ind == 2 : return None ,True - else : return None ,False - elif Ones == 2 : - ind1 = self.val.index(0) - ind2 = self.val.index(0,ind1+1) - if ind1 == 0 and ind2 == 1 : return 'Null',None - elif ind1 == 2 and ind2 == 3 : return None ,'Null' - elif ind1 == 0 and ind2 == 3 : return False,False - else : return True ,True - elif Ones == 1 : - ind = self.val.index(1) - if ind == 0 : return True ,'Null' - elif ind == 1 : return False,'Null' - elif ind == 2 : return 'Null',False - else : return 'Null',True - else: - return 'Null','Null' - + def __init__(self, val=None, S1=None, S2=None): + self.diagonal = False + self.S1 = S1 + self.S2 = S2 + if val is None: + self.val = None + else: + if type(val) is int: + self.diagonal = True + self.type = None + else: + self.type = val.count(0) + self.val = val + + def getTranspose(self): + if self.diagonal: + return self.val + return CTelement( + (self.val[0], self.val[3], self.val[2], self.val[1]), self.S2, self.S1 + ) + + def getDependence(self): + if self.diagonal: + if self.val == 0: + return True, False + elif self.val == -1: + return "Null", False + else: + return True, "Null" + + Ones = sum(self.val) + if Ones == 4: + return None, None + elif Ones == 3: + ind = self.val.index(0) + if ind == 0: + return False, None + elif ind == 1: + return True, None + elif ind == 2: + return None, True + else: + return None, False + elif Ones == 2: + ind1 = self.val.index(0) + ind2 = self.val.index(0, ind1 + 1) + if ind1 == 0 and ind2 == 1: + return "Null", None + elif ind1 == 2 and ind2 == 3: + return None, "Null" + elif ind1 == 0 and ind2 == 3: + return False, False + else: + return True, True + elif Ones == 1: + ind = self.val.index(1) + if ind == 0: + return True, "Null" + elif ind == 1: + return False, "Null" + elif ind == 2: + return "Null", False + else: + return "Null", True + else: + return "Null", "Null" + class ConstraintTable(dict): - def __init__(self): - self.diagonal = None - - def __str__(self): - - varName = list(self.keys()) - - # Constraint Table only diagonal terms - if len(self[varName[0]]) == 1 : - line = '' - for name in varName : - element = self[name][name] - line += ' {:4d} : {}\n'.format(name,element.val) - return line - - outstr = ' ' - for name in varName : - outstr = outstr + ' {:3d}'.format(name) - outstr = outstr + '\n' - - for name1 in varName : - line = ' {:3d} '.format(name1) - linenot = '~{:3d} '.format(name1) - for name2 in varName: - elmt = self[name1][name2] - if elmt.diagonal : - line += ' {:>2d} '.format(elmt.val) - linenot += ' ' - else: - line += ' {}{} '.format(elmt.val[0],elmt.val[1]) - linenot += ' {}{} '.format(elmt.val[3],elmt.val[2]) - outstr += line +'\n' - outstr += linenot+'\n' - return outstr - - def addElement(self,k1,k2,val): - - if k1 in self.keys(): - self[k1][k2] = val - else: - self[k1] = {k2:val} - - def fillMissingElements(self): - keys = list(self.keys()) - missing = [] - for i,k1 in enumerate(keys): - for k2 in keys[i+1:]: - if k2 in self[k1].keys(): - elmt = self[k1][k2] - self[k2][k1] = elmt.getTranspose() - else: - missing.append((k1,k2)) - - - for k1,k2 in missing: - diag1 = self[k1][k1] - diag2 = self[k2][k2] - new = combineDiagElements (diag1,diag2) - new.S1 = k1 - new.S2 = k2 - self[k1][k2] = new - self[k2][k1] = new.getTranspose() - - def getOutSurfaces(self): - out = [] - for k in self.keys(): - if self[k][k].val != 0 : out.append(k) - return out - - def getConstraintSet(self,valname): - trueSet = {} - falseSet = {} - TNull = False - FNull = False - for k in self.keys(): - TValue,FValue = self[valname][k].getDependence() - if TValue == 'Null' : - TNull = True - TValue = None - if FValue == 'Null' : - FNull = True - FValue = None - if TValue is not None : trueSet[k] = TValue - if FValue is not None : falseSet[k] = FValue - - if TNull : trueSet = None - if FNull : falseSet = None - return trueSet,falseSet - - def solidInBox(self,Seq): # Sequence of the cell - surfs = tuple(Seq.getSurfacesNumbers()) - if self.diagonal : - seqValues = dict() - for s in surfs : - val = BoolVals[self[s][s].val] - if val is not None : seqValues[s] = val - # if evaluate None : Box intersection Cell != 0 Part of the cell in the box - # True : Box intersection Cell == Box Cell cover the full region of the box. Void cell doesn't exist - # False : Box intersection Cell == 0 Cell out of the box - res = Seq.evaluate(seqValues) - return res if type(res) is bool else None - - else: - trueSet,falseSet = self.getConstraintSet(surfs[0]) - if trueSet is not None: - trueVal = Seq.evaluate(trueSet) - trueVal = trueVal if type(trueVal) is bool else None - if trueVal is None : return None - if falseSet is not None: - falseVal = Seq.evaluate(falseSet) - falseVal = falseVal if type(falseVal) is bool else None - if falseVal is None : return None # Part of the cell in the box - if trueVal == falseVal : return trueVal # True Cover full cell, False not in the box - else : return None # Part of the cell in the box - else: - return trueVal - elif falseSet is not None: - falseVal = Seq.evaluate(falseSet) - return falseVal if type(falseVal) is bool else None - else: - print('Bad trouble surfaces {} is on none side of the box!!') - return False - - -def combineDiagElements(d1,d2): - - if d1.val == 0 and d2.val == 0 : return CTelement((1,1,1,1)) - elif d1.val == 1 and d2.val == 0 : return CTelement((1,1,0,0)) - elif d1.val ==-1 and d2.val == 0 : return CTelement((0,0,1,1)) - elif d1.val == 0 and d2.val == 1 : return CTelement((1,0,0,1)) - elif d1.val == 0 and d2.val ==-1 : return CTelement((0,1,1,0)) - elif d1.val == 1 and d2.val == 1 : return CTelement((1,0,0,0)) - elif d1.val == 1 and d2.val ==-1 : return CTelement((0,1,0,0)) - elif d1.val ==-1 and d2.val == 1 : return CTelement((0,0,0,1)) - elif d1.val ==-1 and d2.val ==-1 : return CTelement((0,0,1,0)) - -def buildCTableFromSolids(Box,SurfInfo,option='diag'): - - if type(SurfInfo) is dict : - surfaces = SurfInfo - surfaceList = tuple(surfaces.keys()) - elif type(SurfInfo) is tuple : - surfaceList,surfaces = SurfInfo - else: - surfaces = SurfInfo.Surfaces - surfaceList = SurfInfo.surfaceList - - outSurfaces=[] - if type(surfaces[surfaceList[0]]) is GEOUNED_Surface : - for s in surfaceList: - ss = surfaces[s] - ss.__boundBox__ = Box.BoundBox - ss.buildSurface() - else: - for s in surfaceList: surfaces[s].buildShape(Box.BoundBox) - - CTable = ConstraintTable() - if option == 'diag': + def __init__(self): + self.diagonal = None + + def __str__(self): + + varName = list(self.keys()) + + # Constraint Table only diagonal terms + if len(self[varName[0]]) == 1: + line = "" + for name in varName: + element = self[name][name] + line += " {:4d} : {}\n".format(name, element.val) + return line + + outstr = " " + for name in varName: + outstr = outstr + " {:3d}".format(name) + outstr = outstr + "\n" + + for name1 in varName: + line = " {:3d} ".format(name1) + linenot = "~{:3d} ".format(name1) + for name2 in varName: + elmt = self[name1][name2] + if elmt.diagonal: + line += " {:>2d} ".format(elmt.val) + linenot += " " + else: + line += " {}{} ".format(elmt.val[0], elmt.val[1]) + linenot += " {}{} ".format(elmt.val[3], elmt.val[2]) + outstr += line + "\n" + outstr += linenot + "\n" + return outstr + + def addElement(self, k1, k2, val): + + if k1 in self.keys(): + self[k1][k2] = val + else: + self[k1] = {k2: val} + + def fillMissingElements(self): + keys = list(self.keys()) + missing = [] + for i, k1 in enumerate(keys): + for k2 in keys[i + 1 :]: + if k2 in self[k1].keys(): + elmt = self[k1][k2] + self[k2][k1] = elmt.getTranspose() + else: + missing.append((k1, k2)) + + for k1, k2 in missing: + diag1 = self[k1][k1] + diag2 = self[k2][k2] + new = combineDiagElements(diag1, diag2) + new.S1 = k1 + new.S2 = k2 + self[k1][k2] = new + self[k2][k1] = new.getTranspose() + + def getOutSurfaces(self): + out = [] + for k in self.keys(): + if self[k][k].val != 0: + out.append(k) + return out + + def getConstraintSet(self, valname): + trueSet = {} + falseSet = {} + TNull = False + FNull = False + for k in self.keys(): + TValue, FValue = self[valname][k].getDependence() + if TValue == "Null": + TNull = True + TValue = None + if FValue == "Null": + FNull = True + FValue = None + if TValue is not None: + trueSet[k] = TValue + if FValue is not None: + falseSet[k] = FValue + + if TNull: + trueSet = None + if FNull: + falseSet = None + return trueSet, falseSet + + def solidInBox(self, Seq): # Sequence of the cell + surfs = tuple(Seq.getSurfacesNumbers()) + if self.diagonal: + seqValues = dict() + for s in surfs: + val = BoolVals[self[s][s].val] + if val is not None: + seqValues[s] = val + # if evaluate None : Box intersection Cell != 0 Part of the cell in the box + # True : Box intersection Cell == Box Cell cover the full region of the box. Void cell doesn't exist + # False : Box intersection Cell == 0 Cell out of the box + res = Seq.evaluate(seqValues) + return res if type(res) is bool else None + + else: + trueSet, falseSet = self.getConstraintSet(surfs[0]) + if trueSet is not None: + trueVal = Seq.evaluate(trueSet) + trueVal = trueVal if type(trueVal) is bool else None + if trueVal is None: + return None + if falseSet is not None: + falseVal = Seq.evaluate(falseSet) + falseVal = falseVal if type(falseVal) is bool else None + if falseVal is None: + return None # Part of the cell in the box + if trueVal == falseVal: + return trueVal # True Cover full cell, False not in the box + else: + return None # Part of the cell in the box + else: + return trueVal + elif falseSet is not None: + falseVal = Seq.evaluate(falseSet) + return falseVal if type(falseVal) is bool else None + else: + print("Bad trouble surfaces {} is on none side of the box!!") + return False + + +def combineDiagElements(d1, d2): + + if d1.val == 0 and d2.val == 0: + return CTelement((1, 1, 1, 1)) + elif d1.val == 1 and d2.val == 0: + return CTelement((1, 1, 0, 0)) + elif d1.val == -1 and d2.val == 0: + return CTelement((0, 0, 1, 1)) + elif d1.val == 0 and d2.val == 1: + return CTelement((1, 0, 0, 1)) + elif d1.val == 0 and d2.val == -1: + return CTelement((0, 1, 1, 0)) + elif d1.val == 1 and d2.val == 1: + return CTelement((1, 0, 0, 0)) + elif d1.val == 1 and d2.val == -1: + return CTelement((0, 1, 0, 0)) + elif d1.val == -1 and d2.val == 1: + return CTelement((0, 0, 0, 1)) + elif d1.val == -1 and d2.val == -1: + return CTelement((0, 0, 1, 0)) + + +def buildCTableFromSolids(Box, SurfInfo, option="diag"): + + if type(SurfInfo) is dict: + surfaces = SurfInfo + surfaceList = tuple(surfaces.keys()) + elif type(SurfInfo) is tuple: + surfaceList, surfaces = SurfInfo + else: + surfaces = SurfInfo.Surfaces + surfaceList = SurfInfo.surfaceList + + outSurfaces = [] + if type(surfaces[surfaceList[0]]) is GEOUNED_Surface: + for s in surfaceList: + ss = surfaces[s] + ss.__boundBox__ = Box.BoundBox + ss.buildSurface() + else: + for s in surfaceList: + surfaces[s].buildShape(Box.BoundBox) + + CTable = ConstraintTable() + if option == "diag": CTable.diagonal = True - else: + else: CTable.diagonal = False - for i,s1 in enumerate(surfaceList): - res,splitRegions = splitSolid_fast(Box,surfaces[s1],True) - #res,splitRegions = splitSolid_fast(Box,Surfaces.getSurface(s1),True) - - CTable.addElement(s1,s1,CTelement(res,s1,s1)) - if option == 'diag' :continue - if splitRegions is None : continue # loop, no region to be split by s2 - for j,s2 in enumerate(surfaceList[i+1:]) : - posS1,negS1 = splitRegions + for i, s1 in enumerate(surfaceList): + res, splitRegions = splitSolid_fast(Box, surfaces[s1], True) + # res,splitRegions = splitSolid_fast(Box,Surfaces.getSurface(s1),True) + + CTable.addElement(s1, s1, CTelement(res, s1, s1)) + if option == "diag": + continue + if splitRegions is None: + continue # loop, no region to be split by s2 + for j, s2 in enumerate(surfaceList[i + 1 :]): + posS1, negS1 = splitRegions pos0 = None - for solid in posS1 : - - pos = splitSolid_fast(solid,surfaces[s2],False) - - #pos = splitSolid_fast(solid,Surfaces.getSurface(s2),False) - if pos == (1,1) : break # s2 intersect S1 Region - if pos0 is None : - pos0 = pos + for solid in posS1: + + pos = splitSolid_fast(solid, surfaces[s2], False) + + # pos = splitSolid_fast(solid,Surfaces.getSurface(s2),False) + if pos == (1, 1): + break # s2 intersect S1 Region + if pos0 is None: + pos0 = pos else: - if pos != pos0 : # s1 regions are on both side of s2 - pos = (1,1) - break - + if pos != pos0: # s1 regions are on both side of s2 + pos = (1, 1) + break + neg0 = None - for solid in negS1 : - #neg = splitSolid_fast(solid,Surfaces.getSurface(s2),False) - neg = splitSolid_fast(solid,surfaces[s2],False) - if neg == (1,1) : break # s2 intersect S1 Region - if neg0 is None : - neg0 = neg + for solid in negS1: + # neg = splitSolid_fast(solid,Surfaces.getSurface(s2),False) + neg = splitSolid_fast(solid, surfaces[s2], False) + if neg == (1, 1): + break # s2 intersect S1 Region + if neg0 is None: + neg0 = neg else: - if neg != neg0 : # s1 regions are on both side of s2 - neg = (1,1) - break - - val = (pos[0],pos[1],neg[1],neg[0]) - CTable.addElement(s1,s2,CTelement(val,s1,s2)) + if neg != neg0: # s1 regions are on both side of s2 + neg = (1, 1) + break + val = (pos[0], pos[1], neg[1], neg[0]) + CTable.addElement(s1, s2, CTelement(val, s1, s2)) - # if some surfaces don't cross the box some elements in Constraint table are not filled - if option != 'diag' : CTable.fillMissingElements() - return CTable + # if some surfaces don't cross the box some elements in Constraint table are not filled + if option != "diag": + CTable.fillMissingElements() + return CTable -def removeExtraSurfaces(CellSeq,CTable): +def removeExtraSurfaces(CellSeq, CTable): # checking is make on solid cell definition to be removed from void cell outSurfaces = set(CTable.getOutSurfaces()) changed = False - newDef = BoolSequence(operator='OR') - - #Loop over all compound solids of the metaSolid + newDef = BoolSequence(operator="OR") - if CellSeq.level == 0 and len(CellSeq.elements) == 1 : - return CellSeq + # Loop over all compound solids of the metaSolid - if CellSeq.operator == 'AND' : - newSeq = BoolSequence(operator='AND') + if CellSeq.level == 0 and len(CellSeq.elements) == 1: + return CellSeq + + if CellSeq.operator == "AND": + newSeq = BoolSequence(operator="AND") newSeq.append(CellSeq.copy()) CellSeq.assign(newSeq) - - + for subCell in CellSeq.elements: - nullcell = False + nullcell = False subCell.check() - if type(subCell.elements) is bool : - chk = not subCell.elements + if type(subCell.elements) is bool: + chk = not subCell.elements else: - chk = None - - if chk == False : # the cell doesn't exist - nullcell = True - elif chk == True : # the cell describe the full universe - newDef.elements = True - newDef.level = -1 - return newDef - - #if subcell has finite volume check it intersection with the box - if not nullcell : - res = CTable.solidInBox(subCell) - if res == None : + chk = None + + if chk == False: # the cell doesn't exist + nullcell = True + elif chk == True: # the cell describe the full universe + newDef.elements = True + newDef.level = -1 + return newDef + + # if subcell has finite volume check it intersection with the box + if not nullcell: + res = CTable.solidInBox(subCell) + if res == None: # subcell intersect the box # get the surfaces of the solids out of the box # get reduced definition # if subcell lev!= 0 remove surface operation is not valid - if subCell.level == 0 : - removeSurf = outSurfaces & subCell.getSurfacesNumbers() - for s in removeSurf: - val = True if CTable[s][s].val > 0 else False - subCell.substitute(s,val) - - if type(subCell.elements) is bool : - if subCell.elements == False : # cell does not intersect void box - continue - else: # cell cover fully void box - newDef.elements = True - newDef.level = -1 - return newDef + if subCell.level == 0: + removeSurf = outSurfaces & subCell.getSurfacesNumbers() + for s in removeSurf: + val = True if CTable[s][s].val > 0 else False + subCell.substitute(s, val) + + if type(subCell.elements) is bool: + if subCell.elements == False: # cell does not intersect void box + continue + else: # cell cover fully void box + newDef.elements = True + newDef.level = -1 + return newDef else: - newDef.append(subCell) + newDef.append(subCell) - elif res == True : - # subcell cover the full box region Void cell doesn't exist - newDef.elements = True - newDef.level = -1 - return newDef + elif res == True: + # subcell cover the full box region Void cell doesn't exist + newDef.elements = True + newDef.level = -1 + return newDef newDef.clean() - return newDef - - -def splitSolid_fast(solid,surf,box): - - if box : - if surf.shape : - comsolid = splitBOP(solid,[surf.shape],opt.splitTolerance) - else: - return checkSign(solid,surf),None - - if len(comsolid.Solids) <= 1 : - return checkSign(solid,surf),None - # sgn = checkSign(solid,surf) # if "box" and single object => the box is not split, surface s1 out of the box. - # if sgn == 1 : # The sign is the side of surface s1 where the box is located - # # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 - # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 - # else: - # return ((0,0),(0,1)),None - - else: - posSol = [] - negSol = [] - for s in comsolid.Solids: - sgn = checkSign(s,surf) - if sgn == 1: - posSol.append(s) - else: - negSol.append(s) - return 0, (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 - #return ((1,0),(0,1)), (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 + return newDef + + +def splitSolid_fast(solid, surf, box): + + if box: + if surf.shape: + comsolid = splitBOP(solid, [surf.shape], opt.splitTolerance) + else: + return checkSign(solid, surf), None + + if len(comsolid.Solids) <= 1: + return checkSign(solid, surf), None + # sgn = checkSign(solid,surf) # if "box" and single object => the box is not split, surface s1 out of the box. + # if sgn == 1 : # The sign is the side of surface s1 where the box is located + # # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 + # return ((1,0),(0,0)),None # return the diagonal element of the Constraint Table for s1 + # else: + # return ((0,0),(0,1)),None + + else: + posSol = [] + negSol = [] + for s in comsolid.Solids: + sgn = checkSign(s, surf) + if sgn == 1: + posSol.append(s) + else: + negSol.append(s) + return 0, ( + posSol, + negSol, + ) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 + # return ((1,0),(0,1)), (posSol,negSol) # return the diagonal element of the Constraint Table for s1, and solids to be split by s2 else: - # "not box" => return the position of the +/- region of s1 (the solid) with respect s2 - if surf.shape : - dist = solid.distToShape(surf.shape)[0] - else: - dist = 1. - if dist > 1e-6 : # face doesn't intersect solid - sgn = checkSign(solid,surf) - if sgn == 1: - return (1,0) # values of s2 and -s2 "0" means this region doesn't exist - else: - return (0,1) - else: - return (1,1) # values of s2 and -s2 - - - - + # "not box" => return the position of the +/- region of s1 (the solid) with respect s2 + if surf.shape: + dist = solid.distToShape(surf.shape)[0] + else: + dist = 1.0 + if dist > 1e-6: # face doesn't intersect solid + sgn = checkSign(solid, surf) + if sgn == 1: + return ( + 1, + 0, + ) # values of s2 and -s2 "0" means this region doesn't exist + else: + return (0, 1) + else: + return (1, 1) # values of s2 and -s2 + + # find one point inside a solid (region) def point_inside(solid): - point = solid.CenterOfMass - if solid.isInside(point,0.0,False) : return point + point = solid.CenterOfMass + if solid.isInside(point, 0.0, False): + return point + + cut_line = 32 + cut_box = 2 - cut_line = 32 - cut_box = 2 + v1 = solid.Vertexes[0].Point + for vi in range(len(solid.Vertexes) - 1, 0, -1): + v2 = solid.Vertexes[vi].Point + dv = (v2 - v1) * 0.5 - v1=solid.Vertexes[0].Point - for vi in range(len(solid.Vertexes)-1,0,-1): - v2=solid.Vertexes[vi].Point - dv= (v2-v1)*0.5 - - n=1 + n = 1 while True: - for i in range(n): - point = v1 + dv *(1 + 0.5*i) - if solid.isInside(point,0.0,False) : return point - n=n*2 - dv=dv*0.5 - if (n > cut_line ) : - break - - BBox = solid.optimalBoundingBox(False) - box = [BBox.XMin,BBox.XMax, - BBox.YMin,BBox.YMax, - BBox.ZMin,BBox.ZMax ] - - boxes,centers = CutBox(box) - n = 0 - - while True : - for p in centers : - pp = FreeCAD.Vector(p[0],p[1],p[2]) - if solid.isInside(pp,0.0,False) : return pp - - subbox = [] - centers = [] - for b in boxes : - btab,ctab = CutBox(b) + for i in range(n): + point = v1 + dv * (1 + 0.5 * i) + if solid.isInside(point, 0.0, False): + return point + n = n * 2 + dv = dv * 0.5 + if n > cut_line: + break + + BBox = solid.optimalBoundingBox(False) + box = [BBox.XMin, BBox.XMax, BBox.YMin, BBox.YMax, BBox.ZMin, BBox.ZMax] + + boxes, centers = CutBox(box) + n = 0 + + while True: + for p in centers: + pp = FreeCAD.Vector(p[0], p[1], p[2]) + if solid.isInside(pp, 0.0, False): + return pp + + subbox = [] + centers = [] + for b in boxes: + btab, ctab = CutBox(b) subbox.extend(btab) centers.extend(ctab) - boxes = subbox - n = n + 1 + boxes = subbox + n = n + 1 - if (n == cut_box ) : - break + if n == cut_box: + break - return pointFromSurface(solid) + return pointFromSurface(solid) def pointFromSurface(solid): - + for face in solid.Faces: - parameters = face.ParameterRange - u = (parameters[0]+parameters[1])/2 - v = (parameters[2]+parameters[3])/2 - pface = face.valueAt(u,v) - normal= face.normalAt(u,v) - - d = 10 - pp = pface + d*normal - while d > 1e-8: - if solid.isInside(pp,0.0,False) : return pp - d *= 0.5 - pp = pface + d*normal - - normal = -normal - d = 10 - pp = pface + d*normal - while d > 1e-8: - if solid.isInside(pp,0.0,False) : return pp - d *= 0.5 - pp = pface + d*normal - - print('Solid not found in bounding Box (Volume : {})'.format(solid.Volume)) + parameters = face.ParameterRange + u = (parameters[0] + parameters[1]) / 2 + v = (parameters[2] + parameters[3]) / 2 + pface = face.valueAt(u, v) + normal = face.normalAt(u, v) + + d = 10 + pp = pface + d * normal + while d > 1e-8: + if solid.isInside(pp, 0.0, False): + return pp + d *= 0.5 + pp = pface + d * normal + + normal = -normal + d = 10 + pp = pface + d * normal + while d > 1e-8: + if solid.isInside(pp, 0.0, False): + return pp + d *= 0.5 + pp = pface + d * normal + + print("Solid not found in bounding Box (Volume : {})".format(solid.Volume)) return None + # divide a box into 8 smaller boxes def CutBox(Box): - xmid = (Box[1]+Box[0])*0.5 - ymid = (Box[3]+Box[2])*0.5 - zmid = (Box[5]+Box[4])*0.5 - - - b1 = (Box[0],xmid,Box[2],ymid,Box[4],zmid) - p1 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b2 = (xmid,Box[1],Box[2],ymid,Box[4],zmid) - p2 = (0.5*(xmid+Box[1]), 0.5*(Box[2]+ymid), 0.5*(Box[4]+zmid)) - - b3 = (Box[0],xmid,ymid,Box[3],Box[4],zmid) - p3 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b4 = (xmid,Box[1],ymid,Box[3],Box[4],zmid) - p4 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(Box[4]+zmid)) - - b5 = (Box[0],xmid,Box[2],ymid,zmid,Box[5]) - p5 = (0.5*(Box[0]+xmid),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b6 = (xmid,Box[1],Box[2],ymid,zmid,Box[5]) - p6 = (0.5*(xmid+Box[1]),0.5*(Box[2]+ymid),0.5*(zmid+Box[5])) - - b7 = (Box[0],xmid,ymid,Box[3],zmid,Box[5]) - p7 = (0.5*(Box[0]+xmid),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - b8 = (xmid,Box[1],ymid,Box[3],zmid,Box[5]) - p8 = (0.5*(xmid+Box[1]),0.5*(ymid+Box[3]),0.5*(zmid+Box[5])) - - return (b1,b2,b3,b4,b5,b6,b7,b8),(p1,p2,p3,p4,p5,p6,p7,p8) - - -def checkSign(solid,surf): - - point = point_inside(solid) - - if surf.Type == 'Plane': - r = point - surf.Surf.Position - if surf.Surf.Axis.dot(r) > 0 : - return 1 - else: - return -1 - - elif surf.Type == 'Cylinder': - r = point - surf.Surf.Center - L2 = r.Length*r.Length - z = surf.Surf.Axis.dot(r) - z2 = z*z - R2 = surf.Surf.Radius*surf.Surf.Radius - if L2-z2 > R2 : - return 1 - else: - return -1 - - elif surf.Type == 'Sphere': - r = point - surf.Surf.Center - if r.Length > surf.Surf.Radius : - return 1 - else: - return -1 - - elif surf.Type == 'Cone': - r = point - surf.Surf.Apex - r.normalize() - z = round(surf.Surf.Axis.dot(r),15) - alpha = math.acos(z) - - if alpha > surf.Surf.SemiAngle : - return 1 - else: - return -1 - - elif surf.Type == 'Torus': - r = point - surf.Surf.Center - h = r.dot(surf.Surf.Axis) - rho = r - h * surf.Surf.Axis - - rp = math.sqrt((rho.Length - surf.Surf.MajorRadius)**2 + h**2) - if rp > surf.Surf.MinorRadius: - return 1 - else: - return -1 + xmid = (Box[1] + Box[0]) * 0.5 + ymid = (Box[3] + Box[2]) * 0.5 + zmid = (Box[5] + Box[4]) * 0.5 + + b1 = (Box[0], xmid, Box[2], ymid, Box[4], zmid) + p1 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b2 = (xmid, Box[1], Box[2], ymid, Box[4], zmid) + p2 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (Box[4] + zmid)) + + b3 = (Box[0], xmid, ymid, Box[3], Box[4], zmid) + p3 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b4 = (xmid, Box[1], ymid, Box[3], Box[4], zmid) + p4 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (Box[4] + zmid)) + + b5 = (Box[0], xmid, Box[2], ymid, zmid, Box[5]) + p5 = (0.5 * (Box[0] + xmid), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b6 = (xmid, Box[1], Box[2], ymid, zmid, Box[5]) + p6 = (0.5 * (xmid + Box[1]), 0.5 * (Box[2] + ymid), 0.5 * (zmid + Box[5])) + + b7 = (Box[0], xmid, ymid, Box[3], zmid, Box[5]) + p7 = (0.5 * (Box[0] + xmid), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + b8 = (xmid, Box[1], ymid, Box[3], zmid, Box[5]) + p8 = (0.5 * (xmid + Box[1]), 0.5 * (ymid + Box[3]), 0.5 * (zmid + Box[5])) + + return (b1, b2, b3, b4, b5, b6, b7, b8), (p1, p2, p3, p4, p5, p6, p7, p8) + + +def checkSign(solid, surf): + + point = point_inside(solid) + + if surf.Type == "Plane": + r = point - surf.Surf.Position + if surf.Surf.Axis.dot(r) > 0: + return 1 + else: + return -1 + + elif surf.Type == "Cylinder": + r = point - surf.Surf.Center + L2 = r.Length * r.Length + z = surf.Surf.Axis.dot(r) + z2 = z * z + R2 = surf.Surf.Radius * surf.Surf.Radius + if L2 - z2 > R2: + return 1 + else: + return -1 + + elif surf.Type == "Sphere": + r = point - surf.Surf.Center + if r.Length > surf.Surf.Radius: + return 1 + else: + return -1 + + elif surf.Type == "Cone": + r = point - surf.Surf.Apex + r.normalize() + z = round(surf.Surf.Axis.dot(r), 15) + alpha = math.acos(z) + + if alpha > surf.Surf.SemiAngle: + return 1 + else: + return -1 + + elif surf.Type == "Torus": + r = point - surf.Surf.Center + h = r.dot(surf.Surf.Axis) + rho = r - h * surf.Surf.Axis + + rp = math.sqrt((rho.Length - surf.Surf.MajorRadius) ** 2 + h**2) + if rp > surf.Surf.MinorRadius: + return 1 + else: + return -1 diff --git a/src/geouned/GEOUNED/Utils/Functions.py b/src/geouned/GEOUNED/Utils/Functions.py index f5a34f63..5c87e7c8 100644 --- a/src/geouned/GEOUNED/Utils/Functions.py +++ b/src/geouned/GEOUNED/Utils/Functions.py @@ -8,582 +8,649 @@ import numpy as np import Part -from ..Utils.BasicFunctions_part1 import (ConeParams, CylinderParams, - Plane3PtsParams, PlaneParams, - SphereParams, TorusParams, - isParallel) +from ..Utils.BasicFunctions_part1 import ( + ConeParams, + CylinderParams, + Plane3PtsParams, + PlaneParams, + SphereParams, + TorusParams, + isParallel, +) from ..Utils.Options.Classes import Options from ..Utils.Options.Classes import Tolerances as tol from . import BasicFunctions_part2 as BF def getBox(comp): - bb=FreeCAD.BoundBox(comp.BoundBox) + bb = FreeCAD.BoundBox(comp.BoundBox) bb.enlarge(Options.enlargeBox) - xMin,yMin,zMin = bb.XMin, bb.YMin, bb.ZMin - xLength,yLength,zLength = bb.XLength, bb.YLength, bb.ZLength - - return Part.makeBox( xLength, yLength, zLength, - FreeCAD.Vector( xMin, yMin, zMin), - FreeCAD.Vector(0,0,1)) - -def makePlane(Plane,Boxin): - - normal = Plane.Surf.Axis - p0 = Plane.Surf.Position.dot(normal) - - Box=FreeCAD.BoundBox(Boxin) - Box.enlarge(10) - - pointEdge=[] - for i in range(12): - edge = Box.getEdge(i) - p1 = normal.dot(edge[0]) - p2 = normal.dot(edge[1]) - d0 = p0 - p1 - d1 = p2 - p1 - if d1 != 0 : - a = d0/d1 - if (a >= 0 and a <= 1): - pointEdge.append(edge[0]+a*(edge[1]-edge[0])) - - if len(pointEdge) == 0 : return - s = FreeCAD.Vector((0,0,0)) - for v in pointEdge : - s = s + v - s = s / len(pointEdge) - - vtxvec = [] - for v in pointEdge : - vtxvec.append(v-s) - - X0 = vtxvec[0] - Y0 = normal.cross(X0) - - orden=[] - for i,v in enumerate(vtxvec): - phi = np.arctan2(v.dot(Y0),v.dot(X0)) - orden.append((phi,i)) - orden.sort() - - return Part.Face( Part.makePolygon([ pointEdge[p[1]] for p in orden ], True)) + xMin, yMin, zMin = bb.XMin, bb.YMin, bb.ZMin + xLength, yLength, zLength = bb.XLength, bb.YLength, bb.ZLength + + return Part.makeBox( + xLength, + yLength, + zLength, + FreeCAD.Vector(xMin, yMin, zMin), + FreeCAD.Vector(0, 0, 1), + ) + + +def makePlane(Plane, Boxin): + + normal = Plane.Surf.Axis + p0 = Plane.Surf.Position.dot(normal) + + Box = FreeCAD.BoundBox(Boxin) + Box.enlarge(10) + + pointEdge = [] + for i in range(12): + edge = Box.getEdge(i) + p1 = normal.dot(edge[0]) + p2 = normal.dot(edge[1]) + d0 = p0 - p1 + d1 = p2 - p1 + if d1 != 0: + a = d0 / d1 + if a >= 0 and a <= 1: + pointEdge.append(edge[0] + a * (edge[1] - edge[0])) + + if len(pointEdge) == 0: + return + s = FreeCAD.Vector((0, 0, 0)) + for v in pointEdge: + s = s + v + s = s / len(pointEdge) + + vtxvec = [] + for v in pointEdge: + vtxvec.append(v - s) + + X0 = vtxvec[0] + Y0 = normal.cross(X0) + + orden = [] + for i, v in enumerate(vtxvec): + phi = np.arctan2(v.dot(Y0), v.dot(X0)) + orden.append((phi, i)) + orden.sort() + + return Part.Face(Part.makePolygon([pointEdge[p[1]] for p in orden], True)) class GEOUNED_Solid: - - def __init__(self,id,comsolid=None): - refine = True - if not comsolid : - self.Solids = None - self.Volume = None - self.BoundBox = None - elif type(comsolid) is list : - self.Solids = comsolid - vol = 0 - self.BoundBox = FreeCAD.BoundBox() - for s in comsolid: - vol += s.Volume - self.BoundBox.add(s.BoundBox) - self.Volume = vol - else: - if refine : - try : - self.Solids = comsolid.removeSplitter().Solids - except : - self.Solids = comsolid.Solids - - for s in self.Solids : - if s.Volume < 0: - s.reverse() - else: - self.Solids = comsolid.Solids - self.Volume = comsolid.Volume - self.BoundBox = comsolid.BoundBox - - self.__id__ = id - self.label = None - self.Definition = [] - self.Faces = [] - self.Comments = '' - self.Density = 0 - self.Dilution = 1 - self.Material = 0 - self.Surfaces = [] - self.Rho = None - self.MatInfo = None - self.CellType = 'solid' #other types : 'void', 'enclosure', 'fill' - self.Universe = 0 - self.Void = False - self.IsEnclosure = False - self.EnclosureID = None - self.ParentEnclosureID = None - self.SonEnclosures = [] - self.EnclosureList = None - self.CADSolid = None - self.UniverseBox = None - self.NullCell = True - - def updateSolids(self,solidList): + + def __init__(self, id, comsolid=None): + refine = True + if not comsolid: + self.Solids = None + self.Volume = None + self.BoundBox = None + elif type(comsolid) is list: + self.Solids = comsolid + vol = 0 + self.BoundBox = FreeCAD.BoundBox() + for s in comsolid: + vol += s.Volume + self.BoundBox.add(s.BoundBox) + self.Volume = vol + else: + if refine: + try: + self.Solids = comsolid.removeSplitter().Solids + except: + self.Solids = comsolid.Solids + + for s in self.Solids: + if s.Volume < 0: + s.reverse() + else: + self.Solids = comsolid.Solids + self.Volume = comsolid.Volume + self.BoundBox = comsolid.BoundBox + + self.__id__ = id + self.label = None + self.Definition = [] + self.Faces = [] + self.Comments = "" + self.Density = 0 + self.Dilution = 1 + self.Material = 0 + self.Surfaces = [] + self.Rho = None + self.MatInfo = None + self.CellType = "solid" # other types : 'void', 'enclosure', 'fill' + self.Universe = 0 + self.Void = False + self.IsEnclosure = False + self.EnclosureID = None + self.ParentEnclosureID = None + self.SonEnclosures = [] + self.EnclosureList = None + self.CADSolid = None + self.UniverseBox = None + self.NullCell = True + + def updateSolids(self, solidList): self.Solids = solidList vol = 0 self.BoundBox = FreeCAD.BoundBox() for s in solidList: - vol += s.Volume - self.BoundBox.add(s.BoundBox) + vol += s.Volume + self.BoundBox.add(s.BoundBox) def setCADSolid(self): self.CADSolid = Part.makeCompound(self.Solids) self.Volume = self.CADSolid.Volume self.BoundBox = self.CADSolid.BoundBox - def setUniverseBox(self,UniverseBox): + def setUniverseBox(self, UniverseBox): self.UniverseBox = UniverseBox - def setSonEnclosures(self,sonEnclosures): - self.SonEnclosures = sonEnclosures + def setSonEnclosures(self, sonEnclosures): + self.SonEnclosures = sonEnclosures + + def setDefinition(self, definition, simplify=False): - def setDefinition(self,definition,simplify=False): + if definition is None: + self.NullCell = True + return - if definition is None: - self.NullCell = True - return + self.NullCell = False + self.Definition = definition - self.NullCell = False - self.Definition = definition - - if not self.Void : - if not self.Definition.elements: - self.NullCell = True - return + if not self.Void: + if not self.Definition.elements: + self.NullCell = True + return - self.Surfaces = tuple(self.Definition.getSurfacesNumbers()) + self.Surfaces = tuple(self.Definition.getSurfacesNumbers()) - - def setFaces(self,faces): + def setFaces(self, faces): self.Faces = faces - def setComments(self,comments): + def setComments(self, comments): self.Comments = comments - def setMaterial(self,material,rho=None,info=None): + def setMaterial(self, material, rho=None, info=None): self.Material = material - self.Rho = rho - self.MatInfo = info - - if rho is not None : - self.Density = self.Dilution * rho + self.Rho = rho + self.MatInfo = info + + if rho is not None: + self.Density = self.Dilution * rho else: - if material != 0 : - self.Density = None - - def setDilution(self,dilution): + if material != 0: + self.Density = None + + def setDilution(self, dilution): self.Dilution = dilution - if self.Rho is not None : - self.Density = self.Rho*dilution + if self.Rho is not None: + self.Density = self.Rho * dilution - - def checkIntersection(self,solid,dtolerance=1.0e-6,vtolerance=1e-10): - """ Check if solid intersect with current solid. + def checkIntersection(self, solid, dtolerance=1.0e-6, vtolerance=1e-10): + """Check if solid intersect with current solid. return : -2 solid fully embedded in self.CADSolid ; -1 self.CADSolid fully embedded in solid ; 0 self.CADSolid intersect solid ; - 1 self.CADSolid and solid fully disjoint """ + 1 self.CADSolid and solid fully disjoint""" dist = 1e12 for sol1 in self.CADSolid.Solids: - for sol2 in solid.Solids : - try : - distShape = sol1.distToShape(sol2)[0] - except : - print('Failed solid1.distToshape(solid2), try with inverted solids') - distShape = sol2.distToShape(sol1)[0] - print('inverted disToShape OK',distShape) - dist = min(dist,distShape) - if dist == 0 : break - - if dist > dtolerance : + for sol2 in solid.Solids: + try: + distShape = sol1.distToShape(sol2)[0] + except: + print("Failed solid1.distToshape(solid2), try with inverted solids") + distShape = sol2.distToShape(sol1)[0] + print("inverted disToShape OK", distShape) + dist = min(dist, distShape) + if dist == 0: + break + + if dist > dtolerance: return 1 common = self.CADSolid.common(solid) - if abs(common.Volume) < vtolerance : + if abs(common.Volume) < vtolerance: return 1 - if abs(self.CADSolid.Volume - common.Volume)/common.Volume < vtolerance : - return -1 - elif abs(solid.Volume - common.Volume)/common.Volume < vtolerance : + if abs(self.CADSolid.Volume - common.Volume) / common.Volume < vtolerance: + return -1 + elif abs(solid.Volume - common.Volume) / common.Volume < vtolerance: return -2 else: return 0 - + class GEOUNED_Surface: - - def __init__(self,params,boundBox,Face=None) : - - self.Index = 0 - self.__boundBox__ = boundBox - if params[0] == 'Plane': - self.Type = 'Plane' - self.Surf = PlaneParams(params[1]) #plane point defined as the shortest distance to origin - elif params[0] == 'Plane3Pts' : - self.Type = 'Plane' - self.Surf = Plane3PtsParams(params[1]) #plane point defined with 3 points - elif params[0] == 'Cylinder' : - self.Type = params[0] - self.Surf = CylinderParams(params[1]) - elif params[0] == 'Cone' : - self.Type = params[0] - self.Surf = ConeParams(params[1]) - elif params[0] == 'Sphere' : - self.Type = params[0] - self.Surf = SphereParams(params[1]) - elif params[0] == 'Torus' : - self.Type = params[0] - self.Surf = TorusParams(params[1]) - - self.shape = Face - - if type(Face) is str : - if Face == 'Build' : self.buildSurface() - - if self.shape == 'Build' : - raise ValueError(f'stop {params} {boundBox}') - return - - + + def __init__(self, params, boundBox, Face=None): + + self.Index = 0 + self.__boundBox__ = boundBox + if params[0] == "Plane": + self.Type = "Plane" + self.Surf = PlaneParams( + params[1] + ) # plane point defined as the shortest distance to origin + elif params[0] == "Plane3Pts": + self.Type = "Plane" + self.Surf = Plane3PtsParams(params[1]) # plane point defined with 3 points + elif params[0] == "Cylinder": + self.Type = params[0] + self.Surf = CylinderParams(params[1]) + elif params[0] == "Cone": + self.Type = params[0] + self.Surf = ConeParams(params[1]) + elif params[0] == "Sphere": + self.Type = params[0] + self.Surf = SphereParams(params[1]) + elif params[0] == "Torus": + self.Type = params[0] + self.Surf = TorusParams(params[1]) + + self.shape = Face + + if type(Face) is str: + if Face == "Build": + self.buildSurface() + + if self.shape == "Build": + raise ValueError(f"stop {params} {boundBox}") + return + def buildSurface(self): - - if self.Type == 'Plane': - - normal = self.Surf.Axis - p0 = normal.dot(self.Surf.Position) - Box = FreeCAD.BoundBox(self.__boundBox__) - Box.enlarge(10) - - pointEdge=[] - for i in range(12): - edge = Box.getEdge(i) - p1 = normal.dot(edge[0]) - p2 = normal.dot(edge[1]) - d0 = p0 - p1 - d1 = p2 - p1 - if d1 != 0 : - a = d0/d1 - if (a >= 0 and a <= 1): - pointEdge.append(edge[0]+a*(edge[1]-edge[0])) - - if len(pointEdge) == 0 : - self.shape = None # Plane does not cross box - return - - s = FreeCAD.Vector((0,0,0)) - for v in pointEdge : - s = s + v - s = s / len(pointEdge) - - vtxvec = [] - for v in pointEdge : - vtxvec.append(v-s) - - X0 = vtxvec[0] - Y0 = normal.cross(X0) - - orden=[] - for i,v in enumerate(vtxvec): - phi = np.arctan2(v.dot(Y0),v.dot(X0)) - orden.append((phi,i)) - orden.sort() - - self.shape = Part.Face( Part.makePolygon([ pointEdge[p[1]] for p in orden ], True)) - - return - - elif self.Type == 'Cylinder' : - dir = self.Surf.Axis - pnt = self.Surf.Center - rad = self.Surf.Radius - - dmin = dir.dot((self.__boundBox__.getPoint(0)-pnt)) - dmax = dmin - for i in range(1,8): - d = dir.dot((self.__boundBox__.getPoint(i)-pnt)) - dmin = min(d,dmin) - dmax = max(d,dmax) - - pnt = pnt + (dmin-5) * dir - length = dmax-dmin+10 - self.shape = Part.makeCylinder(rad,length,pnt,dir,360.0) - return - - elif self.Type == 'Cone': -# dir = self.Surf.Axis -# apex = self.Surf.Apex -# tan = math.tan(self.Surf.SemiAngle) -# rad = tan*diag # New radius far away to cover all geometry - - axis = self.Surf.Axis - apex = self.Surf.Apex - tan = math.tan(self.Surf.SemiAngle) - - dmax = axis.dot((self.__boundBox__.getPoint(0)-apex)) - for i in range(1,8): - d = axis.dot((self.__boundBox__.getPoint(i)-apex)) - dmax = max(d,dmax) - - if dmax > 0 : - length = dmax+10 - rad = tan*length - self.shape = Part.makeCone(0.0,rad,length,apex,axis,360.0) - else : - self.shape = None - return - self.shape = cone - - elif self.Type == 'Sphere' : - rad = self.Surf.Radius - pnt = self.Surf.Center - self.shape = Part.makeSphere(rad,pnt).Faces[0] - return - - elif self.Type == 'Torus': - axis = self.Surf.Axis - center = self.Surf.Center - majorR = self.Surf.MajorRadius - minorR = self.Surf.MinorRadius - - torus = Part.makeTorus(majorR,minorR,center,axis) - self.shape = torus.Faces[0] - return - else: - print('Error: Type {} is not defined'.format(self.Type)) - return - - + + if self.Type == "Plane": + + normal = self.Surf.Axis + p0 = normal.dot(self.Surf.Position) + Box = FreeCAD.BoundBox(self.__boundBox__) + Box.enlarge(10) + + pointEdge = [] + for i in range(12): + edge = Box.getEdge(i) + p1 = normal.dot(edge[0]) + p2 = normal.dot(edge[1]) + d0 = p0 - p1 + d1 = p2 - p1 + if d1 != 0: + a = d0 / d1 + if a >= 0 and a <= 1: + pointEdge.append(edge[0] + a * (edge[1] - edge[0])) + + if len(pointEdge) == 0: + self.shape = None # Plane does not cross box + return + + s = FreeCAD.Vector((0, 0, 0)) + for v in pointEdge: + s = s + v + s = s / len(pointEdge) + + vtxvec = [] + for v in pointEdge: + vtxvec.append(v - s) + + X0 = vtxvec[0] + Y0 = normal.cross(X0) + + orden = [] + for i, v in enumerate(vtxvec): + phi = np.arctan2(v.dot(Y0), v.dot(X0)) + orden.append((phi, i)) + orden.sort() + + self.shape = Part.Face( + Part.makePolygon([pointEdge[p[1]] for p in orden], True) + ) + + return + + elif self.Type == "Cylinder": + dir = self.Surf.Axis + pnt = self.Surf.Center + rad = self.Surf.Radius + + dmin = dir.dot((self.__boundBox__.getPoint(0) - pnt)) + dmax = dmin + for i in range(1, 8): + d = dir.dot((self.__boundBox__.getPoint(i) - pnt)) + dmin = min(d, dmin) + dmax = max(d, dmax) + + pnt = pnt + (dmin - 5) * dir + length = dmax - dmin + 10 + self.shape = Part.makeCylinder(rad, length, pnt, dir, 360.0) + return + + elif self.Type == "Cone": + # dir = self.Surf.Axis + # apex = self.Surf.Apex + # tan = math.tan(self.Surf.SemiAngle) + # rad = tan*diag # New radius far away to cover all geometry + + axis = self.Surf.Axis + apex = self.Surf.Apex + tan = math.tan(self.Surf.SemiAngle) + + dmax = axis.dot((self.__boundBox__.getPoint(0) - apex)) + for i in range(1, 8): + d = axis.dot((self.__boundBox__.getPoint(i) - apex)) + dmax = max(d, dmax) + + if dmax > 0: + length = dmax + 10 + rad = tan * length + self.shape = Part.makeCone(0.0, rad, length, apex, axis, 360.0) + else: + self.shape = None + return + self.shape = cone + + elif self.Type == "Sphere": + rad = self.Surf.Radius + pnt = self.Surf.Center + self.shape = Part.makeSphere(rad, pnt).Faces[0] + return + + elif self.Type == "Torus": + axis = self.Surf.Axis + center = self.Surf.Center + majorR = self.Surf.MajorRadius + minorR = self.Surf.MinorRadius + + torus = Part.makeTorus(majorR, minorR, center, axis) + self.shape = torus.Faces[0] + return + else: + print("Error: Type {} is not defined".format(self.Type)) + return + + class Surfaces_dict(dict): - def __init__(self,surfaces=None,offset=0): + def __init__(self, surfaces=None, offset=0): self.IndexOffset = offset - surfname = ['PX','PY','PZ','P','Cyl','Cone','Sph','Tor'] - for name in surfname : - self[name] = [] + surfname = ["PX", "PY", "PZ", "P", "Cyl", "Cone", "Sph", "Tor"] + for name in surfname: + self[name] = [] self.__surfIndex__ = dict() if surfaces is not None: - for key in surfaces.keys(): - self[key]=surfaces[key][:] - self.__surfIndex__[key] = surfaces.__surfIndex__[key][:] - self.surfaceNumber = surfaces.surfaceNumber - self.__last_obj__ = (surfaces.__last_obj__[0],surfaces.__last_obj__[1]) - else: - self.surfaceNumber = 0 - self.__last_obj__ = ('',-1) - for key in surfname : - self.__surfIndex__[key] = [] + for key in surfaces.keys(): + self[key] = surfaces[key][:] + self.__surfIndex__[key] = surfaces.__surfIndex__[key][:] + self.surfaceNumber = surfaces.surfaceNumber + self.__last_obj__ = (surfaces.__last_obj__[0], surfaces.__last_obj__[1]) + else: + self.surfaceNumber = 0 + self.__last_obj__ = ("", -1) + for key in surfname: + self.__surfIndex__[key] = [] + return + + def __str__(self): + for key in self.keys(): + print(key, self[key]) + return "" + + def getSurface(self, index): + + lastKey = self.__last_obj__[0] + lastInd = self.__last_obj__[1] + if lastKey != "": + if len(self[lastKey]) > 0: + if self[lastKey][lastInd].Index == index: + return self[lastKey][lastInd] + + for key, values in self.__surfIndex__.items(): + if index not in values: + continue + i = values.index(index) + self.__last_obj__ = (key, i) + return self[key][i] + + print("Index {} not found in Surfaces".format(index)) + return None + + def delSurface(self, index): + self.getSurface(index) + self.__surfIndex__[self.__last_obj__[0]].remove(index) + del self[self.__last_obj__[0]][self.__last_obj__[1]] return - def __str__(self): - for key in self.keys(): - print( key, self[key]) - return '' - - def getSurface(self,index): - - lastKey = self.__last_obj__[0] - lastInd = self.__last_obj__[1] - if lastKey != '': - if len(self[lastKey]) > 0 : - if self[lastKey][lastInd].Index == index : - return self[lastKey][lastInd] - - for key,values in self.__surfIndex__.items() : - if index not in values : continue - i = values.index(index) - self.__last_obj__ = (key,i) - return self[key][i] - - print ('Index {} not found in Surfaces'.format(index)) - return None - - def delSurface(self,index): - self.getSurface(index) - self.__surfIndex__[self.__last_obj__[0]].remove(index) - del (self[self.__last_obj__[0]][self.__last_obj__[1]]) - return - - def extend(self,surface): - for Pkey in ['PX','PY','PZ','P']: - for s in surface[Pkey]: - self.addPlane(s) - for s in surface['Cyl']: - self.addCylinder(s) - for s in surface['Cone']: - self.addCone(s) - for s in surface['Sph']: - self.addSphere(s) - for s in surface['Tor']: - self.addTorus(s) - - def addPlane(self,plane,fuzzy=False): - ex = FreeCAD.Vector(1,0,0) - ey = FreeCAD.Vector(0,1,0) - ez = FreeCAD.Vector(0,0,1) - - if isParallel(plane.Surf.Axis,ex,tol.pln_angle) : - addPlane = True - for i,p in enumerate(self['PX']): - if BF.isSamePlane(plane.Surf,p.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol,fuzzy=(fuzzy,p.Index)): - addPlane = False - index = p.Index - self.__last_obj__ = ('PX',i) - break - if addPlane : - self.surfaceNumber += 1 - plane.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('PX',len(self['PX'])) - self['PX'].append(plane) - self.__surfIndex__['PX'].append(plane.Index) - - - elif isParallel(plane.Surf.Axis,ey,tol.pln_angle) : - addPlane = True - for i,p in enumerate(self['PY']): - if BF.isSamePlane(plane.Surf,p.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol,fuzzy=(fuzzy,p.Index)) : - addPlane = False - index = p.Index - self.__last_obj__ = ('PY',i) - break - if addPlane : - self.surfaceNumber += 1 - plane.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('PY',len(self['PY'])) - self['PY'].append(plane) - self.__surfIndex__['PY'].append(plane.Index) - - elif isParallel(plane.Surf.Axis,ez,tol.pln_angle) : - addPlane = True - for i,p in enumerate(self['PZ']): - if BF.isSamePlane(plane.Surf,p.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol,fuzzy=(fuzzy,p.Index)) : - addPlane = False - index = p.Index - self.__last_obj__ = ('PZ',i) - break - if addPlane : - self.surfaceNumber += 1 - plane.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('PZ',len(self['PZ'])) - self['PZ'].append(plane) - self.__surfIndex__['PZ'].append(plane.Index) - + def extend(self, surface): + for Pkey in ["PX", "PY", "PZ", "P"]: + for s in surface[Pkey]: + self.addPlane(s) + for s in surface["Cyl"]: + self.addCylinder(s) + for s in surface["Cone"]: + self.addCone(s) + for s in surface["Sph"]: + self.addSphere(s) + for s in surface["Tor"]: + self.addTorus(s) + + def addPlane(self, plane, fuzzy=False): + ex = FreeCAD.Vector(1, 0, 0) + ey = FreeCAD.Vector(0, 1, 0) + ez = FreeCAD.Vector(0, 0, 1) + + if isParallel(plane.Surf.Axis, ex, tol.pln_angle): + addPlane = True + for i, p in enumerate(self["PX"]): + if BF.isSamePlane( + plane.Surf, + p.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + fuzzy=(fuzzy, p.Index), + ): + addPlane = False + index = p.Index + self.__last_obj__ = ("PX", i) + break + if addPlane: + self.surfaceNumber += 1 + plane.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("PX", len(self["PX"])) + self["PX"].append(plane) + self.__surfIndex__["PX"].append(plane.Index) + + elif isParallel(plane.Surf.Axis, ey, tol.pln_angle): + addPlane = True + for i, p in enumerate(self["PY"]): + if BF.isSamePlane( + plane.Surf, + p.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + fuzzy=(fuzzy, p.Index), + ): + addPlane = False + index = p.Index + self.__last_obj__ = ("PY", i) + break + if addPlane: + self.surfaceNumber += 1 + plane.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("PY", len(self["PY"])) + self["PY"].append(plane) + self.__surfIndex__["PY"].append(plane.Index) + + elif isParallel(plane.Surf.Axis, ez, tol.pln_angle): + addPlane = True + for i, p in enumerate(self["PZ"]): + if BF.isSamePlane( + plane.Surf, + p.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + fuzzy=(fuzzy, p.Index), + ): + addPlane = False + index = p.Index + self.__last_obj__ = ("PZ", i) + break + if addPlane: + self.surfaceNumber += 1 + plane.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("PZ", len(self["PZ"])) + self["PZ"].append(plane) + self.__surfIndex__["PZ"].append(plane.Index) + else: - addPlane = True - for i,p in enumerate(self['P']): - if BF.isSamePlane(plane.Surf,p.Surf,dtol=tol.pln_distance,atol=tol.pln_angle,relTol=tol.relativeTol,fuzzy=(fuzzy,p.Index)) : - addPlane = False - index = p.Index - self.__last_obj__ = ('P',i) - break - if addPlane : - self.surfaceNumber += 1 - plane.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('P',len(self['P'])) - self['P'].append(plane) - self.__surfIndex__['P'].append(plane.Index) - - if addPlane : - return plane.Index, False + addPlane = True + for i, p in enumerate(self["P"]): + if BF.isSamePlane( + plane.Surf, + p.Surf, + dtol=tol.pln_distance, + atol=tol.pln_angle, + relTol=tol.relativeTol, + fuzzy=(fuzzy, p.Index), + ): + addPlane = False + index = p.Index + self.__last_obj__ = ("P", i) + break + if addPlane: + self.surfaceNumber += 1 + plane.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("P", len(self["P"])) + self["P"].append(plane) + self.__surfIndex__["P"].append(plane.Index) + + if addPlane: + return plane.Index, False else: - return index, True + return index, True - def addCylinder(self,cyl,fuzzy=False): + def addCylinder(self, cyl, fuzzy=False): addCyl = True - for i,c in enumerate(self['Cyl']): - if BF.isSameCylinder(cyl.Surf,c.Surf,dtol=tol.cyl_distance,atol=tol.cyl_angle,relTol=tol.relativeTol,fuzzy=(fuzzy,c.Index)): + for i, c in enumerate(self["Cyl"]): + if BF.isSameCylinder( + cyl.Surf, + c.Surf, + dtol=tol.cyl_distance, + atol=tol.cyl_angle, + relTol=tol.relativeTol, + fuzzy=(fuzzy, c.Index), + ): addCyl = False index = c.Index - self.__last_obj__ = ('Cyl',i) + self.__last_obj__ = ("Cyl", i) break - - if addCyl : - self.surfaceNumber += 1 - cyl.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('Cyl',len(self['Cyl'])) - self['Cyl'].append(cyl) - self.__surfIndex__['Cyl'].append(cyl.Index) - return cyl.Index, False - else: - return index, True - - def addCone(self,cone): + + if addCyl: + self.surfaceNumber += 1 + cyl.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("Cyl", len(self["Cyl"])) + self["Cyl"].append(cyl) + self.__surfIndex__["Cyl"].append(cyl.Index) + return cyl.Index, False + else: + return index, True + + def addCone(self, cone): addCone = True - for i,c in enumerate(self['Cone']): - if BF.isSameCone(cone.Surf,c.Surf,dtol=tol.kne_distance,atol=tol.kne_angle,relTol=tol.relativeTol): + for i, c in enumerate(self["Cone"]): + if BF.isSameCone( + cone.Surf, + c.Surf, + dtol=tol.kne_distance, + atol=tol.kne_angle, + relTol=tol.relativeTol, + ): addCone = False index = c.Index - self.__last_obj__ = ('Cone',i) + self.__last_obj__ = ("Cone", i) break - if addCone : - self.surfaceNumber += 1 - cone.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('Cone',len(self['Cone'])) - self['Cone'].append(cone) - self.__surfIndex__['Cone'].append(cone.Index) - return cone.Index, False + if addCone: + self.surfaceNumber += 1 + cone.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("Cone", len(self["Cone"])) + self["Cone"].append(cone) + self.__surfIndex__["Cone"].append(cone.Index) + return cone.Index, False else: - return index, True - - def addSphere(self,sph): + return index, True + + def addSphere(self, sph): addSphere = True - for i,s in enumerate(self['Sph']): - if BF.isSameSphere(sph.Surf,s.Surf,tol.sph_distance,relTol=tol.relativeTol): + for i, s in enumerate(self["Sph"]): + if BF.isSameSphere( + sph.Surf, s.Surf, tol.sph_distance, relTol=tol.relativeTol + ): addSphere = False index = s.Index - self.__last_obj__ = ('Sph',i) + self.__last_obj__ = ("Sph", i) break - if addSphere : - self.surfaceNumber += 1 - sph.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('Sph',len(self['Sph'])) - self['Sph'].append(sph) - self.__surfIndex__['Sph'].append(sph.Index) - return sph.Index, False + if addSphere: + self.surfaceNumber += 1 + sph.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("Sph", len(self["Sph"])) + self["Sph"].append(sph) + self.__surfIndex__["Sph"].append(sph.Index) + return sph.Index, False else: - return index, True + return index, True - - def addTorus(self,tor): + def addTorus(self, tor): addTorus = True - for i,s in enumerate(self['Tor']): - if BF.isSameTorus(tor.Surf,s.Surf,dtol=tol.tor_distance,atol=tol.tor_angle,relTol=tol.relativeTol): + for i, s in enumerate(self["Tor"]): + if BF.isSameTorus( + tor.Surf, + s.Surf, + dtol=tol.tor_distance, + atol=tol.tor_angle, + relTol=tol.relativeTol, + ): addTorus = False index = s.Index - self.__last_obj__ = ('Tor',i) + self.__last_obj__ = ("Tor", i) break - if addTorus : - self.surfaceNumber += 1 - tor.Index = self.surfaceNumber + self.IndexOffset - self.__last_obj__ = ('Tor',len(self['Tor'])) - self['Tor'].append(tor) - self.__surfIndex__['Tor'].append(tor.Index) - return tor.Index, False + if addTorus: + self.surfaceNumber += 1 + tor.Index = self.surfaceNumber + self.IndexOffset + self.__last_obj__ = ("Tor", len(self["Tor"])) + self["Tor"].append(tor) + self.__surfIndex__["Tor"].append(tor.Index) + return tor.Index, False + else: + return index, True + + +def splitBOP(solid, tools, tolerance, scale=0.1): + + if tolerance >= 0.1: + compSolid = BOPTools.SplitAPI.slice(solid, tools, "Split", tolerance=tolerance) + + elif tolerance < 1e-12: + if Options.scaleUp: + tol = 1e-13 if Options.splitTolerance == 0 else Options.splitTolerance + compSolid = splitBOP(solid, tools, tol / scale, 1.0 / scale) else: - return index, True - -def splitBOP(solid,tools,tolerance,scale=0.1): - - if tolerance >= 0.1 : - compSolid = BOPTools.SplitAPI.slice(solid,tools,'Split',tolerance =tolerance) - - elif tolerance < 1e-12 : - if Options.scaleUp : - tol = 1e-13 if Options.splitTolerance == 0 else Options.splitTolerance - compSolid = splitBOP(solid,tools,tol/scale,1./scale) - else: - compSolid = BOPTools.SplitAPI.slice(solid,tools,'Split',tolerance =tolerance) - - else: - try : - compSolid = BOPTools.SplitAPI.slice(solid,tools,'Split',tolerance =tolerance) - except: - compSolid = splitBOP(solid,tools,tolerance*scale,scale) - - return compSolid + compSolid = BOPTools.SplitAPI.slice( + solid, tools, "Split", tolerance=tolerance + ) + + else: + try: + compSolid = BOPTools.SplitAPI.slice( + solid, tools, "Split", tolerance=tolerance + ) + except: + compSolid = splitBOP(solid, tools, tolerance * scale, scale) + + return compSolid diff --git a/src/geouned/GEOUNED/Utils/Geometry_GU.py b/src/geouned/GEOUNED/Utils/Geometry_GU.py index 769bab91..8d7945bb 100644 --- a/src/geouned/GEOUNED/Utils/Geometry_GU.py +++ b/src/geouned/GEOUNED/Utils/Geometry_GU.py @@ -13,269 +13,293 @@ # SURFACES class Surfaces_GU(object): - def __init__(self,face): - - self.face = face - self.Surface = self.face.Surface - self.type = str(self.Surface) - - def __str__(self): - """ str(Surface) is done for the classification of the surface. - Surface_GU saves this information in self.type""" + def __init__(self, face): + + self.face = face + self.Surface = self.face.Surface + self.type = str(self.Surface) + + def __str__(self): + """str(Surface) is done for the classification of the surface. + Surface_GU saves this information in self.type""" return self.type - + + class Plane_GU(Surfaces_GU): - def __init__(self,face,plane3Pts=False): - - Surfaces_GU.__init__(self,face) + def __init__(self, face, plane3Pts=False): + + Surfaces_GU.__init__(self, face) self.Axis = face.Surface.Axis self.Position = face.Surface.Position self.pointDef = plane3Pts if plane3Pts: - self.Points = tuple( v.Point for v in face.Vertexes) - d1 = self.Points[0]-self.Points[1] - d2 = self.Points[0]-self.Points[2] - d3 = self.Points[1]-self.Points[2] - self.dim1 = max(d1.Length, d2.Length, d3.Length) - self.dim2 = min(d1.Length, d2.Length, d3.Length) + self.Points = tuple(v.Point for v in face.Vertexes) + d1 = self.Points[0] - self.Points[1] + d2 = self.Points[0] - self.Points[2] + d3 = self.Points[1] - self.Points[2] + self.dim1 = max(d1.Length, d2.Length, d3.Length) + self.dim2 = min(d1.Length, d2.Length, d3.Length) else: - self.dim1 = face.ParameterRange[1]-face.ParameterRange[0] - self.dim2 = face.ParameterRange[3]-face.ParameterRange[2] + self.dim1 = face.ParameterRange[1] - face.ParameterRange[0] + self.dim2 = face.ParameterRange[3] - face.ParameterRange[2] + class Cylinder_GU(Surfaces_GU): - def __init__(self,face): - - Surfaces_GU.__init__(self,face) + def __init__(self, face): + + Surfaces_GU.__init__(self, face) self.Axis = face.Surface.Axis self.Radius = face.Surface.Radius self.Center = face.Surface.Center - self.dimL = face.ParameterRange[3]-face.ParameterRange[2] - + self.dimL = face.ParameterRange[3] - face.ParameterRange[2] + + class Cone_GU(Surfaces_GU): - def __init__(self,face): - - Surfaces_GU.__init__(self,face) + def __init__(self, face): + + Surfaces_GU.__init__(self, face) self.Axis = face.Surface.Axis self.Apex = face.Surface.Apex self.SemiAngle = face.Surface.SemiAngle - self.dimL = face.ParameterRange[3]-face.ParameterRange[2] + self.dimL = face.ParameterRange[3] - face.ParameterRange[2] self.dimR = face.Surface.Radius self.Radius = face.Surface.Radius - + + class Sphere_GU(Surfaces_GU): - def __init__(self,face): - - Surfaces_GU.__init__(self,face) - self.type=self.type[0:6] + def __init__(self, face): + + Surfaces_GU.__init__(self, face) + self.type = self.type[0:6] self.Center = face.Surface.Center self.Radius = face.Surface.Radius + class Torus_GU(Surfaces_GU): - def __init__(self,face): - - Surfaces_GU.__init__(self,face) - self.Center = face.Surface.Center - self.Axis = face.Surface.Axis + def __init__(self, face): + + Surfaces_GU.__init__(self, face) + self.Center = face.Surface.Center + self.Axis = face.Surface.Axis self.MajorRadius = face.Surface.MajorRadius - self.MinorRadius = face.Surface.MinorRadius - -class solid_GU(): - - def __init__(self,solid,plane3Pts = False): - self.solid=solid - faces = DefineListFace_GU(solid.Faces,plane3Pts) - self.Faces=faces - self.Solids=solid.Solids - self.BoundBox=solid.BoundBox - self.Edges=solid.Edges + self.MinorRadius = face.Surface.MinorRadius + + +class solid_GU: + + def __init__(self, solid, plane3Pts=False): + self.solid = solid + faces = DefineListFace_GU(solid.Faces, plane3Pts) + self.Faces = faces + self.Solids = solid.Solids + self.BoundBox = solid.BoundBox + self.Edges = solid.Edges self.TorusVParams = {} self.TorusUParams = {} - toroidIndex=[] - for i,face in enumerate(self.Faces): - if str(face.Surface) != '' : continue + toroidIndex = [] + for i, face in enumerate(self.Faces): + if str(face.Surface) != "": + continue toroidIndex.append(i) if len(toroidIndex) != 0: tFaces = self.__sameTorusSurf__(toroidIndex) - for i,tSet in enumerate(tFaces) : - URange = self.__mergePeriodicUV__('U',tSet) - VRange = self.__mergePeriodicUV__('V',tSet) - for t in tSet: - self.TorusVParams[t] = (i,VRange) - self.TorusUParams[t] = (i,URange) + for i, tSet in enumerate(tFaces): + URange = self.__mergePeriodicUV__("U", tSet) + VRange = self.__mergePeriodicUV__("V", tSet) + for t in tSet: + self.TorusVParams[t] = (i, VRange) + self.TorusUParams[t] = (i, URange) - def __sameTorusSurf__(self,torusList): + def __sameTorusSurf__(self, torusList): - # group identical faces + # group identical faces sameTorusFace = [] temp = torusList[:] - while len(temp) > 0 : - i = temp[0] - current=[i] - for j in temp[1:]: - if isSameTorus(self.Faces[i].Surface,self.Faces[j].Surface,dtol=tol.tor_distance,atol=tol.tor_angle,relTol=tol.relativeTol): - current.append(j) - for c in current: - temp.remove(c) - sameTorusFace.append(current) + while len(temp) > 0: + i = temp[0] + current = [i] + for j in temp[1:]: + if isSameTorus( + self.Faces[i].Surface, + self.Faces[j].Surface, + dtol=tol.tor_distance, + atol=tol.tor_angle, + relTol=tol.relativeTol, + ): + current.append(j) + for c in current: + temp.remove(c) + sameTorusFace.append(current) return self.__separateSurfaces__(sameTorusFace) - - def __separateSurfaces__(self,faceList): + def __separateSurfaces__(self, faceList): # group all faces forming a continuous surface sameSurfaces = [] for tset in faceList: - temp = tset[:] - while len(temp) > 0 : - i = 0 - current = [temp[0]] - removeList = [temp[0]] - while len(temp) > 0 and i < len(current) : - for tindex in temp: - if self.Faces[current[i]].distToShape(self.Faces[tindex])[0] < tol.distance : - if tindex not in current : - current.append(tindex) - removeList.append(tindex) - i += 1 - for c in removeList : - temp.remove(c) - removeList=[] - - sameSurfaces.append(current) + temp = tset[:] + while len(temp) > 0: + i = 0 + current = [temp[0]] + removeList = [temp[0]] + while len(temp) > 0 and i < len(current): + for tindex in temp: + if ( + self.Faces[current[i]].distToShape(self.Faces[tindex])[0] + < tol.distance + ): + if tindex not in current: + current.append(tindex) + removeList.append(tindex) + i += 1 + for c in removeList: + temp.remove(c) + removeList = [] + + sameSurfaces.append(current) return sameSurfaces - def __mergeNoPeriodicUV__(self,parameter,faceList): - - if parameter == 'U': - i1=0 - i2=2 - elif parameter == 'V': - i1 = 2 - i2 = 4 - - Vmin,Vmax = self.Faces[faceList[0]].ParameterRange[i1:i2] - for face in faceList[1:] : - V0,V1 = self.Faces[face].ParameterRange[i1:i2] - Vmin = min(Vmin,V0) - Vmax = max(Vmax,V1) - mergedParams = (False,(Vmin,Vmax)) - - return mergedParams - - def __mergePeriodicUV__(self,parameter,faceList): - twoPi = 2.0 * math.pi - if parameter == 'U': - i1=0 - i2=2 - elif parameter == 'V': - i1 = 2 - i2 = 4 - - params = [] - arcLength = 0. - for face in faceList : - V0,V1 = self.Faces[face].ParameterRange[i1:i2] - arcLength += V1-V0 - params.append((V0,V1)) - - params.sort() - V0 = params[0][0] - V1 = params[-1][1] - if arcLength >= twoPi*(1.-tol.relativePrecision): - mergedParams = (True,(V0,V0+twoPi)) - else: - if isSameValue(V0, 0., tol.relativePrecision ) and isSameValue(V1, twoPi, tol.relativePrecision ) : - for i in range(len(params)-1): - if not isSameValue(params[i][1], params[i+1][0], tol.relativePrecision ): break - Vmin=params[i+1][0]-twoPi - Vmax=params[i][1] - else: - Vmin = params[0][0] - Vmax = params[-1][1] - mergedParams = (False,(Vmin,Vmax)) - - return mergedParams + def __mergeNoPeriodicUV__(self, parameter, faceList): + + if parameter == "U": + i1 = 0 + i2 = 2 + elif parameter == "V": + i1 = 2 + i2 = 4 + + Vmin, Vmax = self.Faces[faceList[0]].ParameterRange[i1:i2] + for face in faceList[1:]: + V0, V1 = self.Faces[face].ParameterRange[i1:i2] + Vmin = min(Vmin, V0) + Vmax = max(Vmax, V1) + mergedParams = (False, (Vmin, Vmax)) + + return mergedParams + + def __mergePeriodicUV__(self, parameter, faceList): + twoPi = 2.0 * math.pi + if parameter == "U": + i1 = 0 + i2 = 2 + elif parameter == "V": + i1 = 2 + i2 = 4 + + params = [] + arcLength = 0.0 + for face in faceList: + V0, V1 = self.Faces[face].ParameterRange[i1:i2] + arcLength += V1 - V0 + params.append((V0, V1)) + + params.sort() + V0 = params[0][0] + V1 = params[-1][1] + if arcLength >= twoPi * (1.0 - tol.relativePrecision): + mergedParams = (True, (V0, V0 + twoPi)) + else: + if isSameValue(V0, 0.0, tol.relativePrecision) and isSameValue( + V1, twoPi, tol.relativePrecision + ): + for i in range(len(params) - 1): + if not isSameValue( + params[i][1], params[i + 1][0], tol.relativePrecision + ): + break + Vmin = params[i + 1][0] - twoPi + Vmax = params[i][1] + else: + Vmin = params[0][0] + Vmax = params[-1][1] + mergedParams = (False, (Vmin, Vmax)) + + return mergedParams + # FACES class Faces_GU(object): - def __init__(self,face,Plane3Pts=False): + def __init__(self, face, Plane3Pts=False): # GEOUNED based atributes - self.__face__ = face - self.Surface = DefineSurface(face,Plane3Pts) # Define the appropiate GU Surface of the face + self.__face__ = face + self.Surface = DefineSurface( + face, Plane3Pts + ) # Define the appropiate GU Surface of the face # FreeCAD based Atributes - self.Area = face.Area - self.CenterOfMass = face.CenterOfMass + self.Area = face.Area + self.CenterOfMass = face.CenterOfMass self.ParameterRange = face.ParameterRange - self.Orientation = face.Orientation - self.OuterWire = face.OuterWire - self.Edges = face.Edges - self.Vertexes = face.Vertexes + self.Orientation = face.Orientation + self.OuterWire = face.OuterWire + self.Edges = face.Edges + self.Vertexes = face.Vertexes return - def tessellate(self,val,reset=False): - res = self.__face__.tessellate(val,reset) + def tessellate(self, val, reset=False): + res = self.__face__.tessellate(val, reset) return res def getUVNodes(self): - return self.__face__.getUVNodes() + return self.__face__.getUVNodes() - def isEqual(self,face): + def isEqual(self, face): return self.__face__.isEqual(face.__face__) - def valueAt(self,u,v): - return self.__face__.valueAt(u,v) + def valueAt(self, u, v): + return self.__face__.valueAt(u, v) - def distToShape(self,shape): + def distToShape(self, shape): shape1 = self.__face__ if type(shape) is Part.Shape: shape2 = shape else: shape2 = shape.__face__ - if shape1 is shape2 : - return (0,) + if shape1 is shape2: + return (0,) else: - try : - dist2Shape = shape1.distToShape(shape2) - except: - dist2Shape = shape2.distToShape(shape1) - return dist2Shape - + try: + dist2Shape = shape1.distToShape(shape2) + except: + dist2Shape = shape2.distToShape(shape1) + return dist2Shape + # Aux functions -def DefineListFace_GU(face_list,plane3Pts=False): - """ Return the list of the corresponding Face_GU object of a FaceList""" - return tuple( Faces_GU(face, plane3Pts) for face in face_list ) - -def DefineSurface(face,plane3Pts): - kind_surf=str(face.Surface) - if kind_surf=='': - Surf_GU=Plane_GU(face,plane3Pts) - elif kind_surf=='': - Surf_GU=Cylinder_GU(face) - elif kind_surf=='': - Surf_GU=Cone_GU(face) - elif kind_surf[0:6] == 'Sphere': - Surf_GU=Sphere_GU(face) - elif kind_surf == '': - Surf_GU=Torus_GU(face) +def DefineListFace_GU(face_list, plane3Pts=False): + """Return the list of the corresponding Face_GU object of a FaceList""" + return tuple(Faces_GU(face, plane3Pts) for face in face_list) + + +def DefineSurface(face, plane3Pts): + kind_surf = str(face.Surface) + if kind_surf == "": + Surf_GU = Plane_GU(face, plane3Pts) + elif kind_surf == "": + Surf_GU = Cylinder_GU(face) + elif kind_surf == "": + Surf_GU = Cone_GU(face) + elif kind_surf[0:6] == "Sphere": + Surf_GU = Sphere_GU(face) + elif kind_surf == "": + Surf_GU = Torus_GU(face) else: - print('bad Surface type',kind_surf) + print("bad Surface type", kind_surf) Surf_GU = None return Surf_GU def ListSurfaces(Surfaces): - Faces=[] + Faces = [] for elem in Surfaces: - Faces.extend( DefineSurface(face) for face in elem ) + Faces.extend(DefineSurface(face) for face in elem) return Faces diff --git a/src/geouned/GEOUNED/Utils/Options/Classes.py b/src/geouned/GEOUNED/Utils/Options/Classes.py index 6f2da916..fe672f25 100644 --- a/src/geouned/GEOUNED/Utils/Options/Classes.py +++ b/src/geouned/GEOUNED/Utils/Options/Classes.py @@ -1,10 +1,10 @@ class Options: pass + class MCNP_numeric_format: pass + class Tolerances: pass - - diff --git a/src/geouned/GEOUNED/Utils/Options/__init__.py b/src/geouned/GEOUNED/Utils/Options/__init__.py index 8a43702e..9e84780c 100644 --- a/src/geouned/GEOUNED/Utils/Options/__init__.py +++ b/src/geouned/GEOUNED/Utils/Options/__init__.py @@ -1,72 +1,77 @@ from .Classes import MCNP_numeric_format, Options, Tolerances -#default options values -forceCylinder = True # Force using cylinders instead cones for auxillary surfaces of torus surface definition -newSplitPlane = True # Use new module for planes splitting in decomposition module -delLastNumber = False # Deleting the last word in the comment if it is a number -verbose = False # Display information during conversion process -enlargeBox = 2 # Enlarge box Boundary when evaluating Ctable (dimension in mm) -nPlaneReverse = 0 # numbers of plane thresold whether cut of parallel planes are made fisrt with lowest or highest number -splitTolerance = 0 # First try for fuzzy tolerance used in BOPTOOL Split function. If BOPTSplit crash try lower value for tolerance -scaleUp = True # Scale up Fuzzy tolerance once get below 1e-12 -quadricPY = False # use quadric form of cones and cylinder not aligned with X,Y,Z axis when write openMC script file -Facets = False # use alternative conversion module when geometry is defined by cells compound by only triangular plane faces -prnt3PPlane = False # print 3 point plane definition in MCNP output as 3 points coordinates -forceNoOverlap = False # force no overlaping cell definition. Adjacent cell definition are rested from current cell definition +# default options values +forceCylinder = True # Force using cylinders instead cones for auxillary surfaces of torus surface definition +newSplitPlane = True # Use new module for planes splitting in decomposition module +delLastNumber = False # Deleting the last word in the comment if it is a number +verbose = False # Display information during conversion process +enlargeBox = 2 # Enlarge box Boundary when evaluating Ctable (dimension in mm) +nPlaneReverse = 0 # numbers of plane thresold whether cut of parallel planes are made fisrt with lowest or highest number +splitTolerance = 0 # First try for fuzzy tolerance used in BOPTOOL Split function. If BOPTSplit crash try lower value for tolerance +scaleUp = True # Scale up Fuzzy tolerance once get below 1e-12 +quadricPY = False # use quadric form of cones and cylinder not aligned with X,Y,Z axis when write openMC script file +Facets = False # use alternative conversion module when geometry is defined by cells compound by only triangular plane faces +prnt3PPlane = ( + False # print 3 point plane definition in MCNP output as 3 points coordinates +) +forceNoOverlap = False # force no overlaping cell definition. Adjacent cell definition are rested from current cell definition -tolValueDict = { 'relativeTol' : False , - 'relativePrecision' : 1.e-6 , # relative precision - 'value' : 1.e-6 , # Tolerance in single value comparison - 'distance' : 1.e-4 , # General Distance Tolerance - 'angle' : 1.e-4 , # General Angle Tolerance - 'pln_distance' : 1.e-4 , # distance between planes equal planes if distance between parallel planes < 1e-4 cm - 'pln_angle' : 1.e-4 , # angle between axis. 1e-4 : planes separate each other 0.1mm each 1m - 'cyl_distance' : 1.e-4 , # distance between radius/center - 'cyl_angle' : 1.e-4 , # angle between axis - 'sph_distance' : 1.e-4 , # distance between radius/center - 'kne_distance' : 1.e-4 , # distance between apex - 'kne_angle' : 1.e-4 , # angle between semiangles/axis - 'tor_distance' : 1.e-4 , # distance between Major/Minor radii/center - 'tor_angle' : 1.e-4 , # angle between axis - 'min_area' : 1.e-2 } # minimun face area to consider in cell definition +tolValueDict = { + "relativeTol": False, + "relativePrecision": 1.0e-6, # relative precision + "value": 1.0e-6, # Tolerance in single value comparison + "distance": 1.0e-4, # General Distance Tolerance + "angle": 1.0e-4, # General Angle Tolerance + "pln_distance": 1.0e-4, # distance between planes equal planes if distance between parallel planes < 1e-4 cm + "pln_angle": 1.0e-4, # angle between axis. 1e-4 : planes separate each other 0.1mm each 1m + "cyl_distance": 1.0e-4, # distance between radius/center + "cyl_angle": 1.0e-4, # angle between axis + "sph_distance": 1.0e-4, # distance between radius/center + "kne_distance": 1.0e-4, # distance between apex + "kne_angle": 1.0e-4, # angle between semiangles/axis + "tor_distance": 1.0e-4, # distance between Major/Minor radii/center + "tor_angle": 1.0e-4, # angle between axis + "min_area": 1.0e-2, +} # minimun face area to consider in cell definition -numValueDict = { 'P_abc' : '14.7e' , # Plane general a,b,c params - 'P_d' : '14.7e' , # Plane general d params - 'P_xyz' : '14.7e' , # PX/PY/PZ params - 'S_r' : '14.7e' , # SO/SX/SY/SZ/S radius - 'S_xyz' : '14.7e' , # SO/SX/SY/SZ/S center - 'C_r' : '12f' , # Cylinder radius - 'C_xyz' : '12f' , # Cylinder center - 'K_xyz' : '13.6e' , # Cone apex - 'K_tan2' : '12f' , # Cone tan^2 value - 'T_r' : '14.7e' , # Torus radii - 'T_xyz' : '14.7e' , # Torus center - 'GQ_1to6' : '18.15f' , # GQ 1 to 6 coefficients (order 2 x2,y2,z2,xy,...) - 'GQ_7to9' : '18.15f' , # GQ 7 to 9 coefficients (order 1 x,y,z) - 'GQ_10' : '18.15f' } # GQ 10 coefficient (order 0) - +numValueDict = { + "P_abc": "14.7e", # Plane general a,b,c params + "P_d": "14.7e", # Plane general d params + "P_xyz": "14.7e", # PX/PY/PZ params + "S_r": "14.7e", # SO/SX/SY/SZ/S radius + "S_xyz": "14.7e", # SO/SX/SY/SZ/S center + "C_r": "12f", # Cylinder radius + "C_xyz": "12f", # Cylinder center + "K_xyz": "13.6e", # Cone apex + "K_tan2": "12f", # Cone tan^2 value + "T_r": "14.7e", # Torus radii + "T_xyz": "14.7e", # Torus center + "GQ_1to6": "18.15f", # GQ 1 to 6 coefficients (order 2 x2,y2,z2,xy,...) + "GQ_7to9": "18.15f", # GQ 7 to 9 coefficients (order 1 x,y,z) + "GQ_10": "18.15f", +} # GQ 10 coefficient (order 0) # Set default attributes to Options class -setattr(Options,'forceCylinder' ,forceCylinder) -setattr(Options,'newSplitPlane' ,newSplitPlane) -setattr(Options,'enlargeBox' ,enlargeBox) -setattr(Options,'delLastNumber' ,delLastNumber) -setattr(Options,'verbose' ,verbose) -setattr(Options,'nPlaneReverse' ,nPlaneReverse) -setattr(Options,'splitTolerance',splitTolerance) -setattr(Options,'scaleUp' ,scaleUp) -setattr(Options,'quadricPY' ,quadricPY) -setattr(Options,'Facets' ,Facets) -setattr(Options,'prnt3PPlane' ,prnt3PPlane) -setattr(Options,'forceNoOverlap',forceNoOverlap) +setattr(Options, "forceCylinder", forceCylinder) +setattr(Options, "newSplitPlane", newSplitPlane) +setattr(Options, "enlargeBox", enlargeBox) +setattr(Options, "delLastNumber", delLastNumber) +setattr(Options, "verbose", verbose) +setattr(Options, "nPlaneReverse", nPlaneReverse) +setattr(Options, "splitTolerance", splitTolerance) +setattr(Options, "scaleUp", scaleUp) +setattr(Options, "quadricPY", quadricPY) +setattr(Options, "Facets", Facets) +setattr(Options, "prnt3PPlane", prnt3PPlane) +setattr(Options, "forceNoOverlap", forceNoOverlap) # Set default attributes to Tolerances class for key in tolValueDict.keys(): - setattr(Tolerances,key,tolValueDict[key]) + setattr(Tolerances, key, tolValueDict[key]) # Set default attributes to MCNP number format class for key in numValueDict.keys(): - setattr(MCNP_numeric_format,key,numValueDict[key]) + setattr(MCNP_numeric_format, key, numValueDict[key]) diff --git a/src/geouned/GEOUNED/Utils/Qform.py b/src/geouned/GEOUNED/Utils/Qform.py index 27ac1bf5..006139e1 100644 --- a/src/geouned/GEOUNED/Utils/Qform.py +++ b/src/geouned/GEOUNED/Utils/Qform.py @@ -1,7 +1,7 @@ # # Script to obtain the Qform of a Cylinder # -# +# # import math @@ -10,125 +10,117 @@ import Part -def RotationMatrix(u,v): +def RotationMatrix(u, v): + """Definition of the rotation matrix for two vectors""" - """ Definition of the rotation matrix for two vectors""" - # defintion of the axis of rotation - - Axis=u.cross(v).normalize() - + + Axis = u.cross(v).normalize() + u.normalize() v.normalize() -# print(u, v) -# print(u.Length, v.Length, Axis.Length) - cose=u.dot(v) - seno=u.cross(v).Length - + # print(u, v) + # print(u.Length, v.Length, Axis.Length) + cose = u.dot(v) + seno = u.cross(v).Length + R = FreeCAD.Matrix() - - #cose=math.cos(angle) - #seno=math.sin(angle) - onecos=1.0-cose - + + # cose=math.cos(angle) + # seno=math.sin(angle) + onecos = 1.0 - cose + # 1st row - R.A11=cose+Axis.x**2*onecos - R.A12=Axis.x*Axis.y*onecos-Axis.z*seno - R.A13=Axis.x*Axis.z*onecos+Axis.y*seno - - #2nd row - R.A21=Axis.x*Axis.y*onecos+Axis.z*seno - R.A22=cose+Axis.y**2*onecos - R.A23=Axis.y*Axis.z*onecos-Axis.x*seno - - #3rd row - R.A31=Axis.z*Axis.x*onecos-Axis.y*seno - R.A32=Axis.z*Axis.y*onecos+Axis.x*seno - R.A33=cose+Axis.z**2*onecos - + R.A11 = cose + Axis.x**2 * onecos + R.A12 = Axis.x * Axis.y * onecos - Axis.z * seno + R.A13 = Axis.x * Axis.z * onecos + Axis.y * seno + + # 2nd row + R.A21 = Axis.x * Axis.y * onecos + Axis.z * seno + R.A22 = cose + Axis.y**2 * onecos + R.A23 = Axis.y * Axis.z * onecos - Axis.x * seno + + # 3rd row + R.A31 = Axis.z * Axis.x * onecos - Axis.y * seno + R.A32 = Axis.z * Axis.y * onecos + Axis.x * seno + R.A33 = cose + Axis.z**2 * onecos + return R - -def RotationMatrixAngleAxis(u,angle): - """ Definition of the rotation matrix for an angle and the rotation axis""" - + +def RotationMatrixAngleAxis(u, angle): + """Definition of the rotation matrix for an angle and the rotation axis""" + # defintion of the exis of rotation - - Axis=u.normalize() - - cose=math.cos(angle) - seno=math.sin(angle) - + + Axis = u.normalize() + + cose = math.cos(angle) + seno = math.sin(angle) + R = FreeCAD.Matrix() - - onecos=1.0-cose - + + onecos = 1.0 - cose + # 1st row - R.A11=cose+Axis.x**2*onecos - R.A12=Axis.x*Axis.y*onecos-Axis.z*seno - R.A13=Axis.x*Axis.z*onecos+Axis.y*seno - - #2nd row - R.A21=Axis.x*Axis.y*onecos+Axis.z*seno - R.A22=cose+Axis.y**2*onecos - R.A23=Axis.y*Axis.z*onecos-Axis.x*seno - - #3rd row - R.A31=Axis.z*Axis.x*onecos-Axis.y*seno - R.A32=Axis.z*Axis.y*onecos+Axis.x*seno - R.A33=cose+Axis.z**2*onecos - + R.A11 = cose + Axis.x**2 * onecos + R.A12 = Axis.x * Axis.y * onecos - Axis.z * seno + R.A13 = Axis.x * Axis.z * onecos + Axis.y * seno + + # 2nd row + R.A21 = Axis.x * Axis.y * onecos + Axis.z * seno + R.A22 = cose + Axis.y**2 * onecos + R.A23 = Axis.y * Axis.z * onecos - Axis.x * seno + + # 3rd row + R.A31 = Axis.z * Axis.x * onecos - Axis.y * seno + R.A32 = Axis.z * Axis.y * onecos + Axis.x * seno + R.A33 = cose + Axis.z**2 * onecos + return R - -def QFormCyl(Axis,Pos,rad): - R=RotationMatrix(FreeCAD.Vector(1,0,0),Axis) + +def QFormCyl(Axis, Pos, rad): + + R = RotationMatrix(FreeCAD.Vector(1, 0, 0), Axis) R.transpose() - Pos2=R.multiply(Pos).negative() - - A=R.A21**2+R.A31**2 - B=R.A22**2+R.A32**2 - C=R.A23**2+R.A33**2 - - D=2.0*(R.A21*R.A22+R.A31*R.A32) - E=2.0*(R.A22*R.A23+R.A32*R.A33) - F=2.0*(R.A23*R.A21+R.A33*R.A31) - - G=2.0*(Pos2.y*R.A21+Pos2.z*R.A31) - H=2.0*(Pos2.y*R.A22+Pos2.z*R.A32) - J=2.0*(Pos2.y*R.A23+Pos2.z*R.A33) - - K=Pos2.y**2+Pos2.z**2-rad**2 - - return (A,B,C,D,E,F,G,H,J,K) - -def QFormCone(Axis,Pos,tan): - - R=RotationMatrix(FreeCAD.Vector(1,0,0),Axis) + Pos2 = R.multiply(Pos).negative() + + A = R.A21**2 + R.A31**2 + B = R.A22**2 + R.A32**2 + C = R.A23**2 + R.A33**2 + + D = 2.0 * (R.A21 * R.A22 + R.A31 * R.A32) + E = 2.0 * (R.A22 * R.A23 + R.A32 * R.A33) + F = 2.0 * (R.A23 * R.A21 + R.A33 * R.A31) + + G = 2.0 * (Pos2.y * R.A21 + Pos2.z * R.A31) + H = 2.0 * (Pos2.y * R.A22 + Pos2.z * R.A32) + J = 2.0 * (Pos2.y * R.A23 + Pos2.z * R.A33) + + K = Pos2.y**2 + Pos2.z**2 - rad**2 + + return (A, B, C, D, E, F, G, H, J, K) + + +def QFormCone(Axis, Pos, tan): + + R = RotationMatrix(FreeCAD.Vector(1, 0, 0), Axis) R.transpose() - Pos2=R.multiply(Pos).negative() - - A=R.A21**2+R.A31**2-(tan*R.A11)**2 - B=R.A22**2+R.A32**2-(tan*R.A12)**2 - C=R.A23**2+R.A33**2-(tan*R.A13)**2 - - D=2.0*(R.A21*R.A22+R.A31*R.A32-tan**2*R.A11*R.A12) - E=2.0*(R.A22*R.A23+R.A32*R.A33-tan**2*R.A12*R.A13) - F=2.0*(R.A23*R.A21+R.A33*R.A31-tan**2*R.A13*R.A11) - - G=2.0*(Pos2.y*R.A21+Pos2.z*R.A31-tan**2*Pos2.x*R.A11) - H=2.0*(Pos2.y*R.A22+Pos2.z*R.A32-tan**2*Pos2.x*R.A12) - J=2.0*(Pos2.y*R.A23+Pos2.z*R.A33-tan**2*Pos2.x*R.A13) - - K=Pos2.y**2+Pos2.z**2-(tan*Pos2.x)**2 - - return (A,B,C,D,E,F,G,H,J,K) - - - - - - - - - + Pos2 = R.multiply(Pos).negative() + + A = R.A21**2 + R.A31**2 - (tan * R.A11) ** 2 + B = R.A22**2 + R.A32**2 - (tan * R.A12) ** 2 + C = R.A23**2 + R.A33**2 - (tan * R.A13) ** 2 + + D = 2.0 * (R.A21 * R.A22 + R.A31 * R.A32 - tan**2 * R.A11 * R.A12) + E = 2.0 * (R.A22 * R.A23 + R.A32 * R.A33 - tan**2 * R.A12 * R.A13) + F = 2.0 * (R.A23 * R.A21 + R.A33 * R.A31 - tan**2 * R.A13 * R.A11) + + G = 2.0 * (Pos2.y * R.A21 + Pos2.z * R.A31 - tan**2 * Pos2.x * R.A11) + H = 2.0 * (Pos2.y * R.A22 + Pos2.z * R.A32 - tan**2 * Pos2.x * R.A12) + J = 2.0 * (Pos2.y * R.A23 + Pos2.z * R.A33 - tan**2 * Pos2.x * R.A13) + + K = Pos2.y**2 + Pos2.z**2 - (tan * Pos2.x) ** 2 + + return (A, B, C, D, E, F, G, H, J, K) diff --git a/src/geouned/GEOUNED/Utils/booleanFunction.py b/src/geouned/GEOUNED/Utils/booleanFunction.py index 4691cbb2..5cb886b6 100644 --- a/src/geouned/GEOUNED/Utils/booleanFunction.py +++ b/src/geouned/GEOUNED/Utils/booleanFunction.py @@ -1,714 +1,754 @@ import re -mostinner=re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses -number =re.compile(r"(?P[-+]?\d+)") -mix =re.compile(r"(?P([-+]?\d+|\[0+\]))") -TFX =re.compile(r"(?P[FTXo]+)") -PValue =re.compile(r"P\d+") -NValue =re.compile(r"N\d+") -conversion = {'T':True,'F':False,'X':None} +mostinner = re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses +number = re.compile(r"(?P[-+]?\d+)") +mix = re.compile(r"(?P([-+]?\d+|\[0+\]))") +TFX = re.compile(r"(?P[FTXo]+)") +PValue = re.compile(r"P\d+") +NValue = re.compile(r"N\d+") +conversion = {"T": True, "F": False, "X": None} + class BoolSequence: - def __init__(self,definition=None,operator=None) : - if definition : + def __init__(self, definition=None, operator=None): + if definition: self.elements = [] self.setDef(definition) - else: + else: self.elements = [] self.operator = operator - self.level = 0 + self.level = 0 def __str__(self): - out='{}['.format(self.operator) - if type(self.elements) is bool : return ' True ' if self.elements else ' False ' - for e in self.elements: - if type(e) is int or type(e) is bool or type(e) is str : - out += ' {} '.format(e) - else : - out += e.__str__() - - out += '] ' - return out - - def append(self,*seq): - for s in seq: - if type(s) is int : - level = -1 - if s in self.elements : - continue - elif -s in self.elements: - self.level = -1 - if self.operator == 'AND' : - self.elements = False + out = "{}[".format(self.operator) + if type(self.elements) is bool: + return " True " if self.elements else " False " + for e in self.elements: + if type(e) is int or type(e) is bool or type(e) is str: + out += " {} ".format(e) + else: + out += e.__str__() + + out += "] " + return out + + def append(self, *seq): + for s in seq: + if type(s) is int: + level = -1 + if s in self.elements: + continue + elif -s in self.elements: + self.level = -1 + if self.operator == "AND": + self.elements = False + else: + self.elements = True + return + elif type(s) is bool: + if self.operator == "AND" and s or self.operator == "OR" and not s: + continue else: - self.elements = True - return - elif type(s) is bool : - if self.operator == 'AND' and s or\ - self.operator == 'OR' and not s : - continue - else: - self.elements = s - self.level = -1 - return - else: - level = s.level - if type(s.elements) is bool: - if self.operator == 'AND' and not s.elements or\ - self.operator == 'OR' and s.elements : - self.level = -1 - self.elements = s.elements - return - else: - continue - - self.elements.append(s) - self.level = max(self.level,level+1) - - def assign(self,Seq): - if type(Seq) is bool : - self.operator == 'AND' - self.elements = Seq - self.level = -1 - return + self.elements = s + self.level = -1 + return + else: + level = s.level + if type(s.elements) is bool: + if ( + self.operator == "AND" + and not s.elements + or self.operator == "OR" + and s.elements + ): + self.level = -1 + self.elements = s.elements + return + else: + continue + + self.elements.append(s) + self.level = max(self.level, level + 1) + + def assign(self, Seq): + if type(Seq) is bool: + self.operator == "AND" + self.elements = Seq + self.level = -1 + return self.operator = Seq.operator self.elements = Seq.elements - self.level = Seq.level + self.level = Seq.level - def update(self,Seq,pos): - if len(pos)== 0: - self.assign(Seq) - return + def update(self, Seq, pos): + if len(pos) == 0: + self.assign(Seq) + return elif len(pos) == 1: - base = self + base = self else: - base = self.getElement(pos[:-1]) + base = self.getElement(pos[:-1]) indexes = pos[-1] indexes.sort() for i in reversed(indexes): - del (base.elements[i]) + del base.elements[i] - if type(Seq.elements) is bool : - base.elements = Seq.elements - base.level = -1 + if type(Seq.elements) is bool: + base.elements = Seq.elements + base.level = -1 else: - base.append(Seq) - base.joinOperators() + base.append(Seq) + base.joinOperators() self.clean(selfLevel=True) return - def getElement(self,pos): - if len(pos) == 1 : - return self.elements[pos[0]] + def getElement(self, pos): + if len(pos) == 1: + return self.elements[pos[0]] else: - return self.elements[pos[0]].getElement(pos[1:]) + return self.elements[pos[0]].getElement(pos[1:]) def copy(self): cp = BoolSequence() - cp.operator= self.operator + cp.operator = self.operator cp.level = self.level if type(self.elements) is bool: - cp.elements = self.elements + cp.elements = self.elements else: - for e in self.elements: - if type(e) is int : - cp.elements.append(e) - else: - cp.elements.append(e.copy()) - return cp - + for e in self.elements: + if type(e) is int: + cp.elements.append(e) + else: + cp.elements.append(e.copy()) + return cp + def getComplementary(self): - c = BoolSequence(operator=self.compOperator()) - c.level = self.level + c = BoolSequence(operator=self.compOperator()) + c.level = self.level - if self.level == 0: - for e in self.elements: - c.elements.append(-e) - return c - else: - self.groupSingle() - for e in self.elements: - c.elements.append( e.getComplementary() ) - return c + if self.level == 0: + for e in self.elements: + c.elements.append(-e) + return c + else: + self.groupSingle() + for e in self.elements: + c.elements.append(e.getComplementary()) + return c - def compOperator(self): - if self.operator == 'AND': - return 'OR' - else: - return 'AND' - - def simplify(self,CT,depth=0): - if self.level > 0 : - for seq in self.elements : - seq.simplify(CT,depth+1) - self.clean() - self.joinOperators() - self.levelUpdate() - - if type(self.elements) is not bool and (self.level > 0 or len(self.elements) > 1) : - levIn = self.level - self.simplifySequence(CT) - - if self.level > levIn and depth < 10: - self.simplify(CT,depth+1) - - - def simplifySequence(self,CT): - if self.level < 1 and CT is None: - self.clean() - return - - surfNames = self.getSurfacesNumbers() - if not surfNames : return - - newNames = surfNames - for valname in surfNames: - if valname in newNames: - - if CT is None : - trueSet = {abs(valname) : True } - falseSet = {abs(valname) : False } - else: - trueSet,falseSet = CT.getConstraintSet(valname) - - if not self.doFactorize(valname,trueSet,falseSet) : continue - self.factorize(valname,trueSet,falseSet) - if type(self.elements) is bool: return - newNames = self.getSurfacesNumbers() - - - def doFactorize(self,valname,trueSet,falseSet): - - if self.level > 0 : return True - if trueSet is None and falseSet is None : - print(f'{valname} is not true nor false') - return False - if trueSet is None or falseSet is None : - return True - - valSet = self.getSurfacesNumbers() - TSet = set(trueSet.keys()) & valSet - FSet = set(falseSet.keys()) & valSet - - if len(TSet) == 1 and len(FSet) == 1 : return False - - value = None - for val in self.elements: - if abs(val) == valname : - value = val - break - - if value is None : return False - - if len(TSet) == 1: - if self.operator == 'AND': - # if value > 0 and TSet[valname] or value < 0 and not TSet[valname] : return False - if value > 0 : return False # TrueSet[Valname] always True - else: - #if value < 0 and TSet[valname] or value > 0 and not TSet[valname] : return False - if value < 0 : return False - - elif len(FSet) == 1: - if self.operator == 'AND': - #if value > 0 and FSet[valname] or value < 0 and not FSet[valname] : return False - if value < 0 : return False - else: - # if value < 0 and FSet[valname] or value > 0 and not FSet[valname] : return False - if value > 0 : return False - - return True - - - - - # check if level 0 sequence have oposite value a & -a = 0 , a|-a = 1 - # return the value of the sequence None(unknown), True, False - def check(self,level0 = False): - if type(self.elements) is bool : return self.elements - if self.level == 0: - signedSurf = set(self.elements) - surfname = self.getSurfacesNumbers() - if len(signedSurf) == len(surfname) : return None # means same surface has not positive and negative value - elif self.operator == 'AND' : - self.elements = False - self.level = -1 - return False - else: - self.elements = True - self.level = -1 - return True - elif not level0: - self.groupSingle() - noneVal = False - for e in reversed(self.elements): - e.check() - if type(e.elements) is bool : - res = e.elements - else: - res = None - - if res is None : noneVal = True - elif self.operator == 'AND' and res is False : - self.level = -1 - self.elements = False - return False - elif self.operator == 'OR' and res is True : - self.level = -1 - self.elements = True - return True - else: - self.elements.remove(e) - - if noneVal : return None - elif self.operator == 'AND' : - self.level = -1 - self.elements = True - return True - else: - self.level = -1 - self.elements = False - return False - - - def substitute(self,var,val): - if val is None : return - if type(self.elements) is bool: return - name = abs(var) - ic = len(self.elements) - for e in reversed(self.elements): - ic -= 1 - if type(e) is int: - if abs(e) == name : - if type(val) is int : - if name == e : self.elements[ic] = val - else : self.elements[ic] = -val - - else : - if name == e : boolValue = val - else : boolValue = not val - - if self.operator == 'AND' and not boolValue : - self.elements = False - self.level = -1 - return - elif self.operator == 'OR' and boolValue : - self.elements = True - self.level = -1 - return - else: - self.elements.remove(e) + if self.operator == "AND": + return "OR" + else: + return "AND" + + def simplify(self, CT, depth=0): + if self.level > 0: + for seq in self.elements: + seq.simplify(CT, depth + 1) + self.clean() + self.joinOperators() + self.levelUpdate() + + if type(self.elements) is not bool and ( + self.level > 0 or len(self.elements) > 1 + ): + levIn = self.level + self.simplifySequence(CT) + + if self.level > levIn and depth < 10: + self.simplify(CT, depth + 1) + + def simplifySequence(self, CT): + if self.level < 1 and CT is None: + self.clean() + return + + surfNames = self.getSurfacesNumbers() + if not surfNames: + return + + newNames = surfNames + for valname in surfNames: + if valname in newNames: + + if CT is None: + trueSet = {abs(valname): True} + falseSet = {abs(valname): False} + else: + trueSet, falseSet = CT.getConstraintSet(valname) + + if not self.doFactorize(valname, trueSet, falseSet): + continue + self.factorize(valname, trueSet, falseSet) + if type(self.elements) is bool: + return + newNames = self.getSurfacesNumbers() + + def doFactorize(self, valname, trueSet, falseSet): + + if self.level > 0: + return True + if trueSet is None and falseSet is None: + print(f"{valname} is not true nor false") + return False + if trueSet is None or falseSet is None: + return True + + valSet = self.getSurfacesNumbers() + TSet = set(trueSet.keys()) & valSet + FSet = set(falseSet.keys()) & valSet + + if len(TSet) == 1 and len(FSet) == 1: + return False + + value = None + for val in self.elements: + if abs(val) == valname: + value = val + break + + if value is None: + return False + + if len(TSet) == 1: + if self.operator == "AND": + # if value > 0 and TSet[valname] or value < 0 and not TSet[valname] : return False + if value > 0: + return False # TrueSet[Valname] always True + else: + # if value < 0 and TSet[valname] or value > 0 and not TSet[valname] : return False + if value < 0: + return False + + elif len(FSet) == 1: + if self.operator == "AND": + # if value > 0 and FSet[valname] or value < 0 and not FSet[valname] : return False + if value < 0: + return False + else: + # if value < 0 and FSet[valname] or value > 0 and not FSet[valname] : return False + if value > 0: + return False + + return True + + # check if level 0 sequence have oposite value a & -a = 0 , a|-a = 1 + # return the value of the sequence None(unknown), True, False + def check(self, level0=False): + if type(self.elements) is bool: + return self.elements + if self.level == 0: + signedSurf = set(self.elements) + surfname = self.getSurfacesNumbers() + if len(signedSurf) == len(surfname): + return None # means same surface has not positive and negative value + elif self.operator == "AND": + self.elements = False + self.level = -1 + return False + else: + self.elements = True + self.level = -1 + return True + elif not level0: + self.groupSingle() + noneVal = False + for e in reversed(self.elements): + e.check() + if type(e.elements) is bool: + res = e.elements + else: + res = None + + if res is None: + noneVal = True + elif self.operator == "AND" and res is False: + self.level = -1 + self.elements = False + return False + elif self.operator == "OR" and res is True: + self.level = -1 + self.elements = True + return True + else: + self.elements.remove(e) + + if noneVal: + return None + elif self.operator == "AND": + self.level = -1 + self.elements = True + return True + else: + self.level = -1 + self.elements = False + return False + + def substitute(self, var, val): + if val is None: + return + if type(self.elements) is bool: + return + name = abs(var) + ic = len(self.elements) + for e in reversed(self.elements): + ic -= 1 + if type(e) is int: + if abs(e) == name: + if type(val) is int: + if name == e: + self.elements[ic] = val + else: + self.elements[ic] = -val + + else: + if name == e: + boolValue = val + else: + boolValue = not val + + if self.operator == "AND" and not boolValue: + self.elements = False + self.level = -1 + return + elif self.operator == "OR" and boolValue: + self.elements = True + self.level = -1 + return + else: + self.elements.remove(e) + + else: + e.substitute(var, val) - else: - e.substitute(var,val) + if self.elements == []: + self.elements = True if self.operator == "AND" else False + self.level = -1 + return - if self.elements == [] : - self.elements = True if self.operator == 'AND' else False - self.level = -1 - return - - self.clean(selfLevel = True) - self.check(level0 = True) - self.joinOperators(selfLevel = True) + self.clean(selfLevel=True) + self.check(level0=True) + self.joinOperators(selfLevel=True) # remove sequence whom elements are boolean values instead of list - def clean(self,selfLevel = False): - if type(self.elements) is bool : return self.elements - for e in reversed(self.elements) : - if type(e) is int : continue - eVal = e if selfLevel else e.clean() - if type(eVal) is not bool : eVal = eVal.elements - - if type(eVal) is bool: - if eVal and self.operator == 'OR' : - self.elements = True - self.level = -1 - return True - elif not eVal and self.operator == 'AND' : - self.elements = False - self.level = -1 - return False - self.elements.remove(e) - - if self.elements == [] : - if self.operator == 'OR' : self.elements = False - else : self.elements = True - self.level = -1 - return self.elements + def clean(self, selfLevel=False): + if type(self.elements) is bool: + return self.elements + for e in reversed(self.elements): + if type(e) is int: + continue + eVal = e if selfLevel else e.clean() + if type(eVal) is not bool: + eVal = eVal.elements + + if type(eVal) is bool: + if eVal and self.operator == "OR": + self.elements = True + self.level = -1 + return True + elif not eVal and self.operator == "AND": + self.elements = False + self.level = -1 + return False + self.elements.remove(e) + + if self.elements == []: + if self.operator == "OR": + self.elements = False + else: + self.elements = True + self.level = -1 + return self.elements else: - return self - + return self # join redundant operators in sequence - def joinOperators(self,selfLevel = False): - if type(self.elements) is bool: return + def joinOperators(self, selfLevel=False): + if type(self.elements) is bool: + return self.clean(selfLevel=True) self.levelUpdate() - if self.level == 0 : return + if self.level == 0: + return self.groupSingle() ANDop = [] - ORop = [] - + ORop = [] + for e in self.elements: - if e.operator == 'AND': ANDop.append(e) - else : ORop.append(e) - - if len(ANDop) > 1 and self.operator == 'AND': - newSeq = BoolSequence(operator='AND') - for s in ANDop : - newSeq.elements.extend(s.elements) - self.elements.remove(s) - newSeq.levelUpdate() - self.append(newSeq) - - - elif len(ORop) > 1 and self.operator == 'OR': - newSeq = BoolSequence(operator='OR') - for s in ORop : - newSeq.elements.extend(s.elements) - self.elements.remove(s) - newSeq.levelUpdate() - self.append(newSeq) - - if self.level > 0 and len(self.elements)==1 : - self.operator = self.elements[0].operator - self.elements[:] = self.elements[0].elements[:] - self.level -= 1 - self.joinOperators() - - if self.level == 0 : - self.check() - return - - if not selfLevel : - if type(self.elements) is bool : return - for e in self.elements: - e.joinOperators() - - - def getSubSequence(self,setIn): - if type(setIn) is set : - valSet = setIn - elif type(setIn) is int : - valSet = {setIn} + if e.operator == "AND": + ANDop.append(e) + else: + ORop.append(e) + + if len(ANDop) > 1 and self.operator == "AND": + newSeq = BoolSequence(operator="AND") + for s in ANDop: + newSeq.elements.extend(s.elements) + self.elements.remove(s) + newSeq.levelUpdate() + self.append(newSeq) + + elif len(ORop) > 1 and self.operator == "OR": + newSeq = BoolSequence(operator="OR") + for s in ORop: + newSeq.elements.extend(s.elements) + self.elements.remove(s) + newSeq.levelUpdate() + self.append(newSeq) + + if self.level > 0 and len(self.elements) == 1: + self.operator = self.elements[0].operator + self.elements[:] = self.elements[0].elements[:] + self.level -= 1 + self.joinOperators() + + if self.level == 0: + self.check() + return + + if not selfLevel: + if type(self.elements) is bool: + return + for e in self.elements: + e.joinOperators() + + def getSubSequence(self, setIn): + if type(setIn) is set: + valSet = setIn + elif type(setIn) is int: + valSet = {setIn} else: - valSet = set(setIn.keys()) + valSet = set(setIn.keys()) - if self.level == 0 : return ([],self) + if self.level == 0: + return ([], self) position = [] - subSeq = BoolSequence(operator = self.operator) - - for pos,e in enumerate(self.elements) : - surf = e.getSurfacesNumbers() - if len(surf&valSet) != 0: - subSeq.append(e) - position.append(pos) + subSeq = BoolSequence(operator=self.operator) - if len(position) == 1 and subSeq.elements[0].level > 0 : - subList,subSeq = subSeq.elements[0].getSubSequence(valSet) - subList.insert(0,position[0]) - else : - subList = [position] + for pos, e in enumerate(self.elements): + surf = e.getSurfacesNumbers() + if len(surf & valSet) != 0: + subSeq.append(e) + position.append(pos) - return subList,subSeq + if len(position) == 1 and subSeq.elements[0].level > 0: + subList, subSeq = subSeq.elements[0].getSubSequence(valSet) + subList.insert(0, position[0]) + else: + subList = [position] + return subList, subSeq - def factorize(self,valname,trueSet,falseSet): + def factorize(self, valname, trueSet, falseSet): - if trueSet is None: # valname cannot take True value - falseFunc = self.evaluate(falseSet) - self.assign(falseFunc) - return True + if trueSet is None: # valname cannot take True value + falseFunc = self.evaluate(falseSet) + self.assign(falseFunc) + return True - if falseSet is None: # valname cannot take false value - trueFunc = self.evaluate(trueSet) - self.assign(trueFunc) - return True + if falseSet is None: # valname cannot take false value + trueFunc = self.evaluate(trueSet) + self.assign(trueFunc) + return True valSet = set(trueSet.keys()) valSet.update(falseSet.keys()) - pos,subSeq = self.getSubSequence(valSet) + pos, subSeq = self.getSubSequence(valSet) updt = True - if len(pos) == 0 : - subSeq = self - updt = False + if len(pos) == 0: + subSeq = self + updt = False - trueFunc = subSeq.evaluate(trueSet) + trueFunc = subSeq.evaluate(trueSet) - falseFunc = subSeq.evaluate(falseSet) - if trueFunc == False : - newSeq = BoolSequence(operator='AND') - if falseFunc == True : - newSeq.append(-valname) + if trueFunc == False: + newSeq = BoolSequence(operator="AND") + if falseFunc == True: + newSeq.append(-valname) elif falseFunc == False: - newSeq.elements = False - newSeq.level = -1 + newSeq.elements = False + newSeq.level = -1 else: - newSeq.append(-valname,falseFunc) - newSeq.joinOperators(selfLevel=True) + newSeq.append(-valname, falseFunc) + newSeq.joinOperators(selfLevel=True) - if updt : - self.update(newSeq,pos) + if updt: + self.update(newSeq, pos) else: - self.assign(newSeq) + self.assign(newSeq) return True elif trueFunc == True: - newSeq = BoolSequence(operator='OR') - if falseFunc == True : - newSeq.elements = True - newSeq.level = -1 + newSeq = BoolSequence(operator="OR") + if falseFunc == True: + newSeq.elements = True + newSeq.level = -1 elif falseFunc == False: - newSeq.append(valname) + newSeq.append(valname) else: - newSeq.append(valname,falseFunc) - newSeq.joinOperators(selfLevel=True) + newSeq.append(valname, falseFunc) + newSeq.joinOperators(selfLevel=True) - if updt : - self.update(newSeq,pos) + if updt: + self.update(newSeq, pos) else: - self.assign(newSeq) + self.assign(newSeq) return True - if falseFunc == False : - newSeq = BoolSequence(operator='AND') - if trueFunc == True : - newSeq.append(valname) + if falseFunc == False: + newSeq = BoolSequence(operator="AND") + if trueFunc == True: + newSeq.append(valname) elif trueFunc == False: - newSeq.elements = False - newSeq.level = -1 + newSeq.elements = False + newSeq.level = -1 else: - newSeq.append(valname,trueFunc) - newSeq.joinOperators(selfLevel=True) - if updt : - self.update(newSeq,pos) + newSeq.append(valname, trueFunc) + newSeq.joinOperators(selfLevel=True) + if updt: + self.update(newSeq, pos) else: - self.assign(newSeq) + self.assign(newSeq) return True elif falseFunc == True: - newSeq = BoolSequence(operator='OR') - if trueFunc == True : - newSeq.elements = True - newSeq.level = -1 + newSeq = BoolSequence(operator="OR") + if trueFunc == True: + newSeq.elements = True + newSeq.level = -1 elif trueFunc == False: - newSeq.append(-valname) + newSeq.append(-valname) else: - newSeq.append(-valname,trueFunc) - newSeq.joinOperators(selfLevel=True) - if updt : - self.update(newSeq,pos) + newSeq.append(-valname, trueFunc) + newSeq.joinOperators(selfLevel=True) + if updt: + self.update(newSeq, pos) else: - self.assign(newSeq) + self.assign(newSeq) return True + def evaluate(self, valueSet): - def evaluate(self,valueSet): - - if type(self.elements) is bool : return self.elements + if type(self.elements) is bool: + return self.elements self.groupSingle() newSeq = self.copy() - for name,value in valueSet.items(): - newSeq.substitute(name,value) - if type(newSeq.elements) is bool : - return newSeq.elements - + for name, value in valueSet.items(): + newSeq.substitute(name, value) + if type(newSeq.elements) is bool: + return newSeq.elements + return newSeq.elements if type(newSeq.elements) is bool else newSeq + def setDef(self, expression): + terms, operator = outterTerms(expression) + self.operator = operator + self.level = 0 + lev0Seq = set() + lev0SeqAbs = set() + for t in terms: + if isInteger(t): + val = int(t.strip("(").strip(")")) + lev0Seq.add(val) + lev0SeqAbs.add(abs(val)) + # self.elements.append(int(t.strip('(').strip(')'))) + else: + x = BoolSequence(t) + self.level = max(x.level + 1, self.level) + self.append(x) + + # check if in integer sequence there is surface sequence s -s + if len(lev0Seq) != len(lev0SeqAbs): + if self.operator == "AND": + self.elements = False + else: + self.elements = True + self.level = -1 + else: + self.append(*lev0Seq) - def setDef(self,expression): - terms,operator = outterTerms(expression) - self.operator = operator - self.level = 0 - lev0Seq = set() - lev0SeqAbs = set() - for t in terms : - if isInteger(t) : - val = int(t.strip('(').strip(')')) - lev0Seq.add( val ) - lev0SeqAbs.add(abs(val)) - #self.elements.append(int(t.strip('(').strip(')'))) - else: - x = BoolSequence(t) - self.level = max(x.level+1,self.level) - self.append(x) - - # check if in integer sequence there is surface sequence s -s - if len(lev0Seq) != len(lev0SeqAbs) : - if self.operator == 'AND' : - self.elements = False - else: - self.elements = True - self.level = -1 - else: - self.append(*lev0Seq) - - self.groupSingle() + self.groupSingle() def groupSingle(self): - if self.level == 0 : return - if type(self.elements) is bool : return - group = [] - for e in reversed(self.elements): - if type(e) is int : - group.append(e) - self.elements.remove(e) - elif e.level==0 and len(e.elements) == 1 : - group.append(e.elements[0]) - self.elements.remove(e) - - - if not group : return - seq = BoolSequence() - seq.elements.extend(group) - seq.operator = self.operator - seq.level = 0 - self.elements.insert(0,seq) - + if self.level == 0: + return + if type(self.elements) is bool: + return + group = [] + for e in reversed(self.elements): + if type(e) is int: + group.append(e) + self.elements.remove(e) + elif e.level == 0 and len(e.elements) == 1: + group.append(e.elements[0]) + self.elements.remove(e) + + if not group: + return + seq = BoolSequence() + seq.elements.extend(group) + seq.operator = self.operator + seq.level = 0 + self.elements.insert(0, seq) def getSurfacesNumbers(self): - if type(self.elements) is bool : return tuple() + if type(self.elements) is bool: + return tuple() surf = set() for e in self.elements: - if type(e) is int : + if type(e) is int: surf.add(abs(e)) - else: + else: surf.update(e.getSurfacesNumbers()) - return surf + return surf def levelUpdate(self): - if type(self.elements) is bool : - self.level = 0 - return - - self.level = 0 - for e in self.elements: - if type(e) is int : continue - e.levelUpdate() - self.level = max(e.level+1,self.level) - -def insertInSequence(Seq,trgt,nsrf,operator): - - if operator == 'OR' : - newSeq = BoolSequence(f'{trgt}:{nsrf}') + if type(self.elements) is bool: + self.level = 0 + return + + self.level = 0 + for e in self.elements: + if type(e) is int: + continue + e.levelUpdate() + self.level = max(e.level + 1, self.level) + + +def insertInSequence(Seq, trgt, nsrf, operator): + + if operator == "OR": + newSeq = BoolSequence(f"{trgt}:{nsrf}") else: - newSeq = BoolSequence(f'{trgt} {nsrf}') + newSeq = BoolSequence(f"{trgt} {nsrf}") - substituteIntegerElement(Seq,trgt,newSeq) + substituteIntegerElement(Seq, trgt, newSeq) Seq.levelUpdate() - #Seq.joinOperators() - - -def substituteIntegerElement(Seq,target,newElement): - for i,e in enumerate(Seq.elements): - if type(e) is int: - if e == target : - Seq.elements[i] = newElement - else: - substituteIntegerElement(e,target,newElement) - - -def outterTerms(expression,value='number'): - if value == 'number' : - #reValue = number - reValue = mix - nullVal = '0' - else: - reValue = TFX - nullVal = 'o' - - expr = expression - - - # Loop until no redundant parentheses are found - cont = True - - while cont: + # Seq.joinOperators() + + +def substituteIntegerElement(Seq, target, newElement): + for i, e in enumerate(Seq.elements): + if type(e) is int: + if e == target: + Seq.elements[i] = newElement + else: + substituteIntegerElement(e, target, newElement) + + +def outterTerms(expression, value="number"): + if value == "number": + # reValue = number + reValue = mix + nullVal = "0" + else: + reValue = TFX + nullVal = "o" + + expr = expression + + # Loop until no redundant parentheses are found + cont = True + + while cont: # Loop over most inner parentheses pos = 0 cont = False - while True : - m = mostinner.search(expr,pos) - if not m : break - cont = True - if redundant(m,expr): - # remove redundant parentheses - expr = expr[:m.start()]+ ' ' + expr[m.start()+1:m.end()-1]+ ' ' + expr[m.end():] - else: - # replace no redundant parentheses by 0 and : by ; - zeros = '[' + nullVal* (m.end()-m.start()-2) + ']' - expr = expr[:m.start()] + zeros + expr[m.end():] - - pos = m.end() - - if ':' in expr : - terms = [] - pos = 0 - while True : - newpos = expr.find(':',pos) - if newpos == -1 : - terms.append(expression[pos:].strip()) - break - terms.append(expression[pos:newpos].strip()) - pos = newpos + 1 - return (terms,'OR') - else: - terms = [] - pos = 0 - while True: - m = reValue.search(expr,pos) - if not m : break - terms.append(expression[m.start():m.end()]) - pos = m.end() - return (terms,'AND') - - -def redundant(m,geom): - """ check if the inner parentheses are redundant """ - term = m.group() - - # Find first valid character at the left of the parenthese - leftOK= True - left = m.start()-1 - while left > -1: - if geom[left] in ('\n','C','$',' '): - left -= 1 - else: - if geom[left] not in ('(',':') : leftOK = False - break - - # check if no ':' (or) are inside the parenthese - # if not, parentheses are redundants - if (term.find(':') == -1) : return True - - # Find first valid character at the right of the parenthese - rightOK= True - right = m.end() - while right < len(geom) : - if geom[right] in ('\n','C','$',' '): - right += 1 - else: - if geom[right] not in (')',':') : rightOK = False - break - - # if parentheses are like: - # {( or : } ( ....... ) {) or :} - # parentheses are redundants - - if leftOK and rightOK : - return True - else: - return False + while True: + m = mostinner.search(expr, pos) + if not m: + break + cont = True + if redundant(m, expr): + # remove redundant parentheses + expr = ( + expr[: m.start()] + + " " + + expr[m.start() + 1 : m.end() - 1] + + " " + + expr[m.end() :] + ) + else: + # replace no redundant parentheses by 0 and : by ; + zeros = "[" + nullVal * (m.end() - m.start() - 2) + "]" + expr = expr[: m.start()] + zeros + expr[m.end() :] + + pos = m.end() + + if ":" in expr: + terms = [] + pos = 0 + while True: + newpos = expr.find(":", pos) + if newpos == -1: + terms.append(expression[pos:].strip()) + break + terms.append(expression[pos:newpos].strip()) + pos = newpos + 1 + return (terms, "OR") + else: + terms = [] + pos = 0 + while True: + m = reValue.search(expr, pos) + if not m: + break + terms.append(expression[m.start() : m.end()]) + pos = m.end() + return (terms, "AND") + + +def redundant(m, geom): + """check if the inner parentheses are redundant""" + term = m.group() + + # Find first valid character at the left of the parenthese + leftOK = True + left = m.start() - 1 + while left > -1: + if geom[left] in ("\n", "C", "$", " "): + left -= 1 + else: + if geom[left] not in ("(", ":"): + leftOK = False + break + + # check if no ':' (or) are inside the parenthese + # if not, parentheses are redundants + if term.find(":") == -1: + return True + + # Find first valid character at the right of the parenthese + rightOK = True + right = m.end() + while right < len(geom): + if geom[right] in ("\n", "C", "$", " "): + right += 1 + else: + if geom[right] not in (")", ":"): + rightOK = False + break + + # if parentheses are like: + # {( or : } ( ....... ) {) or :} + # parentheses are redundants + + if leftOK and rightOK: + return True + else: + return False + def isInteger(x): - try : - int(x.strip('(').strip(')')) - return True + try: + int(x.strip("(").strip(")")) + return True except: - return False + return False diff --git a/src/geouned/GEOUNED/Void/Void.py b/src/geouned/GEOUNED/Void/Void.py index c7805e33..4eae1802 100644 --- a/src/geouned/GEOUNED/Void/Void.py +++ b/src/geouned/GEOUNED/Void/Void.py @@ -10,175 +10,189 @@ from .VoidBoxClass import VoidBox -def voidGeneration(MetaList,EnclosureList,Surfaces,UniverseBox,setting,init): +def voidGeneration(MetaList, EnclosureList, Surfaces, UniverseBox, setting, init): voidList = [] - + if EnclosureList: - NestedEnclosure = LF.setEnclosureLevels(EnclosureList) - VF.assignEnclosure(MetaList,NestedEnclosure) - - # add to Metalist Level 1 enclosures, remove from list material cells totally embedded in Level 1 enclosures - newMetaList = VF.selectSolids(MetaList,NestedEnclosure[0],UniverseBox) - else: - newMetaList = MetaList[:] - NestedEnclosure = [] - - Box = Part.makeBox(UniverseBox.XLength, UniverseBox.YLength, UniverseBox.ZLength, - FreeCAD.Vector(UniverseBox.XMin, UniverseBox.YMin, UniverseBox.ZMin), - FreeCAD.Vector(0,0,1)) - - EnclosureBox = GEOUNED_Solid(None,Box) - if setting['voidMat']: - voidMat = setting['voidMat'] - EnclosureBox.setMaterial(voidMat[0],voidMat[1],voidMat[2]) - + NestedEnclosure = LF.setEnclosureLevels(EnclosureList) + VF.assignEnclosure(MetaList, NestedEnclosure) + + # add to Metalist Level 1 enclosures, remove from list material cells totally embedded in Level 1 enclosures + newMetaList = VF.selectSolids(MetaList, NestedEnclosure[0], UniverseBox) + else: + newMetaList = MetaList[:] + NestedEnclosure = [] + + Box = Part.makeBox( + UniverseBox.XLength, + UniverseBox.YLength, + UniverseBox.ZLength, + FreeCAD.Vector(UniverseBox.XMin, UniverseBox.YMin, UniverseBox.ZMin), + FreeCAD.Vector(0, 0, 1), + ) + + EnclosureBox = GEOUNED_Solid(None, Box) + if setting["voidMat"]: + voidMat = setting["voidMat"] + EnclosureBox.setMaterial(voidMat[0], voidMat[1], voidMat[2]) # get voids in 0 Level Enclosure (original Universe) # if exist Level 1 enclosures are considered as material cells - print('Build Void highest enclosure') - - voids = GetVoidDef(newMetaList,Surfaces,EnclosureBox,setting,Lev0=True) + print("Build Void highest enclosure") + + voids = GetVoidDef(newMetaList, Surfaces, EnclosureBox, setting, Lev0=True) voidList.append(voids) # Perform enclosure void # Loop until the lowest enclosure level - - for i,Level in enumerate(NestedEnclosure) : - - print('Build Void highest enclosure') - for j,encl in enumerate(Level): - if encl.CellType == 'envelope': continue - newMetaList = VF.selectSolids(MetaList,encl.SonEnclosures,encl) - print('Build Void enclosure {} in enclosure level {}'.format(j,i+1)) + + for i, Level in enumerate(NestedEnclosure): + + print("Build Void highest enclosure") + for j, encl in enumerate(Level): + if encl.CellType == "envelope": + continue + newMetaList = VF.selectSolids(MetaList, encl.SonEnclosures, encl) + print("Build Void enclosure {} in enclosure level {}".format(j, i + 1)) # select solids overlapping current enclosure "encl", and lower level enclosures - voids = GetVoidDef(newMetaList,Surfaces,encl,setting) + voids = GetVoidDef(newMetaList, Surfaces, encl, setting) voidList.append(voids) - - - voidList.append( setGraveyardCell(Surfaces,UniverseBox) ) - - return VF.updateVoidList(init,voidList,NestedEnclosure,setting['sortEnclosure']) - - -def GetVoidDef(MetaList,Surfaces,Enclosure,setting,Lev0=False): - - maxsurf = setting['maxSurf'] - maxbracket = setting['maxBracket'] - minSize = setting['minVoidSize'] - - if 'full' in setting['simplify'].lower() : - simplifyVoid = 'full' - elif 'void' in setting['simplify'].lower() : - simplifyVoid = 'diag' + + voidList.append(setGraveyardCell(Surfaces, UniverseBox)) + + return VF.updateVoidList(init, voidList, NestedEnclosure, setting["sortEnclosure"]) + + +def GetVoidDef(MetaList, Surfaces, Enclosure, setting, Lev0=False): + + maxsurf = setting["maxSurf"] + maxbracket = setting["maxBracket"] + minSize = setting["minVoidSize"] + + if "full" in setting["simplify"].lower(): + simplifyVoid = "full" + elif "void" in setting["simplify"].lower(): + simplifyVoid = "diag" else: - simplifyVoid = 'no' + simplifyVoid = "no" - if Lev0 : - Universe = VoidBox(MetaList,Enclosure.BoundBox) - else: - Universe = VoidBox(MetaList,Enclosure.CADSolid) + if Lev0: + Universe = VoidBox(MetaList, Enclosure.BoundBox) + else: + Universe = VoidBox(MetaList, Enclosure.CADSolid) Initial = [Universe] - VoidDef = [] + VoidDef = [] iloop = 0 while iloop < 50: - Temp = [] - iloop += 1 - nvoid = len(Initial) - print('Loop, Box to Split :',iloop,nvoid) - - for iz,z in enumerate(Initial): - nsurfaces,nbrackets = z.getNumbers() - if opt.verbose : print('{} {}/{} {} {}'.format(iloop,iz+1,nvoid,nsurfaces,nbrackets)) - - if nsurfaces > maxsurf and nbrackets > maxbracket: - newspace = z.Split(minSize) - else: - newspace = None - - if type(newspace) is tuple : - Temp.extend(newspace) - else: -# if len(z.Objects) >= 50 : z.refine() - boxDim = (z.BoundBox.XMin*0.1,z.BoundBox.XMax*0.1, - z.BoundBox.YMin*0.1,z.BoundBox.YMax*0.1, - z.BoundBox.ZMin*0.1,z.BoundBox.ZMax*0.1) - - print('build complementary {} {}'.format(iloop,iz)) - - cell,CellIn = z.getVoidComplementary(Surfaces,simplify=simplifyVoid) - if cell is not None : - VoidCell = (cell,(boxDim,CellIn)) - VoidDef.append(VoidCell) - - Initial = Temp - if len(Temp) == 0 :break + Temp = [] + iloop += 1 + nvoid = len(Initial) + print("Loop, Box to Split :", iloop, nvoid) + + for iz, z in enumerate(Initial): + nsurfaces, nbrackets = z.getNumbers() + if opt.verbose: + print( + "{} {}/{} {} {}".format(iloop, iz + 1, nvoid, nsurfaces, nbrackets) + ) + + if nsurfaces > maxsurf and nbrackets > maxbracket: + newspace = z.Split(minSize) + else: + newspace = None + + if type(newspace) is tuple: + Temp.extend(newspace) + else: + # if len(z.Objects) >= 50 : z.refine() + boxDim = ( + z.BoundBox.XMin * 0.1, + z.BoundBox.XMax * 0.1, + z.BoundBox.YMin * 0.1, + z.BoundBox.YMax * 0.1, + z.BoundBox.ZMin * 0.1, + z.BoundBox.ZMax * 0.1, + ) + + print("build complementary {} {}".format(iloop, iz)) + + cell, CellIn = z.getVoidComplementary(Surfaces, simplify=simplifyVoid) + if cell is not None: + VoidCell = (cell, (boxDim, CellIn)) + VoidDef.append(VoidCell) + + Initial = Temp + if len(Temp) == 0: + break voidList = [] - for i,vcell in enumerate(VoidDef): - mVoid = GEOUNED_Solid(i) - mVoid.Void = True - mVoid.CellType = 'void' - mVoid.setDefinition(vcell[0],simplify=True) - mVoid.setMaterial(Enclosure.Material,Enclosure.Rho,Enclosure.MatInfo) - mVoid.setDilution(Enclosure.Dilution) - - mVoid.__commentInfo__ = vcell[1] - - voidList.append(mVoid) - + for i, vcell in enumerate(VoidDef): + mVoid = GEOUNED_Solid(i) + mVoid.Void = True + mVoid.CellType = "void" + mVoid.setDefinition(vcell[0], simplify=True) + mVoid.setMaterial(Enclosure.Material, Enclosure.Rho, Enclosure.MatInfo) + mVoid.setDilution(Enclosure.Dilution) + + mVoid.__commentInfo__ = vcell[1] + + voidList.append(mVoid) + return voidList -def setGraveyardCell(Surfaces,UniverseBox): - Universe = VoidBox([],UniverseBox) - externalBox = getUniverseComplementary(Universe,Surfaces) +def setGraveyardCell(Surfaces, UniverseBox): + Universe = VoidBox([], UniverseBox) + + externalBox = getUniverseComplementary(Universe, Surfaces) center = UniverseBox.Center - radius = 0.51*UniverseBox.DiagonalLength - sphere = GEOUNED_Surface(('Sphere',(center,radius)),UniverseBox) - id,exist = Surfaces.addSphere(sphere) + radius = 0.51 * UniverseBox.DiagonalLength + sphere = GEOUNED_Surface(("Sphere", (center, radius)), UniverseBox) + id, exist = Surfaces.addSphere(sphere) sphdef = BoolSequence(str(-id)) - sphdef.operator = 'AND' + sphdef.operator = "AND" sphdef.append(externalBox) notsph = BoolSequence(str(id)) - - mVoidSphIn = GEOUNED_Solid(0) - mVoidSphIn.Void = True - mVoidSphIn.CellType = 'void' + + mVoidSphIn = GEOUNED_Solid(0) + mVoidSphIn.Void = True + mVoidSphIn.CellType = "void" mVoidSphIn.setDefinition(sphdef) - mVoidSphIn.setMaterial(0,0,'Graveyard_in') + mVoidSphIn.setMaterial(0, 0, "Graveyard_in") mVoidSphIn.__commentInfo__ = None - mVoidSphOut = GEOUNED_Solid(1) + mVoidSphOut = GEOUNED_Solid(1) mVoidSphOut.Void = True - mVoidSphOut.CellType = 'void' + mVoidSphOut.CellType = "void" mVoidSphOut.setDefinition(notsph) - mVoidSphOut.setMaterial(0,0,'Graveyard') + mVoidSphOut.setMaterial(0, 0, "Graveyard") mVoidSphOut.__commentInfo__ = None - return (mVoidSphIn,mVoidSphOut) + return (mVoidSphIn, mVoidSphOut) -def getUniverseComplementary(Universe,Surfaces): - Def = BoolSequence(operator='OR') +def getUniverseComplementary(Universe, Surfaces): + Def = BoolSequence(operator="OR") for p in Universe.getBoundPlanes(): - id,exist = Surfaces.addPlane(p) - if not exist : - Def.elements.append(-id) - else: - s = Surfaces.getSurface(id) - if isOposite(p.Surf.Axis,s.Surf.Axis): - Def.elements.append(id) - else: - Def.elements.append(-id) - return Def - + id, exist = Surfaces.addPlane(p) + if not exist: + Def.elements.append(-id) + else: + s = Surfaces.getSurface(id) + if isOposite(p.Surf.Axis, s.Surf.Axis): + Def.elements.append(id) + else: + Def.elements.append(-id) + return Def + + def voidCommentLine(CellInfo): - boxDef,cellIn = CellInfo - cells = ', '.join(map(str,cellIn)) - box = ', '.join(f'{num:.3f}' for num in boxDef) - line = f'Automatic Generated Void Cell. Enclosure({box})\n' - line += f'Enclosed cells : ({cells})\n' + boxDef, cellIn = CellInfo + cells = ", ".join(map(str, cellIn)) + box = ", ".join(f"{num:.3f}" for num in boxDef) + line = f"Automatic Generated Void Cell. Enclosure({box})\n" + line += f"Enclosed cells : ({cells})\n" return line diff --git a/src/geouned/GEOUNED/Void/VoidBoxClass.py b/src/geouned/GEOUNED/Void/VoidBoxClass.py index 9ead80e3..309770c7 100644 --- a/src/geouned/GEOUNED/Void/VoidBoxClass.py +++ b/src/geouned/GEOUNED/Void/VoidBoxClass.py @@ -1,4 +1,5 @@ """File with the VoidBox class""" + import FreeCAD import Part @@ -11,379 +12,460 @@ from ..Utils.Options.Classes import Options as opt -class VoidBox (): - def __init__(self,MetaSolids,Enclosure): - - self.Objects =[] - if 'BoundBox' in str(Enclosure) : - self.BoundBox = Enclosure - self.PieceEnclosure = None - else: - self.BoundBox = Enclosure.BoundBox - self.PieceEnclosure = Enclosure - - for m in MetaSolids : - if not m.BoundBox : continue - if m.BoundBox.isValid() : - if self.BoundBox.intersect(m.BoundBox) : - Obj = self.__copyMeta__(m) - self.__removeExtraComp__(Obj,self.BoundBox) - self.Objects.append(Obj) - return - - def Split(self,minSize=200): - - dims = [self.BoundBox.XLength,self.BoundBox.YLength,self.BoundBox.ZLength] - coord = ['X','Y','Z'] - for i in range(2,-1,-1): - if 0.5*dims[i] < minSize : - del(dims[i]) - del(coord[i]) - - if len(dims) == 0 : return None - - ip = dims.index(max(dims)) -# print ('dims : {} {}'.format(coord[ip],0.5*dims[ip])) - if coord[ip] == 'X' : - pos = self.BoundBox.XMin + 0.5*self.BoundBox.XLength - X1Min = self.BoundBox.XMin - X1Max = pos - X2Min = pos - X2Max = self.BoundBox.XMax - Y1Min = self.BoundBox.YMin - Y1Max = self.BoundBox.YMax - Y2Min = Y1Min - Y2Max = Y1Max - Z1Min = self.BoundBox.ZMin - Z1Max = self.BoundBox.ZMax - Z2Min = Z1Min - Z2Max = Z1Max - elif coord[ip] == 'Y' : - pos = self.BoundBox.YMin + 0.5*self.BoundBox.YLength - X1Min = self.BoundBox.XMin - X1Max = self.BoundBox.XMax - X2Min = X1Min - X2Max = X1Max - Y1Min = self.BoundBox.YMin - Y1Max = pos - Y2Min = pos - Y2Max = self.BoundBox.YMax - Z1Min = self.BoundBox.ZMin - Z1Max = self.BoundBox.ZMax - Z2Min = Z1Min - Z2Max = Z1Max - else : - pos = self.BoundBox.ZMin + 0.5*self.BoundBox.ZLength - X1Min = self.BoundBox.XMin - X1Max = self.BoundBox.XMax - X2Min = X1Min - X2Max = X1Max - - Y1Min = self.BoundBox.YMin - Y1Max = self.BoundBox.YMax - Y2Min = Y1Min - Y2Max = Y1Max - - Z1Min = self.BoundBox.ZMin - Z1Max = pos - Z2Min = pos - Z2Max = self.BoundBox.ZMax - - VMin1 = FreeCAD.Vector(X1Min,Y1Min,Z1Min) - VMax1 = FreeCAD.Vector(X1Max,Y1Max,Z1Max) - VMin2 = FreeCAD.Vector(X2Min,Y2Min,Z2Min) - VMax2 = FreeCAD.Vector(X2Max,Y2Max,Z2Max) - box1 = FreeCAD.BoundBox(VMin1,VMax1) - box2 = FreeCAD.BoundBox(VMin2,VMax2) - - if self.PieceEnclosure == None: - Space1 = VoidBox(self.Objects,box1) - Space2 = VoidBox(self.Objects,box2) - VoidBoxTuple = (Space1,Space2) - else: - Space1 = self.PieceEnclosureSplit(box1) - Space2 = self.PieceEnclosureSplit(box2) - VoidBoxTuple = (Space1,Space2) - if Space1 == None: - VoidBoxTuple = (Space2,) - if Space2 == None: - VoidBoxTuple = (Space1,) - if Space1 == None and Space2 == None: - VoidBoxTuple = () - - return VoidBoxTuple - - - def PieceEnclosureSplit(self,Box,Tolerance=1.0e-13): - """This function creates a box-shaped solid with the new limits of given bounding box and - it is intersected with the piece of nested enclosure to create the new void cell. - If the limited region does not intersect with the piece, no void cell is created.""" - - Cube = Part.makeBox( - Box.XLength, Box.YLength, Box.ZLength, - FreeCAD.Vector(Box.XMin, Box.YMin, Box.ZMin), - FreeCAD.Vector(0,0,1)) - dist = Cube.distToShape(self.PieceEnclosure)[0] - try: - if abs(dist/Box.DiagonalLength) > Tolerance: +class VoidBox: + def __init__(self, MetaSolids, Enclosure): + + self.Objects = [] + if "BoundBox" in str(Enclosure): + self.BoundBox = Enclosure + self.PieceEnclosure = None + else: + self.BoundBox = Enclosure.BoundBox + self.PieceEnclosure = Enclosure + + for m in MetaSolids: + if not m.BoundBox: + continue + if m.BoundBox.isValid(): + if self.BoundBox.intersect(m.BoundBox): + Obj = self.__copyMeta__(m) + self.__removeExtraComp__(Obj, self.BoundBox) + self.Objects.append(Obj) + return + + def Split(self, minSize=200): + + dims = [self.BoundBox.XLength, self.BoundBox.YLength, self.BoundBox.ZLength] + coord = ["X", "Y", "Z"] + for i in range(2, -1, -1): + if 0.5 * dims[i] < minSize: + del dims[i] + del coord[i] + + if len(dims) == 0: + return None + + ip = dims.index(max(dims)) + # print ('dims : {} {}'.format(coord[ip],0.5*dims[ip])) + if coord[ip] == "X": + pos = self.BoundBox.XMin + 0.5 * self.BoundBox.XLength + X1Min = self.BoundBox.XMin + X1Max = pos + X2Min = pos + X2Max = self.BoundBox.XMax + Y1Min = self.BoundBox.YMin + Y1Max = self.BoundBox.YMax + Y2Min = Y1Min + Y2Max = Y1Max + Z1Min = self.BoundBox.ZMin + Z1Max = self.BoundBox.ZMax + Z2Min = Z1Min + Z2Max = Z1Max + elif coord[ip] == "Y": + pos = self.BoundBox.YMin + 0.5 * self.BoundBox.YLength + X1Min = self.BoundBox.XMin + X1Max = self.BoundBox.XMax + X2Min = X1Min + X2Max = X1Max + Y1Min = self.BoundBox.YMin + Y1Max = pos + Y2Min = pos + Y2Max = self.BoundBox.YMax + Z1Min = self.BoundBox.ZMin + Z1Max = self.BoundBox.ZMax + Z2Min = Z1Min + Z2Max = Z1Max + else: + pos = self.BoundBox.ZMin + 0.5 * self.BoundBox.ZLength + X1Min = self.BoundBox.XMin + X1Max = self.BoundBox.XMax + X2Min = X1Min + X2Max = X1Max + + Y1Min = self.BoundBox.YMin + Y1Max = self.BoundBox.YMax + Y2Min = Y1Min + Y2Max = Y1Max + + Z1Min = self.BoundBox.ZMin + Z1Max = pos + Z2Min = pos + Z2Max = self.BoundBox.ZMax + + VMin1 = FreeCAD.Vector(X1Min, Y1Min, Z1Min) + VMax1 = FreeCAD.Vector(X1Max, Y1Max, Z1Max) + VMin2 = FreeCAD.Vector(X2Min, Y2Min, Z2Min) + VMax2 = FreeCAD.Vector(X2Max, Y2Max, Z2Max) + box1 = FreeCAD.BoundBox(VMin1, VMax1) + box2 = FreeCAD.BoundBox(VMin2, VMax2) + + if self.PieceEnclosure == None: + Space1 = VoidBox(self.Objects, box1) + Space2 = VoidBox(self.Objects, box2) + VoidBoxTuple = (Space1, Space2) + else: + Space1 = self.PieceEnclosureSplit(box1) + Space2 = self.PieceEnclosureSplit(box2) + VoidBoxTuple = (Space1, Space2) + if Space1 == None: + VoidBoxTuple = (Space2,) + if Space2 == None: + VoidBoxTuple = (Space1,) + if Space1 == None and Space2 == None: + VoidBoxTuple = () + + return VoidBoxTuple + + def PieceEnclosureSplit(self, Box, Tolerance=1.0e-13): + """This function creates a box-shaped solid with the new limits of given bounding box and + it is intersected with the piece of nested enclosure to create the new void cell. + If the limited region does not intersect with the piece, no void cell is created. + """ + + Cube = Part.makeBox( + Box.XLength, + Box.YLength, + Box.ZLength, + FreeCAD.Vector(Box.XMin, Box.YMin, Box.ZMin), + FreeCAD.Vector(0, 0, 1), + ) + dist = Cube.distToShape(self.PieceEnclosure)[0] + try: + if abs(dist / Box.DiagonalLength) > Tolerance: + return None + except ZeroDivisionError: return None - except ZeroDivisionError: - return None - ShapeObject = Cube.common(self.PieceEnclosure) - try: - reldif = (Cube.Volume-ShapeObject.Volume)/Cube.Volume - except ZeroDivisionError: - return None - if abs(reldif) <= Tolerance: - return VoidBox(self.Objects,Box) - elif ShapeObject.Solids : - Solid = ShapeObject.Solids[0] - return VoidBox(self.Objects,Solid) - else: - return None - - - def refine(self): - Cube = Part.makeBox(self.BoundBox.XLength, self.BoundBox.YLength, self.BoundBox.ZLength, - FreeCAD.Vector(self.BoundBox.XMin, self.BoundBox.YMin, self.BoundBox.ZMin), - FreeCAD.Vector(0,0,1)) - refinedList = [] - newcom = [] - - for m in self.Objects: - self.__removeExtraComp__(m,Cube,mode='dist') - return - - def getVoidComplementary(self,Surfaces,simplify='no'): - if self.PieceEnclosure is None: - boxDef = BoolSequence(operator='AND') - center = self.BoundBox.Center - bBox = self.BoundBox - for p in self.getBoundPlanes(): - id,exist = Surfaces.addPlane(p) - if exist: - s = Surfaces.getSurface(id) - if isOposite(p.Surf.Axis,s.Surf.Axis): - id = -id - if isOposite(p.Surf.Axis,p.Surf.Position-center): - boxDef.elements.append(id) - else: - boxDef.elements.append(-id) - enclosure = False - d = opt.enlargeBox - - else: - UniverseBox = self.PieceEnclosure.BoundBox - TempPieceEnclosure = GEOUNED_Solid(None,self.PieceEnclosure) - comsolid,err=Decom.SplitSolid(Part.makeCompound(TempPieceEnclosure.Solids),UniverseBox) - Surfaces.extend(Decom.ExtractSurfaces(comsolid,'All',UniverseBox,MakeObj=True)) - TempPieceEnclosure.updateSolids(comsolid.Solids) - Conv.cellDef(TempPieceEnclosure,Surfaces,UniverseBox) - - boxDef = TempPieceEnclosure.Definition - bBox = self.PieceEnclosure.BoundBox - enclosure = True - d = max(opt.enlargeBox,2) - - Box = Part.makeBox(bBox.XLength+2*d, bBox.YLength+2*d, bBox.ZLength+2*d, - FreeCAD.Vector(bBox.XMin-d, bBox.YMin-d, bBox.ZMin-d), - FreeCAD.Vector(0,0,1)) - - voidSolidDef = BoolSequence(operator='OR') - - cellIn = [] - for m in self.Objects: - voidSolidDef.append(m.Definition) - if m.IsEnclosure : continue - cellIn.append(m.__id__) - - #voidSolidDef.joinOperators() - - if not voidSolidDef.elements : - return boxDef,None # Cell to get complementary are null => Void is only box definition - - # join all basic solids into one big meta Object - # CAD solid representation is not needed because - # here we are working with surfaces and void box - - - complementary = BoolSequence(operator='AND') - complementary.append(boxDef) - if (simplify != 'no' ) : - surfList = voidSolidDef.getSurfacesNumbers() - - if enclosure : - surfList.update(boxDef.getSurfacesNumbers()) - else: - for s in boxDef.elements: - val = s > 0 - voidSolidDef.substitute(abs(s),val) - voidSolidDef.clean() - if type(voidSolidDef.elements) is bool : - res = voidSolidDef.elements - else: - res = None - - if enclosure or res is None: - surfaceDict = {} - for i in surfList: - surfaceDict[i] = Surfaces.getSurface(i) - CTable = buildCTableFromSolids(Box,surfaceDict,option=simplify) - else: - if res == True : - return None,None - else: - return boxDef,None - - newTemp = BoolSequence(operator='OR') - - if voidSolidDef.level == 0 : - if len(voidSolidDef.elements) == 1 : - voidSolidDef.operator = 'AND' - cellVoid = BoolSequence(operator = 'OR') - cellVoid.append(voidSolidDef) - voidSolidDef = cellVoid - - for solDef in voidSolidDef.elements : - newSolid = removeExtraSurfaces(solDef,CTable) - if type(newSolid.elements) is not bool : - newTemp.append(newSolid) - elif newSolid.elements == True: - return None,None - - voidSolidDef = newTemp - - else: - if voidSolidDef.level == 0 : - if len(voidSolidDef.elements) == 1 : - voidSolidDef.operator = 'AND' - cellVoid = BoolSequence(operator = 'OR') - cellVoid.append(voidSolidDef) - voidSolidDef = cellVoid - - if voidSolidDef.elements == True : - return None,None - elif voidSolidDef.elements == False or voidSolidDef.elements == []: - return boxDef,None - - if voidSolidDef.level == 0 : - compSeq = voidSolidDef.getComplementary() - else: - - newCell = [] - - if voidSolidDef.level == 1 and voidSolidDef.operator == 'AND': - compSeq = BoolSequence(operator='OR') - else: - compSeq = BoolSequence(operator='AND') - - for comp in voidSolidDef.elements : - if simplify == 'no': - comp.check() - if type(comp.elements) is bool : - chk = comp.elements - else: - chk = None - - #solid in cover full Void cell volume => Void cell doesn't exist - if chk == True : - if opt.verbose: print('warning void Cell should not exist') - return None,None - - #solid cell is not in void cell Void cell volume => doesn't contribute to void definition - elif chk == False : - continue - - pmoc = comp.getComplementary() - compSeq.append(pmoc) - - if simplify == 'full': - if enclosure : - complementary.append(compSeq) - complementary.simplify(CTable) - else : - compSeq.simplify(CTable) - complementary.append(compSeq) - else: - compSeq.simplify(None) - complementary.simplify(None) - complementary.append(compSeq) - - - complementary.clean() - complementary.levelUpdate() - - if type(complementary.elements) is bool : - return None,None - else : - return complementary,cellIn - - def getBoxNumber(self): - return len(self.Objects) - - def getNumbers(self): - ns = 0 - nb = 0 - - for m in self.Objects: - ns += len(m.Surfaces) - nb += len(m.Definition.elements) if m.Definition.level > 0 else 1 - - return ns,nb - - def getBoundPlanes(self): - Xmid = 0.5*(self.BoundBox.XMin+self.BoundBox.XMax) - Ymid = 0.5*(self.BoundBox.YMin+self.BoundBox.YMax) - Zmid = 0.5*(self.BoundBox.ZMin+self.BoundBox.ZMax) - LX = (self.BoundBox.ZMin+self.BoundBox.XLength) - LY = (self.BoundBox.ZMin+self.BoundBox.YLength) - LZ = (self.BoundBox.ZMin+self.BoundBox.ZLength) - PXMin = GEOUNED_Surface(('Plane',(FreeCAD.Vector(self.BoundBox.XMin,Ymid,Zmid),FreeCAD.Vector( 1,0,0),LY,LZ)),self.BoundBox) - PXMax = GEOUNED_Surface(('Plane',(FreeCAD.Vector(self.BoundBox.XMax,Ymid,Zmid),FreeCAD.Vector(-1,0,0),LY,LZ)),self.BoundBox) - PYMin = GEOUNED_Surface(('Plane',(FreeCAD.Vector(Xmid,self.BoundBox.YMin,Zmid),FreeCAD.Vector(0, 1,0),LZ,LX)),self.BoundBox) - PYMax = GEOUNED_Surface(('Plane',(FreeCAD.Vector(Xmid,self.BoundBox.YMax,Zmid),FreeCAD.Vector(0,-1,0),LZ,LX)),self.BoundBox) - PZMin = GEOUNED_Surface(('Plane',(FreeCAD.Vector(Xmid,Ymid,self.BoundBox.ZMin),FreeCAD.Vector(0,0, 1),LX,LY)),self.BoundBox) - PZMax = GEOUNED_Surface(('Plane',(FreeCAD.Vector(Xmid,Ymid,self.BoundBox.ZMax),FreeCAD.Vector(0,0,-1),LX,LY)),self.BoundBox) - - return (PXMin,PXMax,PYMin,PYMax,PZMin,PZMax) - - def __removeExtraComp__(self,Obj,Box,mode='box'): - reducedSol = [] - reducedDef = BoolSequence(operator='OR') - if not Obj.Solids: return - # Compare Solid BoundBox (here Box is BoundBox Object) - if mode == 'box' : - for i,sol in enumerate(Obj.Solids): - if sol.BoundBox.isValid() : - if Box.intersect(sol.BoundBox) : - reducedSol.append(sol) - reducedDef.append(Obj.Definition.elements[i]) - - # Compare solid using distToshape (here Box is a Solid Cube object) - else : - for i,sol in enumerate(Obj.Solids): - dist = Box.distToShape(sol)[0] - if dist == 0 : - reducedSol.append(sol) - reducedDef.append(Obj.Definition.elements[i]) - - if len(reducedSol) < len(Obj.Solids): - Obj.updateSolids(reducedSol) - Obj.setDefinition(reducedDef) - return - - - def __copyMeta__(self,m): - solidsCopy = m.Solids[:] - facesCopy = m.Faces[:] - Meta = GEOUNED_Solid(m.__id__,solidsCopy) - Meta.setDefinition(m.Definition.copy()) - Meta.setFaces(facesCopy) - if m.IsEnclosure : - Meta.IsEnclosure = True - Meta.EnclosureID = m.EnclosureID - return Meta - - - - + ShapeObject = Cube.common(self.PieceEnclosure) + try: + reldif = (Cube.Volume - ShapeObject.Volume) / Cube.Volume + except ZeroDivisionError: + return None + if abs(reldif) <= Tolerance: + return VoidBox(self.Objects, Box) + elif ShapeObject.Solids: + Solid = ShapeObject.Solids[0] + return VoidBox(self.Objects, Solid) + else: + return None + + def refine(self): + Cube = Part.makeBox( + self.BoundBox.XLength, + self.BoundBox.YLength, + self.BoundBox.ZLength, + FreeCAD.Vector(self.BoundBox.XMin, self.BoundBox.YMin, self.BoundBox.ZMin), + FreeCAD.Vector(0, 0, 1), + ) + refinedList = [] + newcom = [] + + for m in self.Objects: + self.__removeExtraComp__(m, Cube, mode="dist") + return + + def getVoidComplementary(self, Surfaces, simplify="no"): + if self.PieceEnclosure is None: + boxDef = BoolSequence(operator="AND") + center = self.BoundBox.Center + bBox = self.BoundBox + for p in self.getBoundPlanes(): + id, exist = Surfaces.addPlane(p) + if exist: + s = Surfaces.getSurface(id) + if isOposite(p.Surf.Axis, s.Surf.Axis): + id = -id + if isOposite(p.Surf.Axis, p.Surf.Position - center): + boxDef.elements.append(id) + else: + boxDef.elements.append(-id) + enclosure = False + d = opt.enlargeBox + + else: + UniverseBox = self.PieceEnclosure.BoundBox + TempPieceEnclosure = GEOUNED_Solid(None, self.PieceEnclosure) + comsolid, err = Decom.SplitSolid( + Part.makeCompound(TempPieceEnclosure.Solids), UniverseBox + ) + Surfaces.extend( + Decom.ExtractSurfaces(comsolid, "All", UniverseBox, MakeObj=True) + ) + TempPieceEnclosure.updateSolids(comsolid.Solids) + Conv.cellDef(TempPieceEnclosure, Surfaces, UniverseBox) + + boxDef = TempPieceEnclosure.Definition + bBox = self.PieceEnclosure.BoundBox + enclosure = True + d = max(opt.enlargeBox, 2) + + Box = Part.makeBox( + bBox.XLength + 2 * d, + bBox.YLength + 2 * d, + bBox.ZLength + 2 * d, + FreeCAD.Vector(bBox.XMin - d, bBox.YMin - d, bBox.ZMin - d), + FreeCAD.Vector(0, 0, 1), + ) + + voidSolidDef = BoolSequence(operator="OR") + + cellIn = [] + for m in self.Objects: + voidSolidDef.append(m.Definition) + if m.IsEnclosure: + continue + cellIn.append(m.__id__) + + # voidSolidDef.joinOperators() + + if not voidSolidDef.elements: + return ( + boxDef, + None, + ) # Cell to get complementary are null => Void is only box definition + + # join all basic solids into one big meta Object + # CAD solid representation is not needed because + # here we are working with surfaces and void box + + complementary = BoolSequence(operator="AND") + complementary.append(boxDef) + if simplify != "no": + surfList = voidSolidDef.getSurfacesNumbers() + + if enclosure: + surfList.update(boxDef.getSurfacesNumbers()) + else: + for s in boxDef.elements: + val = s > 0 + voidSolidDef.substitute(abs(s), val) + voidSolidDef.clean() + if type(voidSolidDef.elements) is bool: + res = voidSolidDef.elements + else: + res = None + + if enclosure or res is None: + surfaceDict = {} + for i in surfList: + surfaceDict[i] = Surfaces.getSurface(i) + CTable = buildCTableFromSolids(Box, surfaceDict, option=simplify) + else: + if res == True: + return None, None + else: + return boxDef, None + + newTemp = BoolSequence(operator="OR") + + if voidSolidDef.level == 0: + if len(voidSolidDef.elements) == 1: + voidSolidDef.operator = "AND" + cellVoid = BoolSequence(operator="OR") + cellVoid.append(voidSolidDef) + voidSolidDef = cellVoid + + for solDef in voidSolidDef.elements: + newSolid = removeExtraSurfaces(solDef, CTable) + if type(newSolid.elements) is not bool: + newTemp.append(newSolid) + elif newSolid.elements == True: + return None, None + + voidSolidDef = newTemp + + else: + if voidSolidDef.level == 0: + if len(voidSolidDef.elements) == 1: + voidSolidDef.operator = "AND" + cellVoid = BoolSequence(operator="OR") + cellVoid.append(voidSolidDef) + voidSolidDef = cellVoid + + if voidSolidDef.elements == True: + return None, None + elif voidSolidDef.elements == False or voidSolidDef.elements == []: + return boxDef, None + + if voidSolidDef.level == 0: + compSeq = voidSolidDef.getComplementary() + else: + + newCell = [] + + if voidSolidDef.level == 1 and voidSolidDef.operator == "AND": + compSeq = BoolSequence(operator="OR") + else: + compSeq = BoolSequence(operator="AND") + + for comp in voidSolidDef.elements: + if simplify == "no": + comp.check() + if type(comp.elements) is bool: + chk = comp.elements + else: + chk = None + + # solid in cover full Void cell volume => Void cell doesn't exist + if chk == True: + if opt.verbose: + print("warning void Cell should not exist") + return None, None + + # solid cell is not in void cell Void cell volume => doesn't contribute to void definition + elif chk == False: + continue + + pmoc = comp.getComplementary() + compSeq.append(pmoc) + + if simplify == "full": + if enclosure: + complementary.append(compSeq) + complementary.simplify(CTable) + else: + compSeq.simplify(CTable) + complementary.append(compSeq) + else: + compSeq.simplify(None) + complementary.simplify(None) + complementary.append(compSeq) + + complementary.clean() + complementary.levelUpdate() + + if type(complementary.elements) is bool: + return None, None + else: + return complementary, cellIn + + def getBoxNumber(self): + return len(self.Objects) + + def getNumbers(self): + ns = 0 + nb = 0 + + for m in self.Objects: + ns += len(m.Surfaces) + nb += len(m.Definition.elements) if m.Definition.level > 0 else 1 + + return ns, nb + + def getBoundPlanes(self): + Xmid = 0.5 * (self.BoundBox.XMin + self.BoundBox.XMax) + Ymid = 0.5 * (self.BoundBox.YMin + self.BoundBox.YMax) + Zmid = 0.5 * (self.BoundBox.ZMin + self.BoundBox.ZMax) + LX = self.BoundBox.ZMin + self.BoundBox.XLength + LY = self.BoundBox.ZMin + self.BoundBox.YLength + LZ = self.BoundBox.ZMin + self.BoundBox.ZLength + PXMin = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(self.BoundBox.XMin, Ymid, Zmid), + FreeCAD.Vector(1, 0, 0), + LY, + LZ, + ), + ), + self.BoundBox, + ) + PXMax = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(self.BoundBox.XMax, Ymid, Zmid), + FreeCAD.Vector(-1, 0, 0), + LY, + LZ, + ), + ), + self.BoundBox, + ) + PYMin = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(Xmid, self.BoundBox.YMin, Zmid), + FreeCAD.Vector(0, 1, 0), + LZ, + LX, + ), + ), + self.BoundBox, + ) + PYMax = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(Xmid, self.BoundBox.YMax, Zmid), + FreeCAD.Vector(0, -1, 0), + LZ, + LX, + ), + ), + self.BoundBox, + ) + PZMin = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(Xmid, Ymid, self.BoundBox.ZMin), + FreeCAD.Vector(0, 0, 1), + LX, + LY, + ), + ), + self.BoundBox, + ) + PZMax = GEOUNED_Surface( + ( + "Plane", + ( + FreeCAD.Vector(Xmid, Ymid, self.BoundBox.ZMax), + FreeCAD.Vector(0, 0, -1), + LX, + LY, + ), + ), + self.BoundBox, + ) + + return (PXMin, PXMax, PYMin, PYMax, PZMin, PZMax) + + def __removeExtraComp__(self, Obj, Box, mode="box"): + reducedSol = [] + reducedDef = BoolSequence(operator="OR") + if not Obj.Solids: + return + # Compare Solid BoundBox (here Box is BoundBox Object) + if mode == "box": + for i, sol in enumerate(Obj.Solids): + if sol.BoundBox.isValid(): + if Box.intersect(sol.BoundBox): + reducedSol.append(sol) + reducedDef.append(Obj.Definition.elements[i]) + + # Compare solid using distToshape (here Box is a Solid Cube object) + else: + for i, sol in enumerate(Obj.Solids): + dist = Box.distToShape(sol)[0] + if dist == 0: + reducedSol.append(sol) + reducedDef.append(Obj.Definition.elements[i]) + + if len(reducedSol) < len(Obj.Solids): + Obj.updateSolids(reducedSol) + Obj.setDefinition(reducedDef) + return + + def __copyMeta__(self, m): + solidsCopy = m.Solids[:] + facesCopy = m.Faces[:] + Meta = GEOUNED_Solid(m.__id__, solidsCopy) + Meta.setDefinition(m.Definition.copy()) + Meta.setFaces(facesCopy) + if m.IsEnclosure: + Meta.IsEnclosure = True + Meta.EnclosureID = m.EnclosureID + return Meta diff --git a/src/geouned/GEOUNED/Void/voidFunctions.py b/src/geouned/GEOUNED/Void/voidFunctions.py index 59ca2564..b64bfaf6 100644 --- a/src/geouned/GEOUNED/Void/voidFunctions.py +++ b/src/geouned/GEOUNED/Void/voidFunctions.py @@ -1,23 +1,23 @@ +def assignEnclosure(MetaList, NestedEnclosure): + """Assign to all solids the Enclosures ID it belongs to""" -def assignEnclosure(MetaList,NestedEnclosure): - """ Assign to all solids the Enclosures ID it belongs to """ - - for m in MetaList : - if m.IsEnclosure: continue + for m in MetaList: + if m.IsEnclosure: + continue dep = set() outside = True - for lev,Level in enumerate(reversed(NestedEnclosure)) : - for encl in Level : + for lev, Level in enumerate(reversed(NestedEnclosure)): + for encl in Level: inter = m.checkIntersection(encl.CADSolid) # CAD solid intersect level i enclosure -> end of nested loops # Current loop continue because solid can intersect various enclosure - if inter == 0 : + if inter == 0: dep.add(encl.EnclosureID) m.ParentEnclosureID = encl.EnclosureID - if lev == len(NestedEnclosure) -1 : - dep.add(-1) - m.ParentEnclosureID = -1 - + if lev == len(NestedEnclosure) - 1: + dep.add(-1) + m.ParentEnclosureID = -1 + # CAD solid inside level i enclosure -> end of current loop go up i-1 level elif inter == -1: dep.add(encl.EnclosureID) @@ -26,78 +26,86 @@ def assignEnclosure(MetaList,NestedEnclosure): break # stop loop if CAD solid outside all level i enclosure or intersecting one - if not outside : + if not outside: m.EnclosureList = dep break - if not dep: + if not dep: dep.add(-1) m.ParentEnclosureID = -1 - if outside : m.EnclosureList = dep - return - -def selectSolids(MetaList,LowLevelEnclosure,Enclosure): + if outside: + m.EnclosureList = dep + return + + +def selectSolids(MetaList, LowLevelEnclosure, Enclosure): """This function selects the CAD solids and nested enclosures - that can intersect with the current nested enclosure. - For intermediate Levels selected solids are those intersecting i and i+1 level enclosure, - or fully inside level i enclosure and fully outside i+1 enclosure""" + that can intersect with the current nested enclosure. + For intermediate Levels selected solids are those intersecting i and i+1 level enclosure, + or fully inside level i enclosure and fully outside i+1 enclosure""" newMetaList = LowLevelEnclosure[:] - if 'BoundBox' in str(Enclosure): - enclID = -1 + if "BoundBox" in str(Enclosure): + enclID = -1 else: - enclID = Enclosure.EnclosureID + enclID = Enclosure.EnclosureID for m in MetaList: - if m.IsEnclosure : continue - if enclID in m.EnclosureList : - newMetaList.append(m) - + if m.IsEnclosure: + continue + if enclID in m.EnclosureList: + newMetaList.append(m) + return newMetaList -def updateVoidList(offset,voidList,NestedEnclosure,sortEnclosure): + +def updateVoidList(offset, voidList, NestedEnclosure, sortEnclosure): newVoidList = [] - if NestedEnclosure : + if NestedEnclosure: updateComment = True - else: - updateComment =False - + else: + updateComment = False + icount = offset + 1 voids = voidList[0] - for m in voids : - m.__id__ = icount - if updateComment and not sortEnclosure : m.Comments = m.Comments + '\nLevel 0 void enclosure' - icount += 1 - m.ParentEnclosureID = -1 - m.EnclosureID = 0 - newVoidList.append(m) - + for m in voids: + m.__id__ = icount + if updateComment and not sortEnclosure: + m.Comments = m.Comments + "\nLevel 0 void enclosure" + icount += 1 + m.ParentEnclosureID = -1 + m.EnclosureID = 0 + newVoidList.append(m) + ivoid = 1 for Level in NestedEnclosure: - for encl in Level : - if encl.CellType == 'envelope': continue - for m in voidList[ivoid] : - m.__id__ = icount - m.ParentEnclosureID = encl.ParentEnclosureID - m.EnclosureID = encl.EnclosureID - if sortEnclosure : - m.Comments = m.Comments + '\n{}'.format(encl.Comments) - else: - m.Comments = m.Comments + '\nVoid Enclosure #{}'.format(encl.EnclosureID) - icount += 1 - newVoidList.append(m) - ivoid += 1 + for encl in Level: + if encl.CellType == "envelope": + continue + for m in voidList[ivoid]: + m.__id__ = icount + m.ParentEnclosureID = encl.ParentEnclosureID + m.EnclosureID = encl.EnclosureID + if sortEnclosure: + m.Comments = m.Comments + "\n{}".format(encl.Comments) + else: + m.Comments = m.Comments + "\nVoid Enclosure #{}".format( + encl.EnclosureID + ) + icount += 1 + newVoidList.append(m) + ivoid += 1 # graveyard Cell - + Graveyard = voidList[-1] - for m in Graveyard : - m.__id__ = icount - m.ParentEnclosureID = -1 - m.EnclosureID = 0 - newVoidList.append(m) - icount += 1 + for m in Graveyard: + m.__id__ = icount + m.ParentEnclosureID = -1 + m.EnclosureID = 0 + newVoidList.append(m) + icount += 1 return newVoidList diff --git a/src/geouned/GEOUNED/Write/AdditionalFiles.py b/src/geouned/GEOUNED/Write/AdditionalFiles.py index eb3159ad..968113cb 100644 --- a/src/geouned/GEOUNED/Write/AdditionalFiles.py +++ b/src/geouned/GEOUNED/Write/AdditionalFiles.py @@ -1,31 +1,39 @@ - def commentsWrite(name, MetaList): - '''Function to write in an independent file the comment strings''' - - outfile=open(name+'_comments.txt','w',encoding='utf-8') + """Function to write in an independent file the comment strings""" + + outfile = open(name + "_comments.txt", "w", encoding="utf-8") for m in MetaList: - outfile.write(m.Comments+'\n') - + outfile.write(m.Comments + "\n") + outfile.close() -def summaryWrite(name,MetaList): +def summaryWrite(name, MetaList): - outfile=open(name+'_Summary.txt','w',encoding='utf-8') - header = ' Cell Id{:5s}Mat Id{:6s}Density{:7s}Volume{:5s}Comments\n'.format('','','','') + outfile = open(name + "_Summary.txt", "w", encoding="utf-8") + header = " Cell Id{:5s}Mat Id{:6s}Density{:7s}Volume{:5s}Comments\n".format( + "", "", "", "" + ) outfile.write(header) for m in MetaList: - if m.Void or m.__id__ is None : continue - index = m.__id__ - Vol = m.Volume * 1e-3 - if m.Material == 0: - line = ' {:>8d}{:3s}{:>8d}{:3s}{:11s}{:3s}{:11.4e}{:3s}{}\n'.format(index,'',0,'','','',Vol,'',m.Comments) - else: - if abs(m.Density) < 1e-2 : - line = ' {:>8d}{:3s}{:>8d}{:3s}{:11.4e}{:3s}{:11.4e}{:3s}{}\n'.format(index,'',m.Material,'',m.Density,'',Vol,'',m.Comments) - else: - line = ' {:>8d}{:3s}{:>8d}{:3s}{:11.7f}{:3s}{:11.4e}{:3s}{}\n'.format(index,'',m.Material,'',m.Density,'',Vol,'',m.Comments) + if m.Void or m.__id__ is None: + continue + index = m.__id__ + Vol = m.Volume * 1e-3 + if m.Material == 0: + line = " {:>8d}{:3s}{:>8d}{:3s}{:11s}{:3s}{:11.4e}{:3s}{}\n".format( + index, "", 0, "", "", "", Vol, "", m.Comments + ) + else: + if abs(m.Density) < 1e-2: + line = " {:>8d}{:3s}{:>8d}{:3s}{:11.4e}{:3s}{:11.4e}{:3s}{}\n".format( + index, "", m.Material, "", m.Density, "", Vol, "", m.Comments + ) + else: + line = " {:>8d}{:3s}{:>8d}{:3s}{:11.7f}{:3s}{:11.4e}{:3s}{}\n".format( + index, "", m.Material, "", m.Density, "", Vol, "", m.Comments + ) - outfile.write(line) + outfile.write(line) outfile.close() diff --git a/src/geouned/GEOUNED/Write/Functions.py b/src/geouned/GEOUNED/Write/Functions.py index 4094aa47..975d37b1 100644 --- a/src/geouned/GEOUNED/Write/Functions.py +++ b/src/geouned/GEOUNED/Write/Functions.py @@ -11,259 +11,308 @@ from .StringFunctions import remove_redundant -class CardLine : - def __init__(self,card,linesize=80,tabspace=6,fmt=''): - self.str = card + ' ' - self.lineSize = linesize - self.__leftspace__ = linesize - len(self.str) - self.tabspace = tabspace - self.tabstr = ' '*tabspace - self.fmt = fmt - - def extend(self,dataList): - line ='' +class CardLine: + def __init__(self, card, linesize=80, tabspace=6, fmt=""): + self.str = card + " " + self.lineSize = linesize + self.__leftspace__ = linesize - len(self.str) + self.tabspace = tabspace + self.tabstr = " " * tabspace + self.fmt = fmt + + def extend(self, dataList): + line = "" for data in dataList: - data_str = '{:{fmt}} '.format(data,fmt=self.fmt) - if self.__leftspace__ - len(data_str) > 0 : - line += data_str - self.__leftspace__ -= len(data_str) - else: - self.str += line +'\n' - line = '{}{}'.format(self.tabstr,data_str) - self.__leftspace__ = self.lineSize - len(line) + data_str = "{:{fmt}} ".format(data, fmt=self.fmt) + if self.__leftspace__ - len(data_str) > 0: + line += data_str + self.__leftspace__ -= len(data_str) + else: + self.str += line + "\n" + line = "{}{}".format(self.tabstr, data_str) + self.__leftspace__ = self.lineSize - len(line) self.str += line - -class CellString : - def __init__(self,linesize=80,tabspace=6): - self.str = '' - self.lineSize = linesize - self.__leftspace__ = linesize - self.tabspace = tabspace - self.tabstr = ' '*tabspace - - def add(self,string): - self.str += string - - def delLastChar(self): - self.str = self.str[0:-1] - self.__leftspace__ += 1 - - def wrapLine(self,offset=0): - - self.str = self.str.strip() - self.str = re.sub(' +' ,' ' ,self.str) - self.str = re.sub(' *\( *' ,'(' ,self.str) - self.str = re.sub(' *\) *' ,')' ,self.str) - self.str = re.sub(' *: *' ,':' ,self.str) - self.str = re.sub('\)\(' ,') (' ,self.str) - self.str = re.sub('(?P\d)\(','\g (',self.str) - self.str = re.sub('\)(?P\d)',') \g',self.str) - self.str = re.sub('\)-' ,') -' ,self.str) - - if len(self.str)+offset <= self.lineSize : return - - newline = '' - init = 0 - icount = self.lineSize-1 - offset - lenleft = len(self.str) - - while True : - while self.str[icount] not in (')',':',' '): - icount -= 1 - - newline += self.str[init:icount+1] - lenleft -= icount - init + 1 - init = icount + 1 - icount += self.lineSize - self.tabspace - if lenleft == 0: + + +class CellString: + def __init__(self, linesize=80, tabspace=6): + self.str = "" + self.lineSize = linesize + self.__leftspace__ = linesize + self.tabspace = tabspace + self.tabstr = " " * tabspace + + def add(self, string): + self.str += string + + def delLastChar(self): + self.str = self.str[0:-1] + self.__leftspace__ += 1 + + def wrapLine(self, offset=0): + + self.str = self.str.strip() + self.str = re.sub(" +", " ", self.str) + self.str = re.sub(" *\( *", "(", self.str) + self.str = re.sub(" *\) *", ")", self.str) + self.str = re.sub(" *: *", ":", self.str) + self.str = re.sub("\)\(", ") (", self.str) + self.str = re.sub("(?P\d)\(", "\g (", self.str) + self.str = re.sub("\)(?P\d)", ") \g", self.str) + self.str = re.sub("\)-", ") -", self.str) + + if len(self.str) + offset <= self.lineSize: + return + + newline = "" + init = 0 + icount = self.lineSize - 1 - offset + lenleft = len(self.str) + + while True: + while self.str[icount] not in (")", ":", " "): + icount -= 1 + + newline += self.str[init : icount + 1] + lenleft -= icount - init + 1 + init = icount + 1 + icount += self.lineSize - self.tabspace + if lenleft == 0: + break + elif icount < len(self.str): + newline += "\n{}".format(self.tabstr) + else: + newline += "\n{}{}".format(self.tabstr, self.str[init:]) break - elif icount < len(self.str) : - newline += '\n{}'.format(self.tabstr) - else: - newline += '\n{}{}'.format(self.tabstr,self.str[init:]) - break - - self.str = newline - -def changeSurfSign(surf,Seq): - if Seq.level == 0 : - for i,e in enumerate(Seq.elements): - if surf == abs(e) : Seq.elements[i] = -Seq.elements[i] + + self.str = newline + + +def changeSurfSign(surf, Seq): + if Seq.level == 0: + for i, e in enumerate(Seq.elements): + if surf == abs(e): + Seq.elements[i] = -Seq.elements[i] else: - for i,e in enumerate(Seq.elements): - if type(e) is int : - if surf == abs(e) : Seq.elements[i] = -Seq.elements[i] - else: - changeSurfSign(surf,e) - -def writeMCNPCellDef(Definition,tabspace=0,offset=0): - sdef = CellString(tabspace=tabspace) - strDef = remove_redundant(writeSequenceMCNP(Definition)) - sdef.add(strDef) - sdef.wrapLine(offset) - return sdef.str - -def writeSerpentCellDef(Definition,tabspace=0,offset=0): - sdef = CellString(tabspace=tabspace) - strDef = remove_redundant(writeSequenceSerpent(Definition)) - sdef.add(strDef) - sdef.wrapLine(offset) - return sdef.str - -def writePHITSCellDef(Definition,tabspace=0,offset=0): - sdef = CellString(tabspace=tabspace) - strDef = remove_redundant(writeSequencePHITS(Definition)) - sdef.add(strDef) - sdef.wrapLine(offset) - return sdef.str - -def writeOpenMCregion(Definition,Wtype='XML'): - if Wtype == 'XML': - return writeSequenceOMCXML(Definition) - if Wtype == 'PY': - return writeSequenceOMCPY(Definition) + for i, e in enumerate(Seq.elements): + if type(e) is int: + if surf == abs(e): + Seq.elements[i] = -Seq.elements[i] + else: + changeSurfSign(surf, e) + + +def writeMCNPCellDef(Definition, tabspace=0, offset=0): + sdef = CellString(tabspace=tabspace) + strDef = remove_redundant(writeSequenceMCNP(Definition)) + sdef.add(strDef) + sdef.wrapLine(offset) + return sdef.str + + +def writeSerpentCellDef(Definition, tabspace=0, offset=0): + sdef = CellString(tabspace=tabspace) + strDef = remove_redundant(writeSequenceSerpent(Definition)) + sdef.add(strDef) + sdef.wrapLine(offset) + return sdef.str + + +def writePHITSCellDef(Definition, tabspace=0, offset=0): + sdef = CellString(tabspace=tabspace) + strDef = remove_redundant(writeSequencePHITS(Definition)) + sdef.add(strDef) + sdef.wrapLine(offset) + return sdef.str + + +def writeOpenMCregion(Definition, Wtype="XML"): + if Wtype == "XML": + return writeSequenceOMCXML(Definition) + if Wtype == "PY": + return writeSequenceOMCPY(Definition) + def writeSequenceMCNP(Seq): - if Seq.level == 0 : - if Seq.operator == 'AND' : line = '({})'.format(' '.join(map(str,Seq.elements))) - else : line = '({})'.format(':'.join(map(str,Seq.elements))) - else : + if Seq.level == 0: + if Seq.operator == "AND": + line = "({})".format(" ".join(map(str, Seq.elements))) + else: + line = "({})".format(":".join(map(str, Seq.elements))) + else: terms = [] for e in Seq.elements: - if type(e) is int : - terms.append(str(e)) - else : - terms.append(writeSequenceMCNP(e)) + if type(e) is int: + terms.append(str(e)) + else: + terms.append(writeSequenceMCNP(e)) - if Seq.operator == 'AND' : line = '({})'.format(' '.join(terms)) - else : line = '({})'.format(':'.join(terms)) + if Seq.operator == "AND": + line = "({})".format(" ".join(terms)) + else: + line = "({})".format(":".join(terms)) + + return line - return line def writeSequenceSerpent(Seq): - if Seq.level == 0 : - if Seq.operator == 'AND' : line = '({})'.format(' '.join(map(str,Seq.elements))) - else : line = '({})'.format(':'.join(map(str,Seq.elements))) - else : + if Seq.level == 0: + if Seq.operator == "AND": + line = "({})".format(" ".join(map(str, Seq.elements))) + else: + line = "({})".format(":".join(map(str, Seq.elements))) + else: terms = [] for e in Seq.elements: - if type(e) is int : - terms.append(str(e)) - else : - terms.append(writeSequenceMCNP(e)) + if type(e) is int: + terms.append(str(e)) + else: + terms.append(writeSequenceMCNP(e)) + + if Seq.operator == "AND": + line = "({})".format(" ".join(terms)) + else: + line = "({})".format(":".join(terms)) - if Seq.operator == 'AND' : line = '({})'.format(' '.join(terms)) - else : line = '({})'.format(':'.join(terms)) + return line - return line def writeSequencePHITS(Seq): - if Seq.level == 0 : - if Seq.operator == 'AND' : line = '({})'.format(' '.join(map(str,Seq.elements))) - else : line = '({})'.format(':'.join(map(str,Seq.elements))) - else : + if Seq.level == 0: + if Seq.operator == "AND": + line = "({})".format(" ".join(map(str, Seq.elements))) + else: + line = "({})".format(":".join(map(str, Seq.elements))) + else: terms = [] for e in Seq.elements: - if type(e) is int : - terms.append(str(e)) - else : - terms.append(writeSequencePHITS(e)) + if type(e) is int: + terms.append(str(e)) + else: + terms.append(writeSequencePHITS(e)) + + if Seq.operator == "AND": + line = "({})".format(" ".join(terms)) + else: + line = "({})".format(":".join(terms)) - if Seq.operator == 'AND' : line = '({})'.format(' '.join(terms)) - else : line = '({})'.format(':'.join(terms)) + return line - return line def writeSequenceOMCXML(Seq): - if Seq.level == 0 : - if Seq.operator == 'AND' : line = '({})'.format(' '.join(map(str,Seq.elements))) - else : line = '({})'.format(' | '.join(map(str,Seq.elements))) - else : + if Seq.level == 0: + if Seq.operator == "AND": + line = "({})".format(" ".join(map(str, Seq.elements))) + else: + line = "({})".format(" | ".join(map(str, Seq.elements))) + else: terms = [] for e in Seq.elements: - if type(e) is int : - terms.append(str(e)) - else : - terms.append(writeSequenceOMCXML(e)) + if type(e) is int: + terms.append(str(e)) + else: + terms.append(writeSequenceOMCXML(e)) + + if Seq.operator == "AND": + line = "({})".format(" ".join(terms)) + else: + line = "({})".format(" | ".join(terms)) + return line - if Seq.operator == 'AND' : line = '({})'.format(' '.join(terms)) - else : line = '({})'.format(' | '.join(terms)) - return line -def writeSequenceOMCPY(Seq,prefix='S'): +def writeSequenceOMCPY(Seq, prefix="S"): - strSurf = lambda surf : '-{}{}'.format(prefix,-surf) if surf < 0 else '+{}{}'.format(prefix,surf) + strSurf = lambda surf: ( + "-{}{}".format(prefix, -surf) if surf < 0 else "+{}{}".format(prefix, surf) + ) - if Seq.level == 0 : - if Seq.operator == 'AND' : line = '({})'.format(' & '.join(map(strSurf,Seq.elements))) - else : line = '({})'.format(' | '.join(map(strSurf,Seq.elements))) - else : + if Seq.level == 0: + if Seq.operator == "AND": + line = "({})".format(" & ".join(map(strSurf, Seq.elements))) + else: + line = "({})".format(" | ".join(map(strSurf, Seq.elements))) + else: terms = [] for e in Seq.elements: - if type(e) is int : - terms.append(strSurf(e)) - else : - terms.append(writeSequenceOMCPY(e)) - - if Seq.operator == 'AND' : line = '({})'.format(' & '.join(terms)) - else : line = '({})'.format(' | '.join(terms)) - return line - -def MCNPSurface(id,Type,surf): - MCNP_def = '' - - if (Type=='Plane'): - if surf.pointDef and opt.prnt3PPlane: - P1 = surf.Points[0] - P2 = surf.Points[1] - P3 = surf.Points[2] - MCNP_def="""{:<6d} P {P1[0]:{d}} {P1[1]:{d}} {P1[2]:{d}} + if type(e) is int: + terms.append(strSurf(e)) + else: + terms.append(writeSequenceOMCPY(e)) + + if Seq.operator == "AND": + line = "({})".format(" & ".join(terms)) + else: + line = "({})".format(" | ".join(terms)) + return line + + +def MCNPSurface(id, Type, surf): + MCNP_def = "" + + if Type == "Plane": + if surf.pointDef and opt.prnt3PPlane: + P1 = surf.Points[0] + P2 = surf.Points[1] + P3 = surf.Points[2] + MCNP_def = """{:<6d} P {P1[0]:{d}} {P1[1]:{d}} {P1[2]:{d}} {P2[0]:{d}} {P2[1]:{d}} {P2[2]:{d}} - {P3[0]:{d}} {P3[1]:{d}} {P3[2]:{d}}""".format(id,P1=P1/10,P2=P2/10,P3=P3/10,d=nf.P_d) - else: - A=surf.Axis.x - B=surf.Axis.y - C=surf.Axis.z - D=surf.Axis.dot(surf.Position) - if surf.Axis.isEqual(FreeCAD.Vector(1,0,0),tol.pln_angle) : - MCNP_def='{:<6d} PX {:{x}}'.format(id,D/10.0,x=nf.P_xyz) - elif surf.Axis.isEqual(FreeCAD.Vector(0,1,0),tol.pln_angle) : - MCNP_def='{:<6d} PY {:{y}}'.format(id,D/10.0,y=nf.P_xyz) - elif surf.Axis.isEqual(FreeCAD.Vector(0,0,1),tol.pln_angle) : - MCNP_def='{:<6d} PZ {:{z}}'.format(id,D/10.0,z=nf.P_xyz) - else: - MCNP_def='{:<6d} P {:{abc}} {:{abc}} {:{abc}} {:{d}}'.format(id,A,B,C,D/10.0,abc=nf.P_abc,d=nf.P_d) - - elif (Type == 'Cylinder'): + {P3[0]:{d}} {P3[1]:{d}} {P3[2]:{d}}""".format( + id, P1=P1 / 10, P2=P2 / 10, P3=P3 / 10, d=nf.P_d + ) + else: + A = surf.Axis.x + B = surf.Axis.y + C = surf.Axis.z + D = surf.Axis.dot(surf.Position) + if surf.Axis.isEqual(FreeCAD.Vector(1, 0, 0), tol.pln_angle): + MCNP_def = "{:<6d} PX {:{x}}".format(id, D / 10.0, x=nf.P_xyz) + elif surf.Axis.isEqual(FreeCAD.Vector(0, 1, 0), tol.pln_angle): + MCNP_def = "{:<6d} PY {:{y}}".format(id, D / 10.0, y=nf.P_xyz) + elif surf.Axis.isEqual(FreeCAD.Vector(0, 0, 1), tol.pln_angle): + MCNP_def = "{:<6d} PZ {:{z}}".format(id, D / 10.0, z=nf.P_xyz) + else: + MCNP_def = "{:<6d} P {:{abc}} {:{abc}} {:{abc}} {:{d}}".format( + id, A, B, C, D / 10.0, abc=nf.P_abc, d=nf.P_d + ) + + elif Type == "Cylinder": Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - Pos = surf.Center*0.1 - rad = surf.Radius*0.1 - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - if (Pos.y == 0.0 and Pos.z == 0.0): - MCNP_def='{:<6d} CX {:{r}}'.format(id,rad,r=nf.C_r) - else: - MCNP_def='{:<6d} C/X {:{yz}} {:{yz}} {:{r}}'.format(id,Pos.y,Pos.z,rad,yz=nf.C_xyz,r=nf.C_r) - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - if (Pos.x == 0.0 and Pos.z == 0.0): - MCNP_def='{:<6d} CY {:{r}}'.format(id,rad,r=nf.C_r) - else: - MCNP_def='{:<6d} C/Y {:{xz}} {:{xz}} {:{r}}'.format(id,Pos.x,Pos.z,rad,xz=nf.C_xyz,r=nf.C_r) - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - if (Pos.y == 0.0 and Pos.x == 0.0): - MCNP_def='{:<6d} CZ {:{r}}'.format(id,rad,r=nf.C_r) - else: - MCNP_def='{:<6d} C/Z {:{xy}} {:{xy}} {:{r}}'.format(id,Pos.x,Pos.y,rad,xy=nf.C_xyz,r=nf.C_r) + Pos = surf.Center * 0.1 + rad = surf.Radius * 0.1 + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + if Pos.y == 0.0 and Pos.z == 0.0: + MCNP_def = "{:<6d} CX {:{r}}".format(id, rad, r=nf.C_r) + else: + MCNP_def = "{:<6d} C/X {:{yz}} {:{yz}} {:{r}}".format( + id, Pos.y, Pos.z, rad, yz=nf.C_xyz, r=nf.C_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + if Pos.x == 0.0 and Pos.z == 0.0: + MCNP_def = "{:<6d} CY {:{r}}".format(id, rad, r=nf.C_r) + else: + MCNP_def = "{:<6d} C/Y {:{xz}} {:{xz}} {:{r}}".format( + id, Pos.x, Pos.z, rad, xz=nf.C_xyz, r=nf.C_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + if Pos.y == 0.0 and Pos.x == 0.0: + MCNP_def = "{:<6d} CZ {:{r}}".format(id, rad, r=nf.C_r) + else: + MCNP_def = "{:<6d} C/Z {:{xy}} {:{xy}} {:{r}}".format( + id, Pos.x, Pos.y, rad, xy=nf.C_xyz, r=nf.C_r + ) else: - # Is not still working fine - Q=Qform.QFormCyl(Dir,Pos,rad) - MCNP_def='''\ + # Is not still working fine + Q = Qform.QFormCyl(Dir, Pos, rad) + MCNP_def = """\ {:<6d} GQ {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + # Si se quiere rcc en vez de Q form # pnt = surf.Center.sub(surf.Axis.multiply(1.0e7)) # mas alla de 100 m # dir = surf.Axis.multiply(1.0e8) @@ -275,261 +324,340 @@ def MCNPSurface(id,Type,surf): # Hz= dir.z/10.0 # rad=surf.Radius/10.0 # MCNP_def='%i RCC %13.7E %13.7E %13.7E %13.7E\n %13.7E %13.7E %13.7E' %(id,Vx,Vy,Vz,Hx,Hy,Hz,rad) - - elif (Type == 'Cone'): - Apex = surf.Apex*0.1 - Dir = surf.Axis*0.1 + + elif Type == "Cone": + Apex = surf.Apex * 0.1 + Dir = surf.Axis * 0.1 tan = math.tan(surf.SemiAngle) - X_dir=FreeCAD.Vector(1,0,0) - Y_dir=FreeCAD.Vector(0,1,0) - Z_dir=FreeCAD.Vector(0,0,1) - if (isParallel(Dir,X_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,X_dir,tol.angle)): sheet=-1 - if (Apex.y == 0.0 and Apex.z == 0.0): - MCNP_def='{:<6d} KX {:{x}} {:{t2}} {}'.format(id,Apex.x,tan**2,sheet,x=nf.K_xyz,t2=nf.K_tan2) - else: - MCNP_def='{:<6d} K/X {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Y_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Y_dir,tol.angle)): sheet=-1 - if (Apex.x == 0.0 and Apex.z == 0.0): - MCNP_def='{:<6d} KY {:{y}} {:{t2}} {}'.format(id,Apex.y,tan**2,sheet,y=nf.K_xyz,t2=nf.K_tan2) - else: - MCNP_def='{:<6d} K/Y {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Z_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Z_dir,tol.angle)): sheet=-1 - if (Apex.x == 0.0 and Apex.y == 0.0): - MCNP_def='{:<6d} KZ {:{z}} {:{t2}} {}'.format(id,Apex.z,tan**2,sheet,z=nf.K_xyz,t2=nf.K_tan2) - else: - MCNP_def='{:<6d} K/Z {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) + X_dir = FreeCAD.Vector(1, 0, 0) + Y_dir = FreeCAD.Vector(0, 1, 0) + Z_dir = FreeCAD.Vector(0, 0, 1) + if isParallel(Dir, X_dir, tol.angle): + sheet = 1 + if isOposite(Dir, X_dir, tol.angle): + sheet = -1 + if Apex.y == 0.0 and Apex.z == 0.0: + MCNP_def = "{:<6d} KX {:{x}} {:{t2}} {}".format( + id, Apex.x, tan**2, sheet, x=nf.K_xyz, t2=nf.K_tan2 + ) + else: + MCNP_def = "{:<6d} K/X {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) + elif isParallel(Dir, Y_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Y_dir, tol.angle): + sheet = -1 + if Apex.x == 0.0 and Apex.z == 0.0: + MCNP_def = "{:<6d} KY {:{y}} {:{t2}} {}".format( + id, Apex.y, tan**2, sheet, y=nf.K_xyz, t2=nf.K_tan2 + ) + else: + MCNP_def = "{:<6d} K/Y {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) + elif isParallel(Dir, Z_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Z_dir, tol.angle): + sheet = -1 + if Apex.x == 0.0 and Apex.y == 0.0: + MCNP_def = "{:<6d} KZ {:{z}} {:{t2}} {}".format( + id, Apex.z, tan**2, sheet, z=nf.K_xyz, t2=nf.K_tan2 + ) + else: + MCNP_def = "{:<6d} K/Z {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) else: - Q=Qform.QFormCone(Dir,Apex,tan) - MCNP_def='''\ + Q = Qform.QFormCone(Dir, Apex, tan) + MCNP_def = """\ {:<6d} GQ {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - - elif (Type == 'Sphere'): - # corresponding logic - rad = surf.Radius*0.1 - pnt = surf.Center*0.1 - if pnt.isEqual(FreeCAD.Vector(0,0,0),tol.sph_distance): - MCNP_def='{:<6d} SO {:{r}}'.format(id,rad,r=nf.S_r) + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + + elif Type == "Sphere": + # corresponding logic + rad = surf.Radius * 0.1 + pnt = surf.Center * 0.1 + if pnt.isEqual(FreeCAD.Vector(0, 0, 0), tol.sph_distance): + MCNP_def = "{:<6d} SO {:{r}}".format(id, rad, r=nf.S_r) else: - MCNP_def='{:<6d} S {:{xyz}} {:{xyz}} {:{xyz}} {:{r}}'.format(id,pnt.x,pnt.y,pnt.z,rad,xyz=nf.S_xyz,r=nf.S_r) + MCNP_def = "{:<6d} S {:{xyz}} {:{xyz}} {:{xyz}} {:{r}}".format( + id, pnt.x, pnt.y, pnt.z, rad, xyz=nf.S_xyz, r=nf.S_r + ) - elif (Type == 'Torus'): + elif Type == "Torus": Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - Pos = surf.Center*0.1 - radMaj = surf.MajorRadius*0.1 - radMin = surf.MinorRadius*0.1 - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - MCNP_def='''\ + Pos = surf.Center * 0.1 + radMaj = surf.MajorRadius * 0.1 + radMin = surf.MinorRadius * 0.1 + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + MCNP_def = """\ {:<6d} TX {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - MCNP_def='''\ + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + MCNP_def = """\ {:<6d} TY {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - MCNP_def='''\ + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + MCNP_def = """\ {:<6d} TZ {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) - - return trim(MCNP_def,80) - - -def OpenMCSurface(Type,surf,outXML=True,quadricForm=False): - if (Type=='Plane'): - A=surf.Axis.x - B=surf.Axis.y - C=surf.Axis.z - D=surf.Axis.dot(surf.Position)*0.1 - if surf.Axis.isEqual(FreeCAD.Vector(1,0,0),tol.pln_angle) : - if outXML : - OMCsurf = 'x-plane' - coeffs = '{:{x}}'.format(D,x=nf.P_xyz) - else: - OMCsurf = 'XPlane' - coeffs = 'x0={}'.format(D) - - elif surf.Axis.isEqual(FreeCAD.Vector(0,1,0),tol.pln_angle) : - if outXML : - OMCsurf = 'y-plane' - coeffs = '{:{x}}'.format(D,x=nf.P_xyz) - else: - OMCsurf = 'YPlane' - coeffs = 'y0={}'.format(D) - - elif surf.Axis.isEqual(FreeCAD.Vector(0,0,1),tol.pln_angle) : - if outXML : - OMCsurf = 'z-plane' - coeffs = '{:{x}}'.format(D,x=nf.P_xyz) - else: - OMCsurf = 'ZPlane' - coeffs = 'z0={}'.format(D) + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) + + return trim(MCNP_def, 80) + + +def OpenMCSurface(Type, surf, outXML=True, quadricForm=False): + if Type == "Plane": + A = surf.Axis.x + B = surf.Axis.y + C = surf.Axis.z + D = surf.Axis.dot(surf.Position) * 0.1 + if surf.Axis.isEqual(FreeCAD.Vector(1, 0, 0), tol.pln_angle): + if outXML: + OMCsurf = "x-plane" + coeffs = "{:{x}}".format(D, x=nf.P_xyz) + else: + OMCsurf = "XPlane" + coeffs = "x0={}".format(D) + + elif surf.Axis.isEqual(FreeCAD.Vector(0, 1, 0), tol.pln_angle): + if outXML: + OMCsurf = "y-plane" + coeffs = "{:{x}}".format(D, x=nf.P_xyz) + else: + OMCsurf = "YPlane" + coeffs = "y0={}".format(D) + + elif surf.Axis.isEqual(FreeCAD.Vector(0, 0, 1), tol.pln_angle): + if outXML: + OMCsurf = "z-plane" + coeffs = "{:{x}}".format(D, x=nf.P_xyz) + else: + OMCsurf = "ZPlane" + coeffs = "z0={}".format(D) else: - if outXML : - OMCsurf = 'plane' - coeffs = '{:{abc}} {:{abc}} {:{abc}} {:{d}}'.format(A,B,C,D, abc=nf.P_abc, d=nf.P_d) - else: - OMCsurf = 'Plane' - coeffs = 'a={},b={},c={},d={}'.format(A,B,C,D) - - - elif (Type == 'Cylinder'): - Pos = surf.Center*0.1 - Rad = surf.Radius*0.1 + if outXML: + OMCsurf = "plane" + coeffs = "{:{abc}} {:{abc}} {:{abc}} {:{d}}".format( + A, B, C, D, abc=nf.P_abc, d=nf.P_d + ) + else: + OMCsurf = "Plane" + coeffs = "a={},b={},c={},d={}".format(A, B, C, D) + + elif Type == "Cylinder": + Pos = surf.Center * 0.1 + Rad = surf.Radius * 0.1 Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - if outXML : - OMCsurf = 'x-cylinder' - coeffs = '{:{xy}} {:{xy}} {:{r}}'.format(Pos.y, Pos.z, Rad, xy=nf.C_xyz, r=nf.C_r) - else: - OMCsurf = 'XCylinder' - coeffs = 'y0={},z0={},r={}'.format(Pos.y, Pos.z, Rad) - - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - if outXML : - OMCsurf = 'y-cylinder' - coeffs = '{:{xy}} {:{xy}} {:{r}}'.format(Pos.x, Pos.z, Rad, xy=nf.C_xyz, r=nf.C_r) - else: - OMCsurf = 'YCylinder' - coeffs = 'x0={},z0={},r={}'.format(Pos.x, Pos.z, Rad) - - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - if outXML : - OMCsurf = 'z-cylinder' - coeffs = '{:{xy}} {:{xy}} {:{r}}'.format(Pos.x, Pos.y, Rad, xy=nf.C_xyz, r=nf.C_r) - else: - OMCsurf = 'ZCylinder' - coeffs = 'x0={},y0={},r={}'.format(Pos.x, Pos.y, Rad) + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + if outXML: + OMCsurf = "x-cylinder" + coeffs = "{:{xy}} {:{xy}} {:{r}}".format( + Pos.y, Pos.z, Rad, xy=nf.C_xyz, r=nf.C_r + ) + else: + OMCsurf = "XCylinder" + coeffs = "y0={},z0={},r={}".format(Pos.y, Pos.z, Rad) + + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + if outXML: + OMCsurf = "y-cylinder" + coeffs = "{:{xy}} {:{xy}} {:{r}}".format( + Pos.x, Pos.z, Rad, xy=nf.C_xyz, r=nf.C_r + ) + else: + OMCsurf = "YCylinder" + coeffs = "x0={},z0={},r={}".format(Pos.x, Pos.z, Rad) + + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + if outXML: + OMCsurf = "z-cylinder" + coeffs = "{:{xy}} {:{xy}} {:{r}}".format( + Pos.x, Pos.y, Rad, xy=nf.C_xyz, r=nf.C_r + ) + else: + OMCsurf = "ZCylinder" + coeffs = "x0={},y0={},r={}".format(Pos.x, Pos.y, Rad) else: - if outXML : - OMCsurf = 'quadric' - Q=Qform.QFormCyl(Dir,Pos,Rad) - coeffs='{v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} {v[9]:{j}}'\ - .format(v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - else: - if quadricForm : - OMCsurf = 'Quadric' - Q=Qform.QFormCyl(Dir,Pos,Rad) - coeffs='a={v[0]},b={v[1]},c={v[2]},d={v[3]},e={v[4]},f={v[5]},g={v[6]},h={v[7]},j={v[8]},k={v[9]}'.format(v=Q) - else : - OMCsurf = 'Cylinder' - coeffs = 'x0={},y0={},z0={},r={},dx={},dy={},dz={}'.format(Pos.x, Pos.y, Pos.z, Rad, Dir.x, Dir.y, Dir.z) - - elif (Type == 'Cone'): - Apex = surf.Apex*0.1 + if outXML: + OMCsurf = "quadric" + Q = Qform.QFormCyl(Dir, Pos, Rad) + coeffs = "{v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} {v[9]:{j}}".format( + v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + else: + if quadricForm: + OMCsurf = "Quadric" + Q = Qform.QFormCyl(Dir, Pos, Rad) + coeffs = "a={v[0]},b={v[1]},c={v[2]},d={v[3]},e={v[4]},f={v[5]},g={v[6]},h={v[7]},j={v[8]},k={v[9]}".format( + v=Q + ) + else: + OMCsurf = "Cylinder" + coeffs = "x0={},y0={},z0={},r={},dx={},dy={},dz={}".format( + Pos.x, Pos.y, Pos.z, Rad, Dir.x, Dir.y, Dir.z + ) + + elif Type == "Cone": + Apex = surf.Apex * 0.1 Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - tan = math.tan(surf.SemiAngle) + tan = math.tan(surf.SemiAngle) tan2 = tan * tan - X_dir=FreeCAD.Vector(1,0,0) - Y_dir=FreeCAD.Vector(0,1,0) - Z_dir=FreeCAD.Vector(0,0,1) - - if (isParallel(Dir,X_dir,tol.angle)): - if outXML : - OMCsurf = 'x-cone' - coeffs='{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}'.format(Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2) - else: - OMCsurf = 'XCone' - coeffs='x0={},y0={},z0={},r2={}'.format(Apex.x, Apex.y, Apex.z, tan2) - - elif (isParallel(Dir,Y_dir,tol.angle)): - if outXML : - OMCsurf = 'y-cone' - coeffs='{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}'.format(Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2) - else: - OMCsurf = 'YCone' - coeffs='x0={},y0={},z0={},r2={}'.format(Apex.x, Apex.y, Apex.z, tan2) - - elif (isParallel(Dir,Z_dir,tol.angle)): - if outXML : - OMCsurf = 'z-cone' - coeffs='{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}'.format(Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2) - else: - OMCsurf = 'ZCone' - coeffs='x0={},y0={},z0={},r2={}'.format(Apex.x, Apex.y, Apex.z, tan2) + X_dir = FreeCAD.Vector(1, 0, 0) + Y_dir = FreeCAD.Vector(0, 1, 0) + Z_dir = FreeCAD.Vector(0, 0, 1) + + if isParallel(Dir, X_dir, tol.angle): + if outXML: + OMCsurf = "x-cone" + coeffs = "{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}".format( + Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2 + ) + else: + OMCsurf = "XCone" + coeffs = "x0={},y0={},z0={},r2={}".format(Apex.x, Apex.y, Apex.z, tan2) + + elif isParallel(Dir, Y_dir, tol.angle): + if outXML: + OMCsurf = "y-cone" + coeffs = "{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}".format( + Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2 + ) + else: + OMCsurf = "YCone" + coeffs = "x0={},y0={},z0={},r2={}".format(Apex.x, Apex.y, Apex.z, tan2) + + elif isParallel(Dir, Z_dir, tol.angle): + if outXML: + OMCsurf = "z-cone" + coeffs = "{:{xyz}} {:{xyz}} {:{xyz}} {:{t2}}".format( + Apex.x, Apex.y, Apex.z, tan2, xyz=nf.K_xyz, t2=nf.K_tan2 + ) + else: + OMCsurf = "ZCone" + coeffs = "x0={},y0={},z0={},r2={}".format(Apex.x, Apex.y, Apex.z, tan2) else: - if outXML : - OMCsurf = 'quadric' - Q=Qform.QFormCone(Dir,Apex,tan) - coeffs='{v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} {v[9]:{j}}'\ - .format(v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - else: - if quadricForm : - OMCsurf = 'Quadric' - Q=Qform.QFormCone(Dir,Apex,tan) - coeffs='a={v[0]},b={v[1]},c={v[2]},d={v[3]},e={v[4]},f={v[5]},g={v[6]},h={v[7]},j={v[8]},k={v[9]}'.format(v=Q) - else: - OMCsurf = 'Cone' - coeffs='x0={},y0={},z0={},r2={},dx={},dy={},dz={}'.format(Apex.x, Apex.y, Apex.z, tan2, Dir.x, Dir.y, Dir.z) - - elif (Type == 'Sphere'): - Center = surf.Center*0.1 - Rad = surf.Radius*0.1 - if outXML : - OMCsurf = 'sphere' - coeffs = '{:{xyz}} {:{xyz}} {:{xyz}} {:{r}}'.format(Center.x, Center.y, Center.z, Rad, xyz=nf.S_xyz, r=nf.S_r) + if outXML: + OMCsurf = "quadric" + Q = Qform.QFormCone(Dir, Apex, tan) + coeffs = "{v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} {v[9]:{j}}".format( + v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + else: + if quadricForm: + OMCsurf = "Quadric" + Q = Qform.QFormCone(Dir, Apex, tan) + coeffs = "a={v[0]},b={v[1]},c={v[2]},d={v[3]},e={v[4]},f={v[5]},g={v[6]},h={v[7]},j={v[8]},k={v[9]}".format( + v=Q + ) + else: + OMCsurf = "Cone" + coeffs = "x0={},y0={},z0={},r2={},dx={},dy={},dz={}".format( + Apex.x, Apex.y, Apex.z, tan2, Dir.x, Dir.y, Dir.z + ) + + elif Type == "Sphere": + Center = surf.Center * 0.1 + Rad = surf.Radius * 0.1 + if outXML: + OMCsurf = "sphere" + coeffs = "{:{xyz}} {:{xyz}} {:{xyz}} {:{r}}".format( + Center.x, Center.y, Center.z, Rad, xyz=nf.S_xyz, r=nf.S_r + ) else: - OMCsurf = 'Sphere' - coeffs = 'x0={},y0={},z0={},r={}'.format(Center.x, Center.y, Center.z, Rad) + OMCsurf = "Sphere" + coeffs = "x0={},y0={},z0={},r={}".format(Center.x, Center.y, Center.z, Rad) - - elif (Type == 'Torus'): - Center = surf.Center*0.1 - minRad = surf.MinorRadius*0.1 - majRad = surf.MajorRadius*0.1 + elif Type == "Torus": + Center = surf.Center * 0.1 + minRad = surf.MinorRadius * 0.1 + majRad = surf.MajorRadius * 0.1 Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - if outXML : - coeffs ='{:{xyz}} {:{xyz}} {:{xyz}} {:{r}} {:{r}} {:{r}}'.format(Center.x, Center.y, Center.z,\ - majRad, minRad, minRad,\ - xyz=nf.T_xyz,r=nf.T_r) + if outXML: + coeffs = "{:{xyz}} {:{xyz}} {:{xyz}} {:{r}} {:{r}} {:{r}}".format( + Center.x, + Center.y, + Center.z, + majRad, + minRad, + minRad, + xyz=nf.T_xyz, + r=nf.T_r, + ) else: - coeffs ='x0={},y0={},z0={},r{},r1={},r2={}'.format(Center.x, Center.y, Center.z, majRad, minRad, minRad) - - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - OMCsurf = 'x-torus' if outXML else 'XTorus' - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - OMCsurf = 'y-torus' if outXML else 'YTorus' - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - OMCsurf = 'z-torus' if outXML else 'ZTorus' + coeffs = "x0={},y0={},z0={},r{},r1={},r2={}".format( + Center.x, Center.y, Center.z, majRad, minRad, minRad + ) + + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + OMCsurf = "x-torus" if outXML else "XTorus" + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + OMCsurf = "y-torus" if outXML else "YTorus" + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + OMCsurf = "z-torus" if outXML else "ZTorus" else: - OMCsurf = None + OMCsurf = None + + if outXML: + coeffs = " ".join(coeffs.split()) + return OMCsurf, coeffs - if outXML : coeffs = ' '.join(coeffs.split()) - return OMCsurf,coeffs def SerpentSurface(id, Type, surf): - Serpent_def = '' + Serpent_def = "" - if Type == 'Plane': + if Type == "Plane": if surf.pointDef and opt.prnt3PPlane: P1 = surf.Points[0] P2 = surf.Points[1] P3 = surf.Points[2] Serpent_def = f"surf {id} plane {P1.x/10:{nf.P_d}} {P1.y/10:{nf.P_d}} {P1.z/10:{nf.P_d}}\n" - Serpent_def += f" {P2.x/10:{nf.P_d}} {P2.y/10:{nf.P_d}} {P2.z/10:{nf.P_d}}\n" - Serpent_def += f" {P3.x/10:{nf.P_d}} {P3.y/10:{nf.P_d}} {P3.z/10:{nf.P_d}}" + Serpent_def += ( + f" {P2.x/10:{nf.P_d}} {P2.y/10:{nf.P_d}} {P2.z/10:{nf.P_d}}\n" + ) + Serpent_def += ( + f" {P3.x/10:{nf.P_d}} {P3.y/10:{nf.P_d}} {P3.z/10:{nf.P_d}}" + ) else: A = surf.Axis.x @@ -545,136 +673,171 @@ def SerpentSurface(id, Type, surf): else: Serpent_def = f"surf {id} plane {A:{nf.P_d}} {B:{nf.P_d}} {C:{nf.P_d}} {D/10:{nf.P_d}}" - elif Type == 'Cylinder': + elif Type == "Cylinder": Dir = surf.Axis Dir.normalize() - Pos = surf.Center*0.1 - rad = surf.Radius*0.1 + Pos = surf.Center * 0.1 + rad = surf.Radius * 0.1 if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): - Serpent_def = f"surf {id} cylx {Pos.y:{nf.C_xyz}} {Pos.z:{nf.C_xyz}} {rad:{nf.C_r}}" + Serpent_def = ( + f"surf {id} cylx {Pos.y:{nf.C_xyz}} {Pos.z:{nf.C_xyz}} {rad:{nf.C_r}}" + ) elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): - Serpent_def = f"surf {id} cyly {Pos.x:{nf.C_xyz}} {Pos.z:{nf.C_xyz}} {rad:{nf.C_r}}" + Serpent_def = ( + f"surf {id} cyly {Pos.x:{nf.C_xyz}} {Pos.z:{nf.C_xyz}} {rad:{nf.C_r}}" + ) elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): Serpent_def = f"surf {id} cylz {rad:{nf.C_r}}" else: - # Is not still working fine - Q=Qform.QFormCyl(Dir,Pos,rad) - Serpent_def='''\ + # Is not still working fine + Q = Qform.QFormCyl(Dir, Pos, rad) + Serpent_def = """\ surf quadratic {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) - elif Type == 'Cone': - Apex = surf.Apex*0.1 - Dir = surf.Axis*0.1 + elif Type == "Cone": + Apex = surf.Apex * 0.1 + Dir = surf.Axis * 0.1 tan = math.tan(surf.SemiAngle) X_dir = FreeCAD.Vector(1, 0, 0) Y_dir = FreeCAD.Vector(0, 1, 0) Z_dir = FreeCAD.Vector(0, 0, 1) - # Need to check this + # Need to check this # Serpent has no specific card for cone at origin, explicit origin only - if (isParallel(Dir,X_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,X_dir,tol.angle)): sheet=-1 - Serpent_def = 'surf ckx {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Y_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Y_dir,tol.angle)): sheet=-1 - Serpent_def = 'surf cky {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Z_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Z_dir,tol.angle)): sheet=-1 - Serpent_def = 'surf ckz {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) + if isParallel(Dir, X_dir, tol.angle): + sheet = 1 + if isOposite(Dir, X_dir, tol.angle): + sheet = -1 + Serpent_def = "surf ckx {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, Apex.x, Apex.y, Apex.z, tan**2, sheet, xyz=nf.K_xyz, t2=nf.K_tan2 + ) + elif isParallel(Dir, Y_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Y_dir, tol.angle): + sheet = -1 + Serpent_def = "surf cky {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, Apex.x, Apex.y, Apex.z, tan**2, sheet, xyz=nf.K_xyz, t2=nf.K_tan2 + ) + elif isParallel(Dir, Z_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Z_dir, tol.angle): + sheet = -1 + Serpent_def = "surf ckz {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, Apex.x, Apex.y, Apex.z, tan**2, sheet, xyz=nf.K_xyz, t2=nf.K_tan2 + ) else: - Q=Qform.QFormCone(Dir,Apex,tan) - MCNP_def='''\ + Q = Qform.QFormCone(Dir, Apex, tan) + MCNP_def = """\ surf quadratic {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) - elif Type == 'Sphere': - rad = surf.Radius*0.1 - pnt = surf.Center*0.1 + elif Type == "Sphere": + rad = surf.Radius * 0.1 + pnt = surf.Center * 0.1 # Serpent has only explicit spheres at the origin Serpent_def = f"surf {id} sph {pnt.x:{nf.S_xyz}} {pnt.y:{nf.S_xyz}} {pnt.z:{nf.S_xyz}} {rad:{nf.S_r}}" - elif Type == 'Torus': + elif Type == "Torus": Dir = surf.Axis Dir.normalize() - Pos = surf.Center*0.1 - radMaj = surf.MajorRadius*0.1 - radMin = surf.MinorRadius*0.1 - if (isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle)): + Pos = surf.Center * 0.1 + radMaj = surf.MajorRadius * 0.1 + radMin = surf.MinorRadius * 0.1 + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): Serpent_def = f"surf {id} torx {Pos.x:{nf.T_xyz}} {Pos.y:{nf.T_xyz}} {Pos.z:{nf.T_xyz}}\n" - Serpent_def += f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" - elif (isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle)): + Serpent_def += ( + f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" + ) + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): Serpent_def = f"surf {id} tory {Pos.x:{nf.T_xyz}} {Pos.y:{nf.T_xyz}} {Pos.z:{nf.T_xyz}}\n" - Serpent_def += f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" - elif (isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle)): + Serpent_def += ( + f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" + ) + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): Serpent_def = f"surf {id} torz {Pos.x:{nf.T_xyz}} {Pos.y:{nf.T_xyz}} {Pos.z:{nf.T_xyz}}\n" - Serpent_def += f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" + Serpent_def += ( + f" {radMaj:{nf.T_r}} {radMin:{nf.T_r}} {radMin:{nf.T_r}}" + ) return Serpent_def -def PHITSSurface(id,Type,surf): - PHITS_def = '' - if (Type=='Plane'): - if surf.pointDef and opt.prnt3PPlane: - P1 = surf.Points[0] - P2 = surf.Points[1] - P3 = surf.Points[2] - PHITS_def="""{:<6d} P {P1[0]:{d}} {P1[1]:{d}} {P1[2]:{d}} +def PHITSSurface(id, Type, surf): + PHITS_def = "" + + if Type == "Plane": + if surf.pointDef and opt.prnt3PPlane: + P1 = surf.Points[0] + P2 = surf.Points[1] + P3 = surf.Points[2] + PHITS_def = """{:<6d} P {P1[0]:{d}} {P1[1]:{d}} {P1[2]:{d}} {P2[0]:{d}} {P2[1]:{d}} {P2[2]:{d}} - {P3[0]:{d}} {P3[1]:{d}} {P3[2]:{d}}""".format(id,P1=P1/10,P2=P2/10,P3=P3/10,d=nf.P_d) - else: - A=surf.Axis.x - B=surf.Axis.y - C=surf.Axis.z - D=surf.Axis.dot(surf.Position) - if surf.Axis.isEqual(FreeCAD.Vector(1,0,0),tol.pln_angle) : - PHITS_def='{:<6d} PX {:{x}}'.format(id,D/10.0,x=nf.P_xyz) - elif surf.Axis.isEqual(FreeCAD.Vector(0,1,0),tol.pln_angle) : - PHITS_def='{:<6d} PY {:{y}}'.format(id,D/10.0,y=nf.P_xyz) - elif surf.Axis.isEqual(FreeCAD.Vector(0,0,1),tol.pln_angle) : - PHITS_def='{:<6d} PZ {:{z}}'.format(id,D/10.0,z=nf.P_xyz) - else: - PHITS_def='{:<6d} P {:{abc}} {:{abc}} {:{abc}} {:{d}}'.format(id,A,B,C,D/10.0,abc=nf.P_abc,d=nf.P_d) - - elif (Type == 'Cylinder'): + {P3[0]:{d}} {P3[1]:{d}} {P3[2]:{d}}""".format( + id, P1=P1 / 10, P2=P2 / 10, P3=P3 / 10, d=nf.P_d + ) + else: + A = surf.Axis.x + B = surf.Axis.y + C = surf.Axis.z + D = surf.Axis.dot(surf.Position) + if surf.Axis.isEqual(FreeCAD.Vector(1, 0, 0), tol.pln_angle): + PHITS_def = "{:<6d} PX {:{x}}".format(id, D / 10.0, x=nf.P_xyz) + elif surf.Axis.isEqual(FreeCAD.Vector(0, 1, 0), tol.pln_angle): + PHITS_def = "{:<6d} PY {:{y}}".format(id, D / 10.0, y=nf.P_xyz) + elif surf.Axis.isEqual(FreeCAD.Vector(0, 0, 1), tol.pln_angle): + PHITS_def = "{:<6d} PZ {:{z}}".format(id, D / 10.0, z=nf.P_xyz) + else: + PHITS_def = "{:<6d} P {:{abc}} {:{abc}} {:{abc}} {:{d}}".format( + id, A, B, C, D / 10.0, abc=nf.P_abc, d=nf.P_d + ) + + elif Type == "Cylinder": Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - Pos = surf.Center*0.1 - rad = surf.Radius*0.1 - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - if (Pos.y == 0.0 and Pos.z == 0.0): - PHITS_def='{:<6d} CX {:{r}}'.format(id,rad,r=nf.C_r) - else: - PHITS_def='{:<6d} C/X {:{yz}} {:{yz}} {:{r}}'.format(id,Pos.y,Pos.z,rad,yz=nf.C_xyz,r=nf.C_r) - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - if (Pos.x == 0.0 and Pos.z == 0.0): - PHITS_def='{:<6d} CY {:{r}}'.format(id,rad,r=nf.C_r) - else: - PHITS_def='{:<6d} C/Y {:{xz}} {:{xz}} {:{r}}'.format(id,Pos.x,Pos.z,rad,xz=nf.C_xyz,r=nf.C_r) - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - if (Pos.y == 0.0 and Pos.x == 0.0): - PHITS_def='{:<6d} CZ {:{r}}'.format(id,rad,r=nf.C_r) - else: - PHITS_def='{:<6d} C/Z {:{xy}} {:{xy}} {:{r}}'.format(id,Pos.x,Pos.y,rad,xy=nf.C_xyz,r=nf.C_r) + Pos = surf.Center * 0.1 + rad = surf.Radius * 0.1 + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + if Pos.y == 0.0 and Pos.z == 0.0: + PHITS_def = "{:<6d} CX {:{r}}".format(id, rad, r=nf.C_r) + else: + PHITS_def = "{:<6d} C/X {:{yz}} {:{yz}} {:{r}}".format( + id, Pos.y, Pos.z, rad, yz=nf.C_xyz, r=nf.C_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + if Pos.x == 0.0 and Pos.z == 0.0: + PHITS_def = "{:<6d} CY {:{r}}".format(id, rad, r=nf.C_r) + else: + PHITS_def = "{:<6d} C/Y {:{xz}} {:{xz}} {:{r}}".format( + id, Pos.x, Pos.z, rad, xz=nf.C_xyz, r=nf.C_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + if Pos.y == 0.0 and Pos.x == 0.0: + PHITS_def = "{:<6d} CZ {:{r}}".format(id, rad, r=nf.C_r) + else: + PHITS_def = "{:<6d} C/Z {:{xy}} {:{xy}} {:{r}}".format( + id, Pos.x, Pos.y, rad, xy=nf.C_xyz, r=nf.C_r + ) else: - # Is not still working fine - Q=Qform.QFormCyl(Dir,Pos,rad) - PHITS_def='''\ + # Is not still working fine + Q = Qform.QFormCyl(Dir, Pos, rad) + PHITS_def = """\ {:<6d} GQ {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + # Si se quiere rcc en vez de Q form # pnt = surf.Center.sub(surf.Axis.multiply(1.0e7)) # mas alla de 100 m # dir = surf.Axis.multiply(1.0e8) @@ -686,117 +849,159 @@ def PHITSSurface(id,Type,surf): # Hz= dir.z/10.0 # rad=surf.Radius/10.0 # MCNP_def='%i RCC %13.7E %13.7E %13.7E %13.7E\n %13.7E %13.7E %13.7E' %(id,Vx,Vy,Vz,Hx,Hy,Hz,rad) - - elif (Type == 'Cone'): - Apex = surf.Apex*0.1 - Dir = surf.Axis*0.1 + + elif Type == "Cone": + Apex = surf.Apex * 0.1 + Dir = surf.Axis * 0.1 tan = math.tan(surf.SemiAngle) - X_dir=FreeCAD.Vector(1,0,0) - Y_dir=FreeCAD.Vector(0,1,0) - Z_dir=FreeCAD.Vector(0,0,1) - if (isParallel(Dir,X_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,X_dir,tol.angle)): sheet=-1 - if (Apex.y == 0.0 and Apex.z == 0.0): - PHITS_def='{:<6d} KX {:{x}} {:{t2}} {}'.format(id,Apex.x,tan**2,sheet,x=nf.K_xyz,t2=nf.K_tan2) - else: - PHITS_def='{:<6d} K/X {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Y_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Y_dir,tol.angle)): sheet=-1 - if (Apex.x == 0.0 and Apex.z == 0.0): - PHITS_def='{:<6d} KY {:{y}} {:{t2}} {}'.format(id,Apex.y,tan**2,sheet,y=nf.K_xyz,t2=nf.K_tan2) - else: - PHITS_def='{:<6d} K/Y {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) - elif (isParallel(Dir,Z_dir,tol.angle)): - sheet=1 - if (isOposite(Dir,Z_dir,tol.angle)): sheet=-1 - if (Apex.x == 0.0 and Apex.y == 0.0): - PHITS_def='{:<6d} KZ {:{z}} {:{t2}} {}'.format(id,Apex.z,tan**2,sheet,z=nf.K_xyz,t2=nf.K_tan2) - else: - PHITS_def='{:<6d} K/Z {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}'.format(id,Apex.x,Apex.y,Apex.z,tan**2,sheet,xyz=nf.K_xyz,t2=nf.K_tan2) + X_dir = FreeCAD.Vector(1, 0, 0) + Y_dir = FreeCAD.Vector(0, 1, 0) + Z_dir = FreeCAD.Vector(0, 0, 1) + if isParallel(Dir, X_dir, tol.angle): + sheet = 1 + if isOposite(Dir, X_dir, tol.angle): + sheet = -1 + if Apex.y == 0.0 and Apex.z == 0.0: + PHITS_def = "{:<6d} KX {:{x}} {:{t2}} {}".format( + id, Apex.x, tan**2, sheet, x=nf.K_xyz, t2=nf.K_tan2 + ) + else: + PHITS_def = "{:<6d} K/X {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) + elif isParallel(Dir, Y_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Y_dir, tol.angle): + sheet = -1 + if Apex.x == 0.0 and Apex.z == 0.0: + PHITS_def = "{:<6d} KY {:{y}} {:{t2}} {}".format( + id, Apex.y, tan**2, sheet, y=nf.K_xyz, t2=nf.K_tan2 + ) + else: + PHITS_def = "{:<6d} K/Y {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) + elif isParallel(Dir, Z_dir, tol.angle): + sheet = 1 + if isOposite(Dir, Z_dir, tol.angle): + sheet = -1 + if Apex.x == 0.0 and Apex.y == 0.0: + PHITS_def = "{:<6d} KZ {:{z}} {:{t2}} {}".format( + id, Apex.z, tan**2, sheet, z=nf.K_xyz, t2=nf.K_tan2 + ) + else: + PHITS_def = "{:<6d} K/Z {:{xyz}} {:{xyz}} {:{xyz}} {:{t2}} {}".format( + id, + Apex.x, + Apex.y, + Apex.z, + tan**2, + sheet, + xyz=nf.K_xyz, + t2=nf.K_tan2, + ) else: - Q=Qform.QFormCone(Dir,Apex,tan) - PHITS_def='''\ + Q = Qform.QFormCone(Dir, Apex, tan) + PHITS_def = """\ {:<6d} GQ {v[0]:{aTof}} {v[1]:{aTof}} {v[2]:{aTof}} {v[3]:{aTof}} {v[4]:{aTof}} {v[5]:{aTof}} {v[6]:{gToi}} {v[7]:{gToi}} {v[8]:{gToi}} - {v[9]:{j}} '''.format(id,v=Q,aTof=nf.GQ_1to6,gToi=nf.GQ_7to9,j=nf.GQ_10) - - elif (Type == 'Sphere'): - # corresponding logic - rad = surf.Radius*0.1 - pnt = surf.Center*0.1 - if pnt.isEqual(FreeCAD.Vector(0,0,0),tol.sph_distance): - PHITS_def='{:<6d} SO {:{r}}'.format(id,rad,r=nf.S_r) + {v[9]:{j}} """.format( + id, v=Q, aTof=nf.GQ_1to6, gToi=nf.GQ_7to9, j=nf.GQ_10 + ) + + elif Type == "Sphere": + # corresponding logic + rad = surf.Radius * 0.1 + pnt = surf.Center * 0.1 + if pnt.isEqual(FreeCAD.Vector(0, 0, 0), tol.sph_distance): + PHITS_def = "{:<6d} SO {:{r}}".format(id, rad, r=nf.S_r) else: - PHITS_def='{:<6d} S {:{xyz}} {:{xyz}} {:{xyz}} {:{r}}'.format(id,pnt.x,pnt.y,pnt.z,rad,xyz=nf.S_xyz,r=nf.S_r) + PHITS_def = "{:<6d} S {:{xyz}} {:{xyz}} {:{xyz}} {:{r}}".format( + id, pnt.x, pnt.y, pnt.z, rad, xyz=nf.S_xyz, r=nf.S_r + ) - elif (Type == 'Torus'): + elif Type == "Torus": Dir = FreeCAD.Vector(surf.Axis) Dir.normalize() - Pos = surf.Center*0.1 - radMaj = surf.MajorRadius*0.1 - radMin = surf.MinorRadius*0.1 - if (isParallel(Dir,FreeCAD.Vector(1,0,0),tol.angle)): - PHITS_def='''\ + Pos = surf.Center * 0.1 + radMaj = surf.MajorRadius * 0.1 + radMin = surf.MinorRadius * 0.1 + if isParallel(Dir, FreeCAD.Vector(1, 0, 0), tol.angle): + PHITS_def = """\ {:<6d} TX {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) - elif (isParallel(Dir,FreeCAD.Vector(0,1,0),tol.angle)): - PHITS_def='''\ + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 1, 0), tol.angle): + PHITS_def = """\ {:<6d} TY {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) - elif (isParallel(Dir,FreeCAD.Vector(0,0,1),tol.angle)): - PHITS_def='''\ + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) + elif isParallel(Dir, FreeCAD.Vector(0, 0, 1), tol.angle): + PHITS_def = """\ {:<6d} TZ {:{xyz}} {:{xyz}} {:{xyz}} - {:{r}} {:{r}} {:{r}}'''.format(id,Pos.x,Pos.y,Pos.z, \ - radMaj,radMin,radMin,\ - xyz=nf.T_xyz,r=nf.T_r) + {:{r}} {:{r}} {:{r}}""".format( + id, Pos.x, Pos.y, Pos.z, radMaj, radMin, radMin, xyz=nf.T_xyz, r=nf.T_r + ) - return trim(PHITS_def,80) - -def trim(surfDef,lineLength=80): + return trim(PHITS_def, 80) - lines = surfDef.split('\n') - if len(lines) == 1 and len(lines[0]) <= lineLength : + +def trim(surfDef, lineLength=80): + + lines = surfDef.split("\n") + if len(lines) == 1 and len(lines[0]) <= lineLength: return surfDef - + longLine = [] - for i,line in enumerate(lines): - if len(line) > lineLength : - longLine.append(i) + for i, line in enumerate(lines): + if len(line) > lineLength: + longLine.append(i) - if len(longLine) == 0 : + if len(longLine) == 0: return surfDef - newDef = '' - for i,line in enumerate(lines): - if i in longLine : - newLine = cutLine(line,lineLength) - else: - newLine = line - newDef += newLine + '\n' + newDef = "" + for i, line in enumerate(lines): + if i in longLine: + newLine = cutLine(line, lineLength) + else: + newLine = line + newDef += newLine + "\n" return newDef[:-1] -def cutLine(line,lineLength): - tabNumber = 10 +def cutLine(line, lineLength): + tabNumber = 10 while True: - pos = line.rfind(' ') - if pos <= lineLength : break + pos = line.rfind(" ") + if pos <= lineLength: + break line1 = line[0:pos] - line2 = line[pos+1:] + line2 = line[pos + 1 :] # second line is only spaces - if len(line2.strip()) == 0 : - newLine = line1 + if len(line2.strip()) == 0: + newLine = line1 else: - newLine = '{}\n{: <{n}}{}'.format(line1,'',line2,n=tabNumber) + newLine = "{}\n{: <{n}}{}".format(line1, "", line2, n=tabNumber) - return newLine + return newLine diff --git a/src/geouned/GEOUNED/Write/MCNPFormat.py b/src/geouned/GEOUNED/Write/MCNPFormat.py index 4695198d..7e76fb44 100644 --- a/src/geouned/GEOUNED/Write/MCNPFormat.py +++ b/src/geouned/GEOUNED/Write/MCNPFormat.py @@ -14,92 +14,97 @@ class MCNP_input: - def __init__(self,Meta,Surfaces,setting) : - self.Title = setting['title'] - self.VolSDEF = setting['volSDEF'] - self.VolCARD = setting['volCARD'] - self.U0CARD = setting['UCARD'] - self.dummyMat = setting['dummyMat'] - self.Cells = Meta - self.Options = {'Volume':self.VolCARD,'Particle':('n','p'),'Universe':self.U0CARD} - self.part = 'P' - - self.StepFile = setting['stepFile'] - if isinstance(self.StepFile,(tuple,list)): - self.StepFile = "; ".join(self.StepFile) - - if self.Title == '' : - self.Title = self.StepFile - - self.__getSurfaceTable__() - self.__simplifyPlanes__(Surfaces) - - self.Surfaces = self.__sortedSurfaces__(Surfaces) - self.Materials = set() - - return - - def setSDEF(self,data): - + def __init__(self, Meta, Surfaces, setting): + self.Title = setting["title"] + self.VolSDEF = setting["volSDEF"] + self.VolCARD = setting["volCARD"] + self.U0CARD = setting["UCARD"] + self.dummyMat = setting["dummyMat"] + self.Cells = Meta + self.Options = { + "Volume": self.VolCARD, + "Particle": ("n", "p"), + "Universe": self.U0CARD, + } + self.part = "P" + + self.StepFile = setting["stepFile"] + if isinstance(self.StepFile, (tuple, list)): + self.StepFile = "; ".join(self.StepFile) + + if self.Title == "": + self.Title = self.StepFile + + self.__getSurfaceTable__() + self.__simplifyPlanes__(Surfaces) + + self.Surfaces = self.__sortedSurfaces__(Surfaces) + self.Materials = set() + + return + + def setSDEF(self, data): + if data[0] is not None: - sphereId = data[0][0] - radius = data[0][1] - wgt = math.pi*radius*radius*1e-2 - sdef = 'SDEF PAR={} NRM=-1 SUR={} WGT={:13.7e} DIR=d1\n'.format(self.part,sphereId,wgt) - SI1 = 'SI1 0 1\n' - SP1 = 'SP1 -21 1\n' - self.SDEF_sphere = (sdef,SI1,SP1) - else: - self.SDEF_sphere = None - xmin,xmax,ymin,ymax,zmin,zmax = data[1] - - sdef = 'SDEF PAR={} X=D1 Y=D2 Z=D3 \n'.format(self.part) - SI1 = 'SI1 {:13.7e} {:13.7e} \n'.format(xmin*0.1,xmax*0.1) - SI2 = 'SI2 {:13.7e} {:13.7e} \n'.format(ymin*0.1,ymax*0.1) - SI3 = 'SI3 {:13.7e} {:13.7e} \n'.format(zmin*0.1,zmax*0.1) - SP1 = 'SP1 0 1 \n' - SP2 = 'SP2 0 1 \n' - SP3 = 'SP3 0 1 \n' - self.SDEF_box = (sdef,SI1,SI2,SI3,SP1,SP2,SP3) - - def writeInput(self,filename): - print ('write MCNP file {}'.format(filename)) - self.inpfile=open(filename,'w',encoding='utf-8') - self.__write_header__(filename) - self.__write_cell_block__() - self.inpfile.write(' \n') - - surfaceHeader="""\ + sphereId = data[0][0] + radius = data[0][1] + wgt = math.pi * radius * radius * 1e-2 + sdef = "SDEF PAR={} NRM=-1 SUR={} WGT={:13.7e} DIR=d1\n".format( + self.part, sphereId, wgt + ) + SI1 = "SI1 0 1\n" + SP1 = "SP1 -21 1\n" + self.SDEF_sphere = (sdef, SI1, SP1) + else: + self.SDEF_sphere = None + xmin, xmax, ymin, ymax, zmin, zmax = data[1] + + sdef = "SDEF PAR={} X=D1 Y=D2 Z=D3 \n".format(self.part) + SI1 = "SI1 {:13.7e} {:13.7e} \n".format(xmin * 0.1, xmax * 0.1) + SI2 = "SI2 {:13.7e} {:13.7e} \n".format(ymin * 0.1, ymax * 0.1) + SI3 = "SI3 {:13.7e} {:13.7e} \n".format(zmin * 0.1, zmax * 0.1) + SP1 = "SP1 0 1 \n" + SP2 = "SP2 0 1 \n" + SP3 = "SP3 0 1 \n" + self.SDEF_box = (sdef, SI1, SI2, SI3, SP1, SP2, SP3) + + def writeInput(self, filename): + print("write MCNP file {}".format(filename)) + self.inpfile = open(filename, "w", encoding="utf-8") + self.__write_header__(filename) + self.__write_cell_block__() + self.inpfile.write(" \n") + + surfaceHeader = """\ C ########################################################## C SURFACE DEFINITION C ########################################################## """ - self.inpfile.write(surfaceHeader) - self.__write_surface_block__() - self.inpfile.write(' \n') - - self.__write_source_block__() - - self.inpfile.close() - return - - def __write_header__(self,fileout): - - version = GEOUNED_Version - releaseDate = GEOUNED_ReleaseDate - freeCAD_Version = '{V[0]:}.{V[1]:}.{V[2]:}'.format(V=FreeCAD.Version()) - - Header = \ -"""{} + self.inpfile.write(surfaceHeader) + self.__write_surface_block__() + self.inpfile.write(" \n") + + self.__write_source_block__() + + self.inpfile.close() + return + + def __write_header__(self, fileout): + + version = GEOUNED_Version + releaseDate = GEOUNED_ReleaseDate + freeCAD_Version = "{V[0]:}.{V[1]:}.{V[2]:}".format(V=FreeCAD.Version()) + + Header = """{} C ______ _______ _____ _ _ __ _ _______ ______ C | ____ |______ | | ___ | | | \ | |______ | \ C |_____| |______ |_____| |_____| | \_| |______ |_____/ C Version : {} {} -C FreeCAD Version : {} \n""".format(self.Title,version,releaseDate,freeCAD_Version) +C FreeCAD Version : {} \n""".format( + self.Title, version, releaseDate, freeCAD_Version + ) - - Information = \ -"""C + Information = """C C ************************************************************* C Original Step file : {} C @@ -109,246 +114,254 @@ def __write_header__(self,fileout): C Surfaces : {} C Materials : {} C -C **************************************************************\n""".format(self.StepFile ,\ - datetime.now() ,\ - self.__solidCells__ ,\ - self.__cells__ ,\ - len(self.Surfaces), \ - len(self.__materials__) ) - self.inpfile.write(Header) - self.inpfile.write(Information) - return - - def __write_cell_block__(self): +C **************************************************************\n""".format( + self.StepFile, + datetime.now(), + self.__solidCells__, + self.__cells__, + len(self.Surfaces), + len(self.__materials__), + ) + self.inpfile.write(Header) + self.inpfile.write(Information) + return - for i,cell in enumerate(self.Cells): - self.__write_cells__(cell) - return + def __write_cell_block__(self): + for i, cell in enumerate(self.Cells): + self.__write_cells__(cell) + return def __write_surface_block__(self): - for surf in self.Surfaces: - self.__write_surfaces__(surf) - + for surf in self.Surfaces: + self.__write_surfaces__(surf) - def __write_cells__(self,cell): + def __write_cells__(self, cell): - index = cell.label + index = cell.label - # if index is None objet not contain cell definition - # but a comment to insert between cells - if cell.__id__ is None : - comment = self.__commentLine__(cell.Comments) - self.inpfile.write(comment) - return - - if cell.Material == 0: - cellHeader = '{:<5d} {:<5d} '.format(index,0) - else: - self.Materials.add(cell.Material) - if abs(cell.Density) < 1e-2 : - cellHeader = '{:<5d} {:<5d} {:11.4e} '.format(index,cell.Material,cell.Density) - else: - cellHeader = '{:<5d} {:<5d} {:11.7f} '.format(index,cell.Material,cell.Density) - - mcnpcell = '{}{}\n{}{}'.format( cellHeader ,\ - self.__cellFormat__(cell.Definition,offset=len(cellHeader)) ,\ - self.__optionFormat__(cell) ,\ - self.__commentFormat__(cell.Comments,cell.MatInfo)) - self.inpfile.write(mcnpcell) - return + # if index is None objet not contain cell definition + # but a comment to insert between cells + if cell.__id__ is None: + comment = self.__commentLine__(cell.Comments) + self.inpfile.write(comment) + return + if cell.Material == 0: + cellHeader = "{:<5d} {:<5d} ".format(index, 0) + else: + self.Materials.add(cell.Material) + if abs(cell.Density) < 1e-2: + cellHeader = "{:<5d} {:<5d} {:11.4e} ".format( + index, cell.Material, cell.Density + ) + else: + cellHeader = "{:<5d} {:<5d} {:11.7f} ".format( + index, cell.Material, cell.Density + ) + + mcnpcell = "{}{}\n{}{}".format( + cellHeader, + self.__cellFormat__(cell.Definition, offset=len(cellHeader)), + self.__optionFormat__(cell), + self.__commentFormat__(cell.Comments, cell.MatInfo), + ) + self.inpfile.write(mcnpcell) + return + + def __write_surfaces__(self, surface): + """Write the surfaces in MCNP format""" + + MCNP_def = MCNPSurface(surface.Index, surface.Type, surface.Surf) + if MCNP_def: + MCNP_def += "\n" + self.inpfile.write(MCNP_def) + else: + print("Surface {} cannot be written in MCNP input".format(surface.Type)) + return - def __write_surfaces__(self,surface): - """ Write the surfaces in MCNP format """ + def __write_source_block__(self): - MCNP_def = MCNPSurface(surface.Index, surface.Type, surface.Surf) - if MCNP_def : - MCNP_def += '\n' - self.inpfile.write(MCNP_def) - else: - print('Surface {} cannot be written in MCNP input'.format(surface.Type)) - return + if self.SDEF_sphere is None: + return - def __write_source_block__(self): - - if self.SDEF_sphere is None: return - - MODE = 'MODE {}\nVOID \nNPS 1e6\n'.format(self.part) - if self.dummyMat : - mat = list(self.Materials) - mat.sort() - MATCARD = '' - for m in mat: - MATCARD += 'M{:<6d} 1001 1\n'.format(m) - Block = MATCARD+'C \n'+MODE - else: - Block = MODE - - if self.VolSDEF: - Block += 'PRDMP 2J -1\n' - for line in self.SDEF_box : - Block += 'C ' + line - for line in self.SDEF_sphere: - Block += line - - celList,volList = self.__get_solidCellVolume__() - - F4Tally = CardLine('F4:{} '.format(self.part)) - F4Tally.extend(celList) - SD4 = CardLine('SD4 ',fmt='13.7e') - SD4.extend(volList) - - Block += F4Tally.str+'\n' - if not self.VolCARD : - Block += SD4.str - else : - Block += 'C Cell volume normalization is set in cell cards VOL\n' - else : - for line in self.SDEF_sphere : - Block += 'C ' + line - for line in self.SDEF_box : - Block += line - - - self.inpfile.write(Block) - - - - def __cellFormat__(self,Definition,offset=11): - return writeMCNPCellDef(Definition,tabspace=11,offset=offset) - - - def __optionFormat__(self,cell): - - option = '' - if self.Options['Volume']: - if not cell.Void : - option ='{:11s}Vol={:e}\n'.format('',cell.Volume*1e-3) - else: - option = '{:11s}Vol=1.0\n'.format('') - - option += '{:11s}'.format('') - for p in self.Options['Particle']: - if cell.MatInfo == 'Graveyard' : - option += 'imp:{}=0 '.format(p) - else: - option += 'imp:{}=1.0 '.format(p) - - if self.Options['Universe'] is not None: - option += 'U={} '.format(self.Options['Universe']) - option += '\n' - - return option - - def __commentFormat__(self,cComment,mComment=None): - - comment = '' - if mComment : - mComment = mComment.split('\n') - for c in mComment : - if c : comment += '{:11s}${}\n'.format('',c) - - if cComment.strip() != '': - cComment = cComment.strip().split('\n') - for c in cComment: - if c: comment += '{:11s}${}\n'.format('',c) - return comment - - def __commentLine__(self,lineComment): - lineComment = lineComment.strip().split('\n') - comment = '' - if lineComment : - comment = 'C \n' - for c in lineComment: - if c: comment += 'C {}\n'.format(c) - comment += 'C \n' - return comment + MODE = "MODE {}\nVOID \nNPS 1e6\n".format(self.part) + if self.dummyMat: + mat = list(self.Materials) + mat.sort() + MATCARD = "" + for m in mat: + MATCARD += "M{:<6d} 1001 1\n".format(m) + Block = MATCARD + "C \n" + MODE + else: + Block = MODE + + if self.VolSDEF: + Block += "PRDMP 2J -1\n" + for line in self.SDEF_box: + Block += "C " + line + for line in self.SDEF_sphere: + Block += line + + celList, volList = self.__get_solidCellVolume__() + + F4Tally = CardLine("F4:{} ".format(self.part)) + F4Tally.extend(celList) + SD4 = CardLine("SD4 ", fmt="13.7e") + SD4.extend(volList) + + Block += F4Tally.str + "\n" + if not self.VolCARD: + Block += SD4.str + else: + Block += "C Cell volume normalization is set in cell cards VOL\n" + else: + for line in self.SDEF_sphere: + Block += "C " + line + for line in self.SDEF_box: + Block += line + + self.inpfile.write(Block) + + def __cellFormat__(self, Definition, offset=11): + return writeMCNPCellDef(Definition, tabspace=11, offset=offset) + + def __optionFormat__(self, cell): + + option = "" + if self.Options["Volume"]: + if not cell.Void: + option = "{:11s}Vol={:e}\n".format("", cell.Volume * 1e-3) + else: + option = "{:11s}Vol=1.0\n".format("") + + option += "{:11s}".format("") + for p in self.Options["Particle"]: + if cell.MatInfo == "Graveyard": + option += "imp:{}=0 ".format(p) + else: + option += "imp:{}=1.0 ".format(p) + + if self.Options["Universe"] is not None: + option += "U={} ".format(self.Options["Universe"]) + option += "\n" + + return option + + def __commentFormat__(self, cComment, mComment=None): + + comment = "" + if mComment: + mComment = mComment.split("\n") + for c in mComment: + if c: + comment += "{:11s}${}\n".format("", c) + + if cComment.strip() != "": + cComment = cComment.strip().split("\n") + for c in cComment: + if c: + comment += "{:11s}${}\n".format("", c) + return comment + + def __commentLine__(self, lineComment): + lineComment = lineComment.strip().split("\n") + comment = "" + if lineComment: + comment = "C \n" + for c in lineComment: + if c: + comment += "C {}\n".format(c) + comment += "C \n" + return comment def __getSurfaceTable__(self): - self.surfaceTable = {} - self.__solidCells__ = 0 - self.__cells__ = 0 - self.__materials__ = set() - - for i, CellObj in enumerate(self.Cells): - if CellObj.__id__ is None : continue - self.__cells__ += 1 - if CellObj.Material != 0 : - self.__materials__.add(CellObj.Material) - - surf = CellObj.Definition.getSurfacesNumbers() - if not CellObj.Void : self.__solidCells__ += 1 - for index in surf : - if index in self.surfaceTable.keys() : - self.surfaceTable[index].add(i) - else: - self.surfaceTable[index] = {i} - return - - - def __simplifyPlanes__(self,Surfaces): - offset = len(self.Cells) - keys= self.surfaceTable.keys() - - for p in Surfaces['PX']: - if p.Surf.Axis[0] < 0 : - p.Surf.Axis = FreeCAD.Vector(1,0,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PY']: - if p.Surf.Axis[1] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,1,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PZ']: - if p.Surf.Axis[2] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,0,1) - self.__changeSurfSign__(p) - - if opt.prnt3PPlane : - for p in Surfaces['P']: - if p.Surf.pointDef: - axis,d = pointsToCoeffs(p.Surf.Points) - if isOposite(axis,p.Surf.Axis) : - self.__changeSurfSign__(p) - - return - - def __sortedSurfaces__(self,Surfaces): + self.surfaceTable = {} + self.__solidCells__ = 0 + self.__cells__ = 0 + self.__materials__ = set() + + for i, CellObj in enumerate(self.Cells): + if CellObj.__id__ is None: + continue + self.__cells__ += 1 + if CellObj.Material != 0: + self.__materials__.add(CellObj.Material) + + surf = CellObj.Definition.getSurfacesNumbers() + if not CellObj.Void: + self.__solidCells__ += 1 + for index in surf: + if index in self.surfaceTable.keys(): + self.surfaceTable[index].add(i) + else: + self.surfaceTable[index] = {i} + return + + def __simplifyPlanes__(self, Surfaces): + offset = len(self.Cells) + keys = self.surfaceTable.keys() + + for p in Surfaces["PX"]: + if p.Surf.Axis[0] < 0: + p.Surf.Axis = FreeCAD.Vector(1, 0, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PY"]: + if p.Surf.Axis[1] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 1, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PZ"]: + if p.Surf.Axis[2] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 0, 1) + self.__changeSurfSign__(p) + + if opt.prnt3PPlane: + for p in Surfaces["P"]: + if p.Surf.pointDef: + axis, d = pointsToCoeffs(p.Surf.Points) + if isOposite(axis, p.Surf.Axis): + self.__changeSurfSign__(p) + + return + + def __sortedSurfaces__(self, Surfaces): temp = Surfaces_dict(Surfaces) surfList = [] - for ind in range(Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset): - s=temp.getSurface(ind+1) - if s is not None : - surfList.append(s) - temp.delSurface(ind+1) + for ind in range( + Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset + ): + s = temp.getSurface(ind + 1) + if s is not None: + surfList.append(s) + temp.delSurface(ind + 1) return surfList - - def __changeSurfSign__(self,p): - if p.Index not in self.surfaceTable.keys() : - print('{} Surface {} not used in cell definition)'.format(p.Type,p.Index),p.Surf.Axis,p.Surf.Position) + def __changeSurfSign__(self, p): + + if p.Index not in self.surfaceTable.keys(): + print( + "{} Surface {} not used in cell definition)".format(p.Type, p.Index), + p.Surf.Axis, + p.Surf.Position, + ) return - - for ic in self.surfaceTable[p.Index] : - surf = self.Cells[ic].Definition.getSurfacesNumbers() - for s in surf : - if s == p.Index : - changeSurfSign(s, self.Cells[ic].Definition) + for ic in self.surfaceTable[p.Index]: + surf = self.Cells[ic].Definition.getSurfacesNumbers() + for s in surf: + if s == p.Index: + changeSurfSign(s, self.Cells[ic].Definition) def __get_solidCellVolume__(self): solidList = [] volumeList = [] - for m in self.Cells : - if m.CellType == 'solid' and m.__id__ is not None: - solidList.append(m.label) - volumeList.append(m.Volume*1e-3) - - return solidList, volumeList - - - + for m in self.Cells: + if m.CellType == "solid" and m.__id__ is not None: + solidList.append(m.label) + volumeList.append(m.Volume * 1e-3) + + return solidList, volumeList diff --git a/src/geouned/GEOUNED/Write/OpenMCFormat.py b/src/geouned/GEOUNED/Write/OpenMCFormat.py index 5a92b01c..48ebfd68 100644 --- a/src/geouned/GEOUNED/Write/OpenMCFormat.py +++ b/src/geouned/GEOUNED/Write/OpenMCFormat.py @@ -11,108 +11,111 @@ class OpenMC_input: - def __init__(self,Meta,Surfaces,setting) : - - self.Cells = Meta - - self.__getSurfaceTable__() - self.__simplifyPlanes__(Surfaces) - - self.Surfaces = self.__sortedSurfaces__(Surfaces) - self.Materials = set() - - def writeXML(self,filename): - print ('write OpenMC xml file {}'.format(filename)) - self.inpfile=open(filename,'w',encoding='utf-8') - self.__write_xml_header__(filename) - - self.inpfile.write("\n") - self.__write_xml_cell_block__() - self.inpfile.write(' \n') - self.__write_xml_surface_block__() - self.inpfile.write("\n") - - self.inpfile.close() - return - - def __write_xml_header__(self,fileout): - Header = "\n" - self.inpfile.write(Header) - return - + def __init__(self, Meta, Surfaces, setting): + + self.Cells = Meta + + self.__getSurfaceTable__() + self.__simplifyPlanes__(Surfaces) + + self.Surfaces = self.__sortedSurfaces__(Surfaces) + self.Materials = set() + + def writeXML(self, filename): + print("write OpenMC xml file {}".format(filename)) + self.inpfile = open(filename, "w", encoding="utf-8") + self.__write_xml_header__(filename) + + self.inpfile.write("\n") + self.__write_xml_cell_block__() + self.inpfile.write(" \n") + self.__write_xml_surface_block__() + self.inpfile.write("\n") + + self.inpfile.close() + return + + def __write_xml_header__(self, fileout): + Header = "\n" + self.inpfile.write(Header) + return + def __write_xml_cell_block__(self): - for i,cell in enumerate(self.Cells): - if cell.MatInfo == 'Graveyard' : continue - self.__write_xml_cells__(cell) - return + for i, cell in enumerate(self.Cells): + if cell.MatInfo == "Graveyard": + continue + self.__write_xml_cells__(cell) + return def __write_xml_surface_block__(self): - for surf in self.Surfaces[:-1]: - self.__write_xml_surfaces__(surf) - self.__write_xml_surfaces__(self.Surfaces[-1],boundary=True) - - def __write_xml_cells__(self,cell): - """ Write the cell in xml OpenMC format """ - index = cell.label - cellName = ". ".join(cell.Comments.splitlines()) - if cell.__id__ is None : return - - if cell.Material == 0: - matName = 'void' - else: - matName = '{}'.format(cell.Material) - - OMCcell = ' \n'.format( \ - index,\ - matName,\ - cellName,\ - writeOpenMCregion(cell.Definition,'XML') ) - self.inpfile.write(OMCcell) - return - - - def __write_xml_surfaces__(self,surface,boundary=False): - """ Write the surfaces in xml OpenMC format """ - - surfType,coeffs = OpenMCSurface( surface.Type, surface.Surf) - - if not boundary: - OMCsurf = ' \n'.format(surface.Index, surfType, coeffs) - else: - OMCsurf = ' \n'.format(surface.Index, surfType, coeffs) - - self.inpfile.write(OMCsurf) - return - - def writePY(self,filename): - print ('write OpenMC python script {}'.format(filename)) - - # get all the materials present in the model - for cell in self.Cells: - if cell.Material != 0: - self.Materials.add(cell.Material) - - self.inpfile=open(filename,'w',encoding='utf-8') - self.__write_py_header__(filename) - - if len(self.Materials) > 0 : - self.inpfile.write("# Materials setup\n") - self.__write_py_materials__() - self.inpfile.write("\n") - - self.inpfile.write("# Surface setup\n") - self.__write_py_surface_block__() - self.inpfile.write("\n") - - self.inpfile.write('# Cell definition \n') - self.__write_py_cell_block__() - - self.inpfile.close() - return - - def __write_py_header__(self,fileout): - - Header = """\ + for surf in self.Surfaces[:-1]: + self.__write_xml_surfaces__(surf) + self.__write_xml_surfaces__(self.Surfaces[-1], boundary=True) + + def __write_xml_cells__(self, cell): + """Write the cell in xml OpenMC format""" + index = cell.label + cellName = ". ".join(cell.Comments.splitlines()) + if cell.__id__ is None: + return + + if cell.Material == 0: + matName = "void" + else: + matName = "{}".format(cell.Material) + + OMCcell = ' \n'.format( + index, matName, cellName, writeOpenMCregion(cell.Definition, "XML") + ) + self.inpfile.write(OMCcell) + return + + def __write_xml_surfaces__(self, surface, boundary=False): + """Write the surfaces in xml OpenMC format""" + + surfType, coeffs = OpenMCSurface(surface.Type, surface.Surf) + + if not boundary: + OMCsurf = ' \n'.format( + surface.Index, surfType, coeffs + ) + else: + OMCsurf = ' \n'.format( + surface.Index, surfType, coeffs + ) + + self.inpfile.write(OMCsurf) + return + + def writePY(self, filename): + print("write OpenMC python script {}".format(filename)) + + # get all the materials present in the model + for cell in self.Cells: + if cell.Material != 0: + self.Materials.add(cell.Material) + + self.inpfile = open(filename, "w", encoding="utf-8") + self.__write_py_header__(filename) + + if len(self.Materials) > 0: + self.inpfile.write("# Materials setup\n") + self.__write_py_materials__() + self.inpfile.write("\n") + + self.inpfile.write("# Surface setup\n") + self.__write_py_surface_block__() + self.inpfile.write("\n") + + self.inpfile.write("# Cell definition \n") + self.__write_py_cell_block__() + + self.inpfile.close() + return + + def __write_py_header__(self, fileout): + + Header = """\ # openMC geometry script generated by GEOUNED import openmc @@ -121,136 +124,150 @@ def __write_py_header__(self,fileout): ############################################################################### """ - self.inpfile.write(Header) - return + self.inpfile.write(Header) + return def __write_py_materials__(self): matList = tuple(sorted(self.Materials)) strMat = [] for m in matList: - material = "M{} = openmc.Material(name='M{}')\n".format(m,m) - self.inpfile.write(material) - strMat.append('M{}'.format(m)) + material = "M{} = openmc.Material(name='M{}')\n".format(m, m) + self.inpfile.write(material) + strMat.append("M{}".format(m)) - collect = 'materials = openmc.Materials([{}])\n'.format(', '.join(strMat)) + collect = "materials = openmc.Materials([{}])\n".format(", ".join(strMat)) self.inpfile.write(collect) - self.inpfile.write('materials.export_to_xml()\n') - + self.inpfile.write("materials.export_to_xml()\n") def __write_py_surface_block__(self): - for surf in self.Surfaces[:-1]: - self.__write_py_surfaces__(surf) - self.__write_py_surfaces__(self.Surfaces[-1],boundary=True) + for surf in self.Surfaces[:-1]: + self.__write_py_surfaces__(surf) + self.__write_py_surfaces__(self.Surfaces[-1], boundary=True) + def __write_py_surfaces__(self, surface, boundary=False): + """Write the surfaces in python OpenMC format""" - def __write_py_surfaces__(self,surface,boundary=False): - """ Write the surfaces in python OpenMC format """ + surfType, coeffs = OpenMCSurface( + surface.Type, surface.Surf, outXML=False, quadricForm=opt.quadricPY + ) - surfType,coeffs = OpenMCSurface(surface.Type, surface.Surf, outXML = False, quadricForm = opt.quadricPY) + if not boundary: + OMCsurf = "S{} = openmc.{}({})\n".format(surface.Index, surfType, coeffs) + else: + OMCsurf = 'S{} = openmc.{}({}, boundary_type="vacuum")\n'.format( + surface.Index, surfType, coeffs + ) - if not boundary: - OMCsurf = 'S{} = openmc.{}({})\n'.format(surface.Index, surfType, coeffs) - else: - OMCsurf = 'S{} = openmc.{}({}, boundary_type="vacuum")\n'.format(surface.Index, surfType, coeffs) - - self.inpfile.write(OMCsurf) - return + self.inpfile.write(OMCsurf) + return def __write_py_cell_block__(self): - cellNames = [] - for i,cell in enumerate(self.Cells): - if cell.MatInfo == 'Graveyard' : continue - self.__write_py_cells__(cell) - if cell.__id__ is None : continue - cellNames.append('C{}'.format(cell.label)) - - geometry = "\ngeometry = openmc.Geometry([{}])\ngeometry.export_to_xml()\n".format(', '.join(cellNames)) - - self.inpfile.write(geometry) - return - - - def __write_py_cells__(self,cell): - """ Write the cell in python OpenMC format """ - index = cell.label - cellName = ". ".join(cell.Comments.splitlines()) - if cell.__id__ is None : return - - if cell.Material == 0: - OMCcell = 'C{} = openmc.Cell(name="{}", region={})\n'.format(index, cellName, writeOpenMCregion(cell.Definition,'PY') ) - else: - matName = 'M{}'.format(cell.Material) - OMCcell = 'C{} = openmc.Cell(name="{}", fill={}, region={})\n'.format(index, cellName, matName, writeOpenMCregion(cell.Definition,'PY') ) - self.inpfile.write(OMCcell) - return + cellNames = [] + for i, cell in enumerate(self.Cells): + if cell.MatInfo == "Graveyard": + continue + self.__write_py_cells__(cell) + if cell.__id__ is None: + continue + cellNames.append("C{}".format(cell.label)) + + geometry = ( + "\ngeometry = openmc.Geometry([{}])\ngeometry.export_to_xml()\n".format( + ", ".join(cellNames) + ) + ) + + self.inpfile.write(geometry) + return + + def __write_py_cells__(self, cell): + """Write the cell in python OpenMC format""" + index = cell.label + cellName = ". ".join(cell.Comments.splitlines()) + if cell.__id__ is None: + return + if cell.Material == 0: + OMCcell = 'C{} = openmc.Cell(name="{}", region={})\n'.format( + index, cellName, writeOpenMCregion(cell.Definition, "PY") + ) + else: + matName = "M{}".format(cell.Material) + OMCcell = 'C{} = openmc.Cell(name="{}", fill={}, region={})\n'.format( + index, cellName, matName, writeOpenMCregion(cell.Definition, "PY") + ) + self.inpfile.write(OMCcell) + return def __getSurfaceTable__(self): - self.surfaceTable = {} - self.__solidCells__ = 0 - self.__cells__ = 0 - self.__materials__ = set() - - for i, CellObj in enumerate(self.Cells): - if CellObj.__id__ is None : continue - self.__cells__ += 1 - if CellObj.Material != 0 : - self.__materials__.add(CellObj.Material) - - surf = CellObj.Definition.getSurfacesNumbers() - if not CellObj.Void : self.__solidCells__ += 1 - for index in surf : - if index in self.surfaceTable.keys() : - self.surfaceTable[index].add(i) - else: - self.surfaceTable[index] = {i} - return - - - def __simplifyPlanes__(self,Surfaces): - offset = len(self.Cells) - keys= self.surfaceTable.keys() - - for p in Surfaces['PX']: - if p.Surf.Axis[0] < 0 : - p.Surf.Axis = FreeCAD.Vector(1,0,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PY']: - if p.Surf.Axis[1] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,1,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PZ']: - if p.Surf.Axis[2] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,0,1) - self.__changeSurfSign__(p) - return - - def __sortedSurfaces__(self,Surfaces): + self.surfaceTable = {} + self.__solidCells__ = 0 + self.__cells__ = 0 + self.__materials__ = set() + + for i, CellObj in enumerate(self.Cells): + if CellObj.__id__ is None: + continue + self.__cells__ += 1 + if CellObj.Material != 0: + self.__materials__.add(CellObj.Material) + + surf = CellObj.Definition.getSurfacesNumbers() + if not CellObj.Void: + self.__solidCells__ += 1 + for index in surf: + if index in self.surfaceTable.keys(): + self.surfaceTable[index].add(i) + else: + self.surfaceTable[index] = {i} + return + + def __simplifyPlanes__(self, Surfaces): + offset = len(self.Cells) + keys = self.surfaceTable.keys() + + for p in Surfaces["PX"]: + if p.Surf.Axis[0] < 0: + p.Surf.Axis = FreeCAD.Vector(1, 0, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PY"]: + if p.Surf.Axis[1] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 1, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PZ"]: + if p.Surf.Axis[2] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 0, 1) + self.__changeSurfSign__(p) + return + + def __sortedSurfaces__(self, Surfaces): temp = Surfaces_dict(Surfaces) surfList = [] - for ind in range(Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset): - s=temp.getSurface(ind+1) - if s is not None : - surfList.append(s) - temp.delSurface(ind+1) + for ind in range( + Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset + ): + s = temp.getSurface(ind + 1) + if s is not None: + surfList.append(s) + temp.delSurface(ind + 1) return surfList - - def __changeSurfSign__(self,p): - - if p.Index not in self.surfaceTable.keys() : - print('{} Surface {} not used in cell definition)'.format(p.Type,p.Index),p.Surf.Axis,p.Surf.Position) - return - - for ic in self.surfaceTable[p.Index] : - surf = self.Cells[ic].Definition.getSurfacesNumbers() - for s in surf : - if s == p.Index : - changeSurfSign(s, self.Cells[ic].Definition) + def __changeSurfSign__(self, p): + if p.Index not in self.surfaceTable.keys(): + print( + "{} Surface {} not used in cell definition)".format(p.Type, p.Index), + p.Surf.Axis, + p.Surf.Position, + ) + return - + for ic in self.surfaceTable[p.Index]: + surf = self.Cells[ic].Definition.getSurfacesNumbers() + for s in surf: + if s == p.Index: + changeSurfSign(s, self.Cells[ic].Definition) diff --git a/src/geouned/GEOUNED/Write/PHITSFormat.py b/src/geouned/GEOUNED/Write/PHITSFormat.py index 5740d9c4..8163a138 100644 --- a/src/geouned/GEOUNED/Write/PHITSFormat.py +++ b/src/geouned/GEOUNED/Write/PHITSFormat.py @@ -4,7 +4,7 @@ # Mainly based on the MCNPFormat.py # Some are modified for PHITS -# 1. Chosen the graveyard surface as the boundary of the outer void region (-1) +# 1. Chosen the graveyard surface as the boundary of the outer void region (-1) # 2. Unified the auto genarated void regions when envelope*_*_ and/or enclosure*_*_ are not setted # 3. Applied MATERIAL DEFINITION block when dummyMat = True # 4. Applied VOLUME DEFINITION block when volCARD = True @@ -20,44 +20,48 @@ from ..Utils.BasicFunctions_part1 import isOposite, pointsToCoeffs from ..Utils.Functions import Surfaces_dict from ..Utils.Options.Classes import Options as opt -from ..Write.Functions import (CellString, PHITSSurface, changeSurfSign, - writePHITSCellDef) +from ..Write.Functions import ( + CellString, + PHITSSurface, + changeSurfSign, + writePHITSCellDef, +) class PHITS_input: - def __init__(self,Meta,Surfaces,setting) : - self.Title = setting['title'] - self.VolSDEF = setting['volSDEF'] - self.VolCARD = setting['volCARD'] - self.U0CARD = setting['UCARD'] - self.DummyMat = setting['dummyMat'] - self.Matfile = setting['matFile'] - self.voidMat = setting['voidMat'] - self.startCell= setting['startCell'] - self.Cells = Meta - self.Options = {'Volume':self.VolCARD,'Universe':self.U0CARD} - - self.StepFile = setting['stepFile'] - if isinstance(self.StepFile,(tuple,list)): + def __init__(self, Meta, Surfaces, setting): + self.Title = setting["title"] + self.VolSDEF = setting["volSDEF"] + self.VolCARD = setting["volCARD"] + self.U0CARD = setting["UCARD"] + self.DummyMat = setting["dummyMat"] + self.Matfile = setting["matFile"] + self.voidMat = setting["voidMat"] + self.startCell = setting["startCell"] + self.Cells = Meta + self.Options = {"Volume": self.VolCARD, "Universe": self.U0CARD} + + self.StepFile = setting["stepFile"] + if isinstance(self.StepFile, (tuple, list)): self.StepFile = "; ".join(self.StepFile) - if self.Title == '' : - self.Title = self.StepFile - + if self.Title == "": + self.Title = self.StepFile + self.__getSurfaceTable__() self.__simplifyPlanes__(Surfaces) - - self.Surfaces = self.__sortedSurfaces__(Surfaces) - self.Materials= set() - - return - - def writePHITS(self,filename): - print ('write PHITS file {}'.format(filename)) - self.inpfile=open(filename,'w',encoding='utf-8') + + self.Surfaces = self.__sortedSurfaces__(Surfaces) + self.Materials = set() + + return + + def writePHITS(self, filename): + print("write PHITS file {}".format(filename)) + self.inpfile = open(filename, "w", encoding="utf-8") self.__write_PHITS_header__(filename) - cHeader="""\ + cHeader = """\ $ $ ########################################################## $ CELL DEFINITION @@ -67,9 +71,9 @@ def writePHITS(self,filename): self.inpfile.write(cHeader) self.__write_PHITS_cell_block__() - self.inpfile.write(' \n') - - surfaceHeader="""\ + self.inpfile.write(" \n") + + surfaceHeader = """\ $ $ ########################################################## $ SURFACE DEFINITION @@ -79,9 +83,9 @@ def writePHITS(self,filename): self.inpfile.write(surfaceHeader) self.__write_PHITS_surface_block__() - self.inpfile.write(' \n') + self.inpfile.write(" \n") - materialHeader="""\ + materialHeader = """\ $ $ ########################################################## $ MATERIAL DEFINITION @@ -94,9 +98,9 @@ def writePHITS(self,filename): if self.DummyMat: self.inpfile.write(materialHeader) self.__write_PHITS_source_block__() - self.inpfile.write(' \n') + self.inpfile.write(" \n") - volHeader="""\ + volHeader = """\ $ $ ########################################################## $ VOLUME DEFINITION @@ -107,32 +111,34 @@ def writePHITS(self,filename): $ [VOLUME] off\n""" - if self.Options['Volume']: + if self.Options["Volume"]: self.inpfile.write(volHeader) self.__write_PHITS__Volume_block__() - self.inpfile.write(' \n') + self.inpfile.write(" \n") self.inpfile.close() - return + return - def __write_PHITS_header__(self,fileout): + def __write_PHITS_header__(self, fileout): version = GEOUNED_Version releaseDate = GEOUNED_ReleaseDate - freeCAD_Version = '{V[0]:}.{V[1]:}.{V[2]:}'.format(V=FreeCAD.Version()) + freeCAD_Version = "{V[0]:}.{V[1]:}.{V[2]:}".format(V=FreeCAD.Version()) - Header ="$ " \ -"""{} + Header = ( + "$ " + """{} $ ______ _______ _____ _ _ __ _ _______ ______ $ | ____ |______ | | ___ | | | \ | |______ | \ $ |_____| |______ |_____| |_____| | \_| |______ |_____/ $ Version : {} {} $ FreeCAD Version : {} -$ PHITSFormat Version : 0.0.2.3 06/03/2024\n""".format(self.Title,version,releaseDate,freeCAD_Version) +$ PHITSFormat Version : 0.0.2.3 06/03/2024\n""".format( + self.Title, version, releaseDate, freeCAD_Version + ) + ) - - Information = \ -"""$ + Information = """$ $ ************************************************************* $ Original Step file : {} $ @@ -144,41 +150,47 @@ def __write_PHITS_header__(self,fileout): $ $ ************************************************************** -\n""".format(self.StepFile ,\ - datetime.now() ,\ - self.__solidCells__ ,\ - self.__cells__ ,\ - len(self.Surfaces), \ - len(self.__materials__) ) +\n""".format( + self.StepFile, + datetime.now(), + self.__solidCells__, + self.__cells__, + len(self.Surfaces), + len(self.__materials__), + ) self.inpfile.write(Header) self.inpfile.write(Information) return - + def __write_PHITS_cell_block__(self): enclenvChk = [] enclenvChk = self.__stepfile_label_chk__(self.StepFile) if enclenvChk: - print('Unified the inner void cell(s) definition') - for i,cell in enumerate(self.Cells): + print("Unified the inner void cell(s) definition") + for i, cell in enumerate(self.Cells): self.__write_PHITS_cells_uniVoidDef__(cell) return - else: - for i,cell in enumerate(self.Cells): + else: + for i, cell in enumerate(self.Cells): self.__write_PHITS_cells__(cell) return - def __stepfile_label_chk__(self,filename): - + def __stepfile_label_chk__(self, filename): + enclenvList = [] with open(filename) as f: enclenvList = f.readlines() - enclLabel = re.search('enclosure(?P[0-9]+)_(?P[0-9]+)_', str(enclenvList)) - envelLabel = re.search('envelope(?P[0-9]+)_(?P[0-9]+)_', str(enclenvList)) - cond1 = enclLabel==None - cond2 = envelLabel==None + enclLabel = re.search( + "enclosure(?P[0-9]+)_(?P[0-9]+)_", str(enclenvList) + ) + envelLabel = re.search( + "envelope(?P[0-9]+)_(?P[0-9]+)_", str(enclenvList) + ) + cond1 = enclLabel == None + cond2 = envelLabel == None return cond1 and cond2 def __write_PHITS_surface_block__(self): @@ -186,60 +198,72 @@ def __write_PHITS_surface_block__(self): for surf in self.Surfaces: self.__write_PHITS_surfaces__(surf) - def __write_PHITS_cells__(self,cell): + def __write_PHITS_cells__(self, cell): index = cell.label # if index is None objet not contain cell definition # but a comment to insert between cells - if cell.__id__ is None : + if cell.__id__ is None: comment = self.__commentLine__(cell.Comments) self.inpfile.write(comment) return - + if cell.Material == 0: - if cell.MatInfo == 'Graveyard': - cell.MatInfo = 'Outer void' - cellHeader = '{:<5d} {:<5d} '.format(index,-1) + if cell.MatInfo == "Graveyard": + cell.MatInfo = "Outer void" + cellHeader = "{:<5d} {:<5d} ".format(index, -1) - elif cell.MatInfo == 'Graveyard_in': - cell.MatInfo = 'Inner void' + elif cell.MatInfo == "Graveyard_in": + cell.MatInfo = "Inner void" if self.voidMat != []: self.Materials.add(self.voidMat[0]) - if abs(self.voidMat[1]) < 1e-2 : - cellHeader = '{:<5d} {:<5d} {:11.4e} '.format(index,self.voidMat[0],self.voidMat[1]) + if abs(self.voidMat[1]) < 1e-2: + cellHeader = "{:<5d} {:<5d} {:11.4e} ".format( + index, self.voidMat[0], self.voidMat[1] + ) else: - cellHeader = '{:<5d} {:<5d} {:11.7f} '.format(index,self.voidMat[0],self.voidMat[1]) + cellHeader = "{:<5d} {:<5d} {:11.7f} ".format( + index, self.voidMat[0], self.voidMat[1] + ) else: - cellHeader = '{:<5d} {:<5d} '.format(index,0) - + cellHeader = "{:<5d} {:<5d} ".format(index, 0) + else: - cellHeader = '{:<5d} {:<5d} '.format(index,0) + cellHeader = "{:<5d} {:<5d} ".format(index, 0) else: self.Materials.add(cell.Material) - if self.Matfile=='' and cell.EnclosureID!=0: - cellHeader = '{:<5d} {:<5d} c{:<5d} '.format(index,cell.Material,cell.Material) + if self.Matfile == "" and cell.EnclosureID != 0: + cellHeader = "{:<5d} {:<5d} c{:<5d} ".format( + index, cell.Material, cell.Material + ) else: - if abs(cell.Density) < 1e-2 : - cellHeader = '{:<5d} {:<5d} {:11.4e} '.format(index,cell.Material,cell.Density) + if abs(cell.Density) < 1e-2: + cellHeader = "{:<5d} {:<5d} {:11.4e} ".format( + index, cell.Material, cell.Density + ) else: - cellHeader = '{:<5d} {:<5d} {:11.7f} '.format(index,cell.Material,cell.Density) - - phitscell = '{}{}\n{}{}'.format( cellHeader ,\ - self.__cellFormat__(cell.Definition,offset=len(cellHeader)) ,\ - self.__optionFormat__(cell) ,\ - self.__commentFormat__(cell.Comments,cell.MatInfo)) + cellHeader = "{:<5d} {:<5d} {:11.7f} ".format( + index, cell.Material, cell.Density + ) + + phitscell = "{}{}\n{}{}".format( + cellHeader, + self.__cellFormat__(cell.Definition, offset=len(cellHeader)), + self.__optionFormat__(cell), + self.__commentFormat__(cell.Comments, cell.MatInfo), + ) self.inpfile.write(phitscell) return - def __write_PHITS_cells_uniVoidDef__(self,cell): + def __write_PHITS_cells_uniVoidDef__(self, cell): index = cell.label # if index is None objet not contain cell definition # but a comment to insert between cells - if cell.__id__ is None : + if cell.__id__ is None: comment = self.__commentLine__(cell.Comments) self.inpfile.write(comment) return @@ -253,54 +277,64 @@ def __write_PHITS_cells_uniVoidDef__(self,cell): # is appended to the new inner void cell definition # after self.__cellFormat__(cell.Definition) process. """ - + if cell.Void: - if cell.MatInfo == 'Graveyard_in': - cell.MatInfo = 'Inner void' + if cell.MatInfo == "Graveyard_in": + cell.MatInfo = "Inner void" newInnerVoidCell = cell.Definition.elements[:1] - cell.Definition.operator = 'AND' - cell.Definition.elements = newInnerVoidCell + cell.Definition.operator = "AND" + cell.Definition.elements = newInnerVoidCell - inclSolidCells = '' - startVoidIndex = self.__solidCells__+self.startCell - eliminated_endVoidIndex = self.__cells__+self.startCell-3 + inclSolidCells = "" + startVoidIndex = self.__solidCells__ + self.startCell + eliminated_endVoidIndex = self.__cells__ + self.startCell - 3 - if self.startCell == startVoidIndex-1: - inclSolidCells = '{:1s}#{}'.format('',self.startCell) + if self.startCell == startVoidIndex - 1: + inclSolidCells = "{:1s}#{}".format("", self.startCell) else: - for i in range(self.startCell,startVoidIndex): - inclSolidCells += '{:1s}#{}'.format('',i) + for i in range(self.startCell, startVoidIndex): + inclSolidCells += "{:1s}#{}".format("", i) if startVoidIndex == eliminated_endVoidIndex: - one_mervoid_str = 'VOID CELL {} merged, so the auto-genarated void definition is eliminated\n' + one_mervoid_str = "VOID CELL {} merged, so the auto-genarated void definition is eliminated\n" cell.Comments = one_mervoid_str.format(startVoidIndex) else: - some_mervoid_str = 'VOID CELLs {}-{} merged, so the auto-genarated void definitions are eliminated\n' - cell.Comments = some_mervoid_str.format(startVoidIndex,eliminated_endVoidIndex) + some_mervoid_str = "VOID CELLs {}-{} merged, so the auto-genarated void definitions are eliminated\n" + cell.Comments = some_mervoid_str.format( + startVoidIndex, eliminated_endVoidIndex + ) if self.voidMat != []: self.Materials.add(self.voidMat[0]) - if abs(self.voidMat[1]) < 1e-2 : - cellHeader = '{:<5d} {:<5d} {:11.4e} '.format(index,self.voidMat[0],self.voidMat[1]) + if abs(self.voidMat[1]) < 1e-2: + cellHeader = "{:<5d} {:<5d} {:11.4e} ".format( + index, self.voidMat[0], self.voidMat[1] + ) else: - cellHeader = '{:<5d} {:<5d} {:11.7f} '.format(index,self.voidMat[0],self.voidMat[1]) + cellHeader = "{:<5d} {:<5d} {:11.7f} ".format( + index, self.voidMat[0], self.voidMat[1] + ) else: - cellHeader = '{:<5d} {:<5d} '.format(index,0) - - phitscell = '{}{}\n{}{}\n'.format( cellHeader ,\ - self.__new_InnerVoid_Def__(inclSolidCells,cell.Definition,offset=len(cellHeader)) ,\ - self.__optionFormat__(cell) ,\ - self.__commentFormat__(cell.Comments,cell.MatInfo)) + cellHeader = "{:<5d} {:<5d} ".format(index, 0) + + phitscell = "{}{}\n{}{}\n".format( + cellHeader, + self.__new_InnerVoid_Def__( + inclSolidCells, cell.Definition, offset=len(cellHeader) + ), + self.__optionFormat__(cell), + self.__commentFormat__(cell.Comments, cell.MatInfo), + ) self.inpfile.write(phitscell) return - elif cell.MatInfo == 'Graveyard': - cellHeader = '{:<5d} {:<5d} '.format(index,-1) - cell.MatInfo = 'Outer void' - - else: - return - + elif cell.MatInfo == "Graveyard": + cellHeader = "{:<5d} {:<5d} ".format(index, -1) + cell.MatInfo = "Outer void" + + else: + return + """ # To check auto-generated voids, apply this commented out section instead # and comment out above from "if cell.Void:..." to "... else: return" @@ -312,89 +346,118 @@ def __write_PHITS_cells_uniVoidDef__(self,cell): cellHeader = '{:<5d} {:<5d} '.format(index,-1) else: cellHeader = '{:<5d} {:<5d} '.format(index,0) - """ - + """ + else: self.Materials.add(cell.Material) - if self.Matfile=='' and cell.EnclosureID!=0: - cellHeader = '{:<5d} {:<5d} c{:<5d} '.format(index,cell.Material,cell.Material) + if self.Matfile == "" and cell.EnclosureID != 0: + cellHeader = "{:<5d} {:<5d} c{:<5d} ".format( + index, cell.Material, cell.Material + ) else: - if abs(cell.Density) < 1e-2 : - cellHeader = '{:<5d} {:<5d} {:11.4e} '.format(index,cell.Material,cell.Density) + if abs(cell.Density) < 1e-2: + cellHeader = "{:<5d} {:<5d} {:11.4e} ".format( + index, cell.Material, cell.Density + ) else: - cellHeader = '{:<5d} {:<5d} {:11.7f} '.format(index,cell.Material,cell.Density) - - phitscell = '{}{}\n{}{}'.format( cellHeader ,\ - self.__cellFormat__(cell.Definition,offset=len(cellHeader)) ,\ - self.__optionFormat__(cell) ,\ - self.__commentFormat__(cell.Comments,cell.MatInfo)) + cellHeader = "{:<5d} {:<5d} {:11.7f} ".format( + index, cell.Material, cell.Density + ) + + phitscell = "{}{}\n{}{}".format( + cellHeader, + self.__cellFormat__(cell.Definition, offset=len(cellHeader)), + self.__optionFormat__(cell), + self.__commentFormat__(cell.Comments, cell.MatInfo), + ) self.inpfile.write(phitscell) return - def __write_PHITS_surfaces__(self,surface): - """ Write the surfaces in PHITS format """ + def __write_PHITS_surfaces__(self, surface): + """Write the surfaces in PHITS format""" PHITS_def = PHITSSurface(surface.Index, surface.Type, surface.Surf) - if PHITS_def : - PHITS_def += '\n' - self.inpfile.write(PHITS_def) + if PHITS_def: + PHITS_def += "\n" + self.inpfile.write(PHITS_def) else: - print('Surface {} cannot be written in PHITS input'.format(surface.Type)) - return - + print("Surface {} cannot be written in PHITS input".format(surface.Type)) + return + def __write_PHITS_source_block__(self): - - if self.DummyMat : + + if self.DummyMat: mat = list(self.Materials) mat.sort() MATID = [] - MATCARD = '' - for i,cell in enumerate(self.Cells): + MATCARD = "" + for i, cell in enumerate(self.Cells): if (cell.Material in mat) and (cell.Material not in MATID): MATID.append(cell.Material) - if self.Matfile=='' and cell.EnclosureID!=0: - mismat_comment = '$ Change dummyMat M{}, {} c{} g/cm3 is assigned\n M{:<6d} H 2 O 1\n' - MATCARD += mismat_comment.format(cell.Material,cell.MatInfo,cell.Material,cell.Material) + if self.Matfile == "" and cell.EnclosureID != 0: + mismat_comment = "$ Change dummyMat M{}, {} c{} g/cm3 is assigned\n M{:<6d} H 2 O 1\n" + MATCARD += mismat_comment.format( + cell.Material, cell.MatInfo, cell.Material, cell.Material + ) else: - mat_comment = '$ Change dummyMat M{} to {}, Density = {}g/cm3\n M{:<6d} H 2 O 1\n' - MATCARD += mat_comment.format(cell.Material,cell.MatInfo,-1*cell.Density,cell.Material) - Block = MATCARD+'\n' - + mat_comment = "$ Change dummyMat M{} to {}, Density = {}g/cm3\n M{:<6d} H 2 O 1\n" + MATCARD += mat_comment.format( + cell.Material, + cell.MatInfo, + -1 * cell.Density, + cell.Material, + ) + Block = MATCARD + "\n" + self.inpfile.write(Block) def __write_PHITS__Volume_block__(self): - vol = '{:5s}reg{:5s}vol\n'.format('','') + vol = "{:5s}reg{:5s}vol\n".format("", "") - startVoidIndex = self.__solidCells__+self.startCell - eliminated_endVoidIndex = self.__cells__+self.startCell-3 + startVoidIndex = self.__solidCells__ + self.startCell + eliminated_endVoidIndex = self.__cells__ + self.startCell - 3 enclenvChk = [] enclenvChk = self.__stepfile_label_chk__(self.StepFile) - if enclenvChk and self.Options['Volume']: - for i,cell in enumerate(self.Cells): - if cell.__id__ is not None : - if cell.Void and startVoidIndex==eliminated_endVoidIndex: - if cell.label == startVoidIndex: - print('Eliminated the merged void cell {} from [VOLUME] section'.format(cell.label)) + if enclenvChk and self.Options["Volume"]: + for i, cell in enumerate(self.Cells): + if cell.__id__ is not None: + if cell.Void and startVoidIndex == eliminated_endVoidIndex: + if cell.label == startVoidIndex: + print( + "Eliminated the merged void cell {} from [VOLUME] section".format( + cell.label + ) + ) + else: + vol += "{:6s}{}{:6s}1.0\n".format("", cell.label, "") + elif cell.Void: + if cell.label in range( + startVoidIndex, eliminated_endVoidIndex + 1 + ): + print( + "Eliminated the merged void cell {} from [VOLUME] section".format( + cell.label + ) + ) else: - vol +='{:6s}{}{:6s}1.0\n'.format('',cell.label,'') - elif cell.Void: - if cell.label in range(startVoidIndex,eliminated_endVoidIndex+1): - print('Eliminated the merged void cell {} from [VOLUME] section'.format(cell.label)) - else: - vol +='{:6s}{}{:6s}1.0\n'.format('',cell.label,'') + vol += "{:6s}{}{:6s}1.0\n".format("", cell.label, "") else: - vol +='{:6s}{}{:6s}{:6e}\n'.format('',cell.label,'',cell.Volume*1e-3) + vol += "{:6s}{}{:6s}{:6e}\n".format( + "", cell.label, "", cell.Volume * 1e-3 + ) else: - if self.Options['Volume']: - for i,cell in enumerate(self.Cells): - if cell.__id__ is not None : - if cell.Void : - vol +='{:6s}{}{:6s}1.0\n'.format('',cell.label,'') + if self.Options["Volume"]: + for i, cell in enumerate(self.Cells): + if cell.__id__ is not None: + if cell.Void: + vol += "{:6s}{}{:6s}1.0\n".format("", cell.label, "") else: - vol +='{:6s}{}{:6s}{:6e}\n'.format('',cell.label,'',cell.Volume*1e-3) + vol += "{:6s}{}{:6s}{:6e}\n".format( + "", cell.label, "", cell.Volume * 1e-3 + ) self.inpfile.write(vol) @@ -413,134 +476,141 @@ def __write_PHITS__Volume_block__(self): self.inpfile.write(vol) """ - def __cellFormat__(self,Definition,offset=11): - return writePHITSCellDef(Definition,tabspace=11,offset=offset) - - def __new_InnerVoid_Def__(self,innerSolidCells,Definition,offset=11): - newInnerVoidDef = self.__cellFormat__(Definition,offset) - strdef = CellString(tabspace=11) - strdef.add(newInnerVoidDef+innerSolidCells) - strdef.wrapLine(offset) - return strdef.str - - def __optionFormat__(self,cell): - - option = '' - if self.Options['Volume']: - if not cell.Void : - option ='${:11s}Vol={:e} cm3\n'.format('',cell.Volume*1e-3) + def __cellFormat__(self, Definition, offset=11): + return writePHITSCellDef(Definition, tabspace=11, offset=offset) + + def __new_InnerVoid_Def__(self, innerSolidCells, Definition, offset=11): + newInnerVoidDef = self.__cellFormat__(Definition, offset) + strdef = CellString(tabspace=11) + strdef.add(newInnerVoidDef + innerSolidCells) + strdef.wrapLine(offset) + return strdef.str + + def __optionFormat__(self, cell): + + option = "" + if self.Options["Volume"]: + if not cell.Void: + option = "${:11s}Vol={:e} cm3\n".format("", cell.Volume * 1e-3) else: - option ='${:11s}Vol=1.0 cm3\n'.format('') + option = "${:11s}Vol=1.0 cm3\n".format("") - if self.Options['Universe'] is not None: - option += '{:11s}U={}\n'.format('',self.Options['Universe']) + if self.Options["Universe"] is not None: + option += "{:11s}U={}\n".format("", self.Options["Universe"]) return option - def __commentFormat__(self,cComment,mComment=None): - - comment = '' - if mComment : - mComment = mComment.split('\n') - for c in mComment : - if c : comment += '{:11s}${}\n'.format('',c) - - if cComment.strip() != '': - cComment = cComment.strip().split('\n') + def __commentFormat__(self, cComment, mComment=None): + + comment = "" + if mComment: + mComment = mComment.split("\n") + for c in mComment: + if c: + comment += "{:11s}${}\n".format("", c) + + if cComment.strip() != "": + cComment = cComment.strip().split("\n") for c in cComment: - if c: comment += '{:11s}${}\n'.format('',c) - return comment - - def __commentLine__(self,lineComment): - lineComment = lineComment.strip().split('\n') - comment = '' - if lineComment : - comment = '$ \n' + if c: + comment += "{:11s}${}\n".format("", c) + return comment + + def __commentLine__(self, lineComment): + lineComment = lineComment.strip().split("\n") + comment = "" + if lineComment: + comment = "$ \n" for c in lineComment: - if c: comment += '$ {}\n'.format(c) - comment += '$ \n' - return comment + if c: + comment += "$ {}\n".format(c) + comment += "$ \n" + return comment def __getSurfaceTable__(self): self.surfaceTable = {} self.__solidCells__ = 0 - self.__cells__ = 0 + self.__cells__ = 0 self.__materials__ = set() - + for i, CellObj in enumerate(self.Cells): - if CellObj.__id__ is None : continue + if CellObj.__id__ is None: + continue self.__cells__ += 1 - if CellObj.Material != 0 : + if CellObj.Material != 0: self.__materials__.add(CellObj.Material) surf = CellObj.Definition.getSurfacesNumbers() - if not CellObj.Void : self.__solidCells__ += 1 - for index in surf : - if index in self.surfaceTable.keys() : + if not CellObj.Void: + self.__solidCells__ += 1 + for index in surf: + if index in self.surfaceTable.keys(): self.surfaceTable[index].add(i) else: self.surfaceTable[index] = {i} return - - def __simplifyPlanes__(self,Surfaces): + + def __simplifyPlanes__(self, Surfaces): offset = len(self.Cells) - keys= self.surfaceTable.keys() + keys = self.surfaceTable.keys() - for p in Surfaces['PX']: - if p.Surf.Axis[0] < 0 : - p.Surf.Axis = FreeCAD.Vector(1,0,0) + for p in Surfaces["PX"]: + if p.Surf.Axis[0] < 0: + p.Surf.Axis = FreeCAD.Vector(1, 0, 0) self.__changeSurfSign__(p) - - for p in Surfaces['PY']: - if p.Surf.Axis[1] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,1,0) + + for p in Surfaces["PY"]: + if p.Surf.Axis[1] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 1, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PZ"]: + if p.Surf.Axis[2] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 0, 1) self.__changeSurfSign__(p) - - for p in Surfaces['PZ']: - if p.Surf.Axis[2] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,0,1) - self.__changeSurfSign__(p) - - if opt.prnt3PPlane : - for p in Surfaces['P']: + + if opt.prnt3PPlane: + for p in Surfaces["P"]: if p.Surf.pointDef: - axis,d = pointsToCoeffs(p.Surf.Points) - if isOposite(axis,p.Surf.Axis) : - self.__changeSurfSign__(p) + axis, d = pointsToCoeffs(p.Surf.Points) + if isOposite(axis, p.Surf.Axis): + self.__changeSurfSign__(p) return - - def __sortedSurfaces__(self,Surfaces): + + def __sortedSurfaces__(self, Surfaces): temp = Surfaces_dict(Surfaces) surfList = [] - for ind in range(Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset): - s=temp.getSurface(ind+1) - if s is not None : + for ind in range( + Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset + ): + s = temp.getSurface(ind + 1) + if s is not None: surfList.append(s) - temp.delSurface(ind+1) + temp.delSurface(ind + 1) return surfList - - def __changeSurfSign__(self,p): - if p.Index not in self.surfaceTable.keys() : - print('{} Surface {} not used in cell definition)'.format(p.Type,p.Index),p.Surf.Axis,p.Surf.Position) + def __changeSurfSign__(self, p): + + if p.Index not in self.surfaceTable.keys(): + print( + "{} Surface {} not used in cell definition)".format(p.Type, p.Index), + p.Surf.Axis, + p.Surf.Position, + ) return - - for ic in self.surfaceTable[p.Index] : + + for ic in self.surfaceTable[p.Index]: surf = self.Cells[ic].Definition.getSurfacesNumbers() - for s in surf : - if s == p.Index : + for s in surf: + if s == p.Index: changeSurfSign(s, self.Cells[ic].Definition) - def __get_solidCellVolume__(self): solidList = [] volumeList = [] - for m in self.Cells : - if m.CellType == 'solid' and m.__id__ is not None: + for m in self.Cells: + if m.CellType == "solid" and m.__id__ is not None: solidList.append(m.label) - volumeList.append(m.Volume*1e-3) - return solidList, volumeList - - - + volumeList.append(m.Volume * 1e-3) + return solidList, volumeList diff --git a/src/geouned/GEOUNED/Write/SerpentFormat.py b/src/geouned/GEOUNED/Write/SerpentFormat.py index d215c7f1..5af58fc4 100644 --- a/src/geouned/GEOUNED/Write/SerpentFormat.py +++ b/src/geouned/GEOUNED/Write/SerpentFormat.py @@ -13,37 +13,41 @@ class Serpent_input: - def __init__(self,Meta,Surfaces,setting) : - self.Title = setting['title'] - self.VolSDEF = setting['volSDEF'] - self.VolCARD = setting['volCARD'] - self.U0CARD = setting['UCARD'] - self.dummyMat = setting['dummyMat'] - self.Cells = Meta - self.Options = {'Volume':self.VolCARD,'Particle':('n','p'),'Universe':self.U0CARD} - self.part = 'p' - - self.StepFile = setting['stepFile'] - if isinstance(self.StepFile,(tuple,list)): - self.StepFile = "; ".join(self.StepFile) - - if self.Title == '' : - self.Title = self.StepFile - - self.__getSurfaceTable__() - self.__simplifyPlanes__(Surfaces) - - self.Surfaces = self.__sortedSurfaces__(Surfaces) - self.Materials = set() - - return + def __init__(self, Meta, Surfaces, setting): + self.Title = setting["title"] + self.VolSDEF = setting["volSDEF"] + self.VolCARD = setting["volCARD"] + self.U0CARD = setting["UCARD"] + self.dummyMat = setting["dummyMat"] + self.Cells = Meta + self.Options = { + "Volume": self.VolCARD, + "Particle": ("n", "p"), + "Universe": self.U0CARD, + } + self.part = "p" + + self.StepFile = setting["stepFile"] + if isinstance(self.StepFile, (tuple, list)): + self.StepFile = "; ".join(self.StepFile) + + if self.Title == "": + self.Title = self.StepFile + + self.__getSurfaceTable__() + self.__simplifyPlanes__(Surfaces) + + self.Surfaces = self.__sortedSurfaces__(Surfaces) + self.Materials = set() + + return # def setSRC(self,data): - + # if data[0] is not None: # sdef = f'src point {self.part}\n' # self.src_sphere = (sdef) - # else: + # else: # self.src_sphere = None # xmin,xmax,ymin,ymax,zmin,zmax = data[1] @@ -56,46 +60,45 @@ def __init__(self,Meta,Surfaces,setting) : # SP3 = 'SP3 0 1 \n' # self.SDEF_box = (sdef,SI1,SI2,SI3,SP1,SP2,SP3) - def writeInput(self,filename): - print (f'write Serpent file {filename}') - self.inpfile=open(filename,'w',encoding='utf-8') - self.__write_header__(filename) - cellblockHeader="""\ + def writeInput(self, filename): + print(f"write Serpent file {filename}") + self.inpfile = open(filename, "w", encoding="utf-8") + self.__write_header__(filename) + cellblockHeader = """\ % --- CELL DEFINITIONS """ - self.inpfile.write(cellblockHeader) - self.__write_cell_block__() - self.inpfile.write(' \n') - - surfaceHeader="""\ + self.inpfile.write(cellblockHeader) + self.__write_cell_block__() + self.inpfile.write(" \n") + + surfaceHeader = """\ % --- SURFACE DEFINITIONS """ - self.inpfile.write(surfaceHeader) - self.__write_surface_block__() - self.inpfile.write(' \n') - - self.__write_source_block__() - - self.inpfile.close() - return - - def __write_header__(self,fileout): - - version = GEOUNED_Version - releaseDate = GEOUNED_ReleaseDate - freeCAD_Version = '{V[0]:}.{V[1]:}.{V[2]:}'.format(V=FreeCAD.Version()) - - Header = \ -"""{} + self.inpfile.write(surfaceHeader) + self.__write_surface_block__() + self.inpfile.write(" \n") + + self.__write_source_block__() + + self.inpfile.close() + return + + def __write_header__(self, fileout): + + version = GEOUNED_Version + releaseDate = GEOUNED_ReleaseDate + freeCAD_Version = "{V[0]:}.{V[1]:}.{V[2]:}".format(V=FreeCAD.Version()) + + Header = """{} % ______ _______ _____ _ _ __ _ _______ ______ % | ____ |______ | | ___ | | | \ | |______ | \ % |_____| |______ |_____| |_____| | \_| |______ |_____/ % Version : {} {} -% FreeCAD Version : {} \n""".format(self.Title,version,releaseDate,freeCAD_Version) +% FreeCAD Version : {} \n""".format( + self.Title, version, releaseDate, freeCAD_Version + ) - - Information = \ -"""% + Information = """% % ************************************************************* % Original Step file : {} % @@ -105,29 +108,30 @@ def __write_header__(self,fileout): % Surfaces : {} % Materials : {} % -% **************************************************************\n""".format(self.StepFile ,\ - datetime.now() ,\ - self.__solidCells__ ,\ - self.__cells__ ,\ - len(self.Surfaces), \ - len(self.__materials__) ) - self.inpfile.write(Header) - self.inpfile.write(Information) - return - +% **************************************************************\n""".format( + self.StepFile, + datetime.now(), + self.__solidCells__, + self.__cells__, + len(self.Surfaces), + len(self.__materials__), + ) + self.inpfile.write(Header) + self.inpfile.write(Information) + return + def __write_surface_block__(self): - for surf in self.Surfaces: - self.__write_surfaces__(surf) - + for surf in self.Surfaces: + self.__write_surfaces__(surf) def __write_cell_block__(self): - for i,cell in enumerate(self.Cells): - self.__write_cells__(cell) - return + for i, cell in enumerate(self.Cells): + self.__write_cells__(cell) + return -# to_mod + # to_mod def __write_cells__(self, cell): index = cell.label @@ -137,109 +141,116 @@ def __write_cells__(self, cell): comment = self.comment_line(cell.Comments) self.inpfile.write(comment) return - - if self.Options['Universe'] is not None: + + if self.Options["Universe"] is not None: if cell.Material == 0: - cellHeader = f'cell {index:<5d} {self.Options["Universe"]} {"void":<5d} ' + cellHeader = ( + f'cell {index:<5d} {self.Options["Universe"]} {"void":<5d} ' + ) else: self.Materials.add(cell.Material) - cellHeader = f'cell {index:<5d} {self.Options["Universe"]} {cell.Material:<5d} ' - - serpent_cell = f'{cellHeader}{self.__cellFormat__(cell.Definition, offset=len(cellHeader))}' \ - f'{self.comment_format(cell.Comments, cell.MatInfo)}' + cellHeader = ( + f'cell {index:<5d} {self.Options["Universe"]} {cell.Material:<5d} ' + ) + + serpent_cell = ( + f"{cellHeader}{self.__cellFormat__(cell.Definition, offset=len(cellHeader))}" + f"{self.comment_format(cell.Comments, cell.MatInfo)}" + ) self.inpfile.write(serpent_cell) else: - if cell.Material == 0 and cell.MatInfo != 'Graveyard' : - cellHeader = f'cell {index:<5d} 0 void ' - elif cell.Material == 0 and cell.MatInfo == 'Graveyard' : - cellHeader = f'cell {index:<5d} 0 outside ' + if cell.Material == 0 and cell.MatInfo != "Graveyard": + cellHeader = f"cell {index:<5d} 0 void " + elif cell.Material == 0 and cell.MatInfo == "Graveyard": + cellHeader = f"cell {index:<5d} 0 outside " else: self.Materials.add(cell.Material) - cellHeader = f'cell {index:<5d} 0 {cell.Material:<5d} ' + cellHeader = f"cell {index:<5d} 0 {cell.Material:<5d} " - serpent_cell = f'{cellHeader}{self.__cellFormat__(cell.Definition, offset=len(cellHeader))}' \ - f'{self.comment_format(cell.Comments, cell.MatInfo)}' - self.inpfile.write(serpent_cell) - - return + serpent_cell = ( + f"{cellHeader}{self.__cellFormat__(cell.Definition, offset=len(cellHeader))}" + f"{self.comment_format(cell.Comments, cell.MatInfo)}" + ) + self.inpfile.write(serpent_cell) + return - def __write_surfaces__(self,surface): - """ Write the surfaces in Serpent format """ + def __write_surfaces__(self, surface): + """Write the surfaces in Serpent format""" - Serpent_def = SerpentSurface(surface.Index, surface.Type, surface.Surf) - if Serpent_def : - Serpent_def += '\n' - self.inpfile.write(Serpent_def) - else: - print('Surface {} cannot be written in Serpent input'.format(surface.Type)) - return + Serpent_def = SerpentSurface(surface.Index, surface.Type, surface.Surf) + if Serpent_def: + Serpent_def += "\n" + self.inpfile.write(Serpent_def) + else: + print("Surface {} cannot be written in Serpent input".format(surface.Type)) + return -# No void all option in Serpent. For now remove addition of source. + # No void all option in Serpent. For now remove addition of source. def __write_source_block__(self): - -# if self.SDEF_sphere is None: return - MODE = f'\nset nps 1e6\nset bc 1' - if self.dummyMat : - mat = list(self.Materials) - mat.sort() - MATCARD = '' - for m in mat: - MATCARD += 'mat {:<6d} {:11.4e} \n1001 1 \n'.format(m, self.cell.Density) - Block = MATCARD+'% \n'+MODE - else: - Block = MODE - - # Not included for Serpent - # if self.VolSDEF: - # Block += 'PRDMP 2J -1\n' - # for line in self.SDEF_box : - # Block += 'C ' + line - # for line in self.SDEF_sphere: - # Block += line - - # celList,volList = self.__get_solidCellVolume__() - - # F4Tally = CardLine('F4:{} '.format(self.part)) - # F4Tally.extend(celList) - # SD4 = CardLine('SD4 ',fmt='13.7e') - # SD4.extend(volList) - - # Block += F4Tally.str+'\n' - # if not self.VolCARD : - # Block += SD4.str - # else : - # Block += 'C Cell volume normalization is set in cell cards VOL\n' - # else : - # for line in self.SDEF_sphere : - # Block += 'C ' + line - # for line in self.SDEF_box : - # Block += line - - - self.inpfile.write(Block) - - - def __cellFormat__(self,Definition,offset=11): - return writeSerpentCellDef(Definition,tabspace=11,offset=offset) - -# Function not relevant for Serpent : No importance setting, universes assigned elsewhere. -# Volumes only defined on tally cards. - #def __optionFormat__(self,cell): - + + # if self.SDEF_sphere is None: return + MODE = f"\nset nps 1e6\nset bc 1" + if self.dummyMat: + mat = list(self.Materials) + mat.sort() + MATCARD = "" + for m in mat: + MATCARD += "mat {:<6d} {:11.4e} \n1001 1 \n".format( + m, self.cell.Density + ) + Block = MATCARD + "% \n" + MODE + else: + Block = MODE + + # Not included for Serpent + # if self.VolSDEF: + # Block += 'PRDMP 2J -1\n' + # for line in self.SDEF_box : + # Block += 'C ' + line + # for line in self.SDEF_sphere: + # Block += line + + # celList,volList = self.__get_solidCellVolume__() + + # F4Tally = CardLine('F4:{} '.format(self.part)) + # F4Tally.extend(celList) + # SD4 = CardLine('SD4 ',fmt='13.7e') + # SD4.extend(volList) + + # Block += F4Tally.str+'\n' + # if not self.VolCARD : + # Block += SD4.str + # else : + # Block += 'C Cell volume normalization is set in cell cards VOL\n' + # else : + # for line in self.SDEF_sphere : + # Block += 'C ' + line + # for line in self.SDEF_box : + # Block += line + + self.inpfile.write(Block) + + def __cellFormat__(self, Definition, offset=11): + return writeSerpentCellDef(Definition, tabspace=11, offset=offset) + + # Function not relevant for Serpent : No importance setting, universes assigned elsewhere. + # Volumes only defined on tally cards. + # def __optionFormat__(self,cell): + # option = '' # if self.Options['Volume']: - # if not cell.Void : + # if not cell.Void : # option ='{:11s}Vol={:e}\n'.format('',cell.Volume*1e-3) # else: # option = '{:11s}Vol=1.0\n'.format('') - # option += '{:11s}'.format('') + # option += '{:11s}'.format('') # for p in self.Options['Particle']: # if cell.MatInfo == 'Graveyard' : # option += 'imp:{}=0 '.format(p) - # else: + # else: # option += 'imp:{}=1.0 '.format(p) # if self.Options['Universe'] is not None: @@ -249,115 +260,117 @@ def __cellFormat__(self,Definition,offset=11): # return option def comment_format(self, cComment, mComment=None): - comment = '' + comment = "" if mComment: - mComment = mComment.split('\n') + mComment = mComment.split("\n") for c in mComment: if c: - comment += '{:11s}%{}\n'.format('', c) + comment += "{:11s}%{}\n".format("", c) - if cComment.strip() != '': - cComment = cComment.strip().split('\n') + if cComment.strip() != "": + cComment = cComment.strip().split("\n") for c in cComment: if c: - comment += '{:11s}%{}\n'.format('', c) + comment += "{:11s}%{}\n".format("", c) return comment def comment_line(self, lineComment): - lineComment = lineComment.strip().split('\n') - comment = '' + lineComment = lineComment.strip().split("\n") + comment = "" if lineComment: - comment = '% \n' + comment = "% \n" for c in lineComment: if c: - comment += '% {}\n'.format(c) - comment += '% \n' + comment += "% {}\n".format(c) + comment += "% \n" return comment - def __getSurfaceTable__(self): - self.surfaceTable = {} - self.__solidCells__ = 0 - self.__cells__ = 0 - self.__materials__ = set() - - for i, CellObj in enumerate(self.Cells): - if CellObj.__id__ is None : continue - self.__cells__ += 1 - if CellObj.Material != 0 : - self.__materials__.add(CellObj.Material) - - surf = CellObj.Definition.getSurfacesNumbers() - if not CellObj.Void : self.__solidCells__ += 1 - for index in surf : - if index in self.surfaceTable.keys() : - self.surfaceTable[index].add(i) - else: - self.surfaceTable[index] = {i} - return - - - def __simplifyPlanes__(self,Surfaces): - offset = len(self.Cells) - keys= self.surfaceTable.keys() - - for p in Surfaces['PX']: - if p.Surf.Axis[0] < 0 : - p.Surf.Axis = FreeCAD.Vector(1,0,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PY']: - if p.Surf.Axis[1] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,1,0) - self.__changeSurfSign__(p) - - for p in Surfaces['PZ']: - if p.Surf.Axis[2] < 0 : - p.Surf.Axis = FreeCAD.Vector(0,0,1) - self.__changeSurfSign__(p) - - if opt.prnt3PPlane : - for p in Surfaces['P']: - if p.Surf.pointDef: - axis,d = pointsToCoeffs(p.Surf.Points) - if isOposite(axis,p.Surf.Axis) : - self.__changeSurfSign__(p) - - return - - def __sortedSurfaces__(self,Surfaces): + self.surfaceTable = {} + self.__solidCells__ = 0 + self.__cells__ = 0 + self.__materials__ = set() + + for i, CellObj in enumerate(self.Cells): + if CellObj.__id__ is None: + continue + self.__cells__ += 1 + if CellObj.Material != 0: + self.__materials__.add(CellObj.Material) + + surf = CellObj.Definition.getSurfacesNumbers() + if not CellObj.Void: + self.__solidCells__ += 1 + for index in surf: + if index in self.surfaceTable.keys(): + self.surfaceTable[index].add(i) + else: + self.surfaceTable[index] = {i} + return + + def __simplifyPlanes__(self, Surfaces): + offset = len(self.Cells) + keys = self.surfaceTable.keys() + + for p in Surfaces["PX"]: + if p.Surf.Axis[0] < 0: + p.Surf.Axis = FreeCAD.Vector(1, 0, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PY"]: + if p.Surf.Axis[1] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 1, 0) + self.__changeSurfSign__(p) + + for p in Surfaces["PZ"]: + if p.Surf.Axis[2] < 0: + p.Surf.Axis = FreeCAD.Vector(0, 0, 1) + self.__changeSurfSign__(p) + + if opt.prnt3PPlane: + for p in Surfaces["P"]: + if p.Surf.pointDef: + axis, d = pointsToCoeffs(p.Surf.Points) + if isOposite(axis, p.Surf.Axis): + self.__changeSurfSign__(p) + + return + + def __sortedSurfaces__(self, Surfaces): temp = Surfaces_dict(Surfaces) surfList = [] - for ind in range(Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset): - s=temp.getSurface(ind+1) - if s is not None : - surfList.append(s) - temp.delSurface(ind+1) + for ind in range( + Surfaces.IndexOffset, Surfaces.surfaceNumber + Surfaces.IndexOffset + ): + s = temp.getSurface(ind + 1) + if s is not None: + surfList.append(s) + temp.delSurface(ind + 1) return surfList - - def __changeSurfSign__(self,p): - if p.Index not in self.surfaceTable.keys() : - print('{} Surface {} not used in cell definition)'.format(p.Type,p.Index),p.Surf.Axis,p.Surf.Position) + def __changeSurfSign__(self, p): + + if p.Index not in self.surfaceTable.keys(): + print( + "{} Surface {} not used in cell definition)".format(p.Type, p.Index), + p.Surf.Axis, + p.Surf.Position, + ) return - - for ic in self.surfaceTable[p.Index] : - surf = self.Cells[ic].Definition.getSurfacesNumbers() - for s in surf : - if s == p.Index : - changeSurfSign(s, self.Cells[ic].Definition) + for ic in self.surfaceTable[p.Index]: + surf = self.Cells[ic].Definition.getSurfacesNumbers() + for s in surf: + if s == p.Index: + changeSurfSign(s, self.Cells[ic].Definition) def __get_solidCellVolume__(self): solidList = [] volumeList = [] - for m in self.Cells : - if m.CellType == 'solid' and m.__id__ is not None: - solidList.append(m.label) - volumeList.append(m.Volume*1e-3) - - return solidList, volumeList - - - + for m in self.Cells: + if m.CellType == "solid" and m.__id__ is not None: + solidList.append(m.label) + volumeList.append(m.Volume * 1e-3) + + return solidList, volumeList diff --git a/src/geouned/GEOUNED/Write/StringFunctions.py b/src/geouned/GEOUNED/Write/StringFunctions.py index a1bc1ea3..f8cf2970 100644 --- a/src/geouned/GEOUNED/Write/StringFunctions.py +++ b/src/geouned/GEOUNED/Write/StringFunctions.py @@ -6,135 +6,174 @@ # used in card_split -celmat=re.compile(r"(?P^ *\d+) +(?P(\d+|like))",re.I) # identify first two entries on cell card (cell name, material) -grlnumber=re.compile(r"[-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?",re.I) # identify a general number form signed integer, float or exponential -param=re.compile(r"((^|\n {5})[\(\):\-\+\d+\.\# ]*)([\*a-z])",re.I) # identity begining of the paramter part of the cell card -likebut=re.compile(r"but",re.I) # identify likebut card -trans=re.compile(r"trcl|fill= *\d+[ c\$\n]*\(,",re.I) # identify tranformed card +celmat = re.compile( + r"(?P^ *\d+) +(?P(\d+|like))", re.I +) # identify first two entries on cell card (cell name, material) +grlnumber = re.compile( + r"[-+]?(\d+\.\d+|\.\d+|\d+\.?)(e[+-]\d+)?", re.I +) # identify a general number form signed integer, float or exponential +param = re.compile( + r"((^|\n {5})[\(\):\-\+\d+\.\# ]*)([\*a-z])", re.I +) # identity begining of the paramter part of the cell card +likebut = re.compile(r"but", re.I) # identify likebut card +trans = re.compile(r"trcl|fill= *\d+[ c\$\n]*\(,", re.I) # identify tranformed card # user in get_stat function -reword=re.compile(r"(\d+|\(|\)|:|\#)") # word identification in cell line -compcell=re.compile(r"\#\d") # identify hashcell complement operator +reword = re.compile(r"(\d+|\(|\)|:|\#)") # word identification in cell line +compcell = re.compile(r"\#\d") # identify hashcell complement operator # used in Complementary operator function -number=re.compile(r"(?P[-+]?\d+)") # signed (+-) (or not) numbers +number = re.compile(r"(?P[-+]?\d+)") # signed (+-) (or not) numbers # leftp=re.compile(r"^ *(?P[-\d\(\#])",re.M) # identify first valid character -leftp=re.compile(r"(?P[-+\d\(\#])",re.I) # identify first valid character -rightp=re.compile(r"(?P[ c\$\n]*$)",re.I) # identify last valid character -#interblk=re.compile(r"(?P\d)(?P(( +| *(\$)?\n(C\n)* *)[-+]?\d))") # two numbers separated by blank (or newline or comments) -#intercls=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)[-+]?\d))") # closed parenthesis followed by number -#interopn=re.compile(r"(?P\d)(?P(( *| *(\$)?\n(C\n)* *)\())") # number followed by opened parenthesis -#intercop=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)\())") # closed parenthesis followed by opened parenthesis -interblk=re.compile(r"(?P\d)(?P(( +| *((\n *)?\$|\nC)*\n *)[-+]?\d))") # two numbers separated by blank (or newline or comments) -intercls=re.compile(r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)[-+]?\d))") # closed parenthesis followed by number -interopn=re.compile(r"(?P\d)(?P(( *| *((\n *)?\$|\nC)*\n *)\())") # number followed by opened parenthesis -intercop=re.compile(r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)\())") # closed parenthesis followed by opened parenthesis -colonamp=re.compile(r"[:&]") # colon or ampersand +leftp = re.compile(r"(?P[-+\d\(\#])", re.I) # identify first valid character +rightp = re.compile(r"(?P[ c\$\n]*$)", re.I) # identify last valid character +# interblk=re.compile(r"(?P\d)(?P(( +| *(\$)?\n(C\n)* *)[-+]?\d))") # two numbers separated by blank (or newline or comments) +# intercls=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)[-+]?\d))") # closed parenthesis followed by number +# interopn=re.compile(r"(?P\d)(?P(( *| *(\$)?\n(C\n)* *)\())") # number followed by opened parenthesis +# intercop=re.compile(r"(?P\))(?P(( *| *(\$)?\n(C\n)* *)\())") # closed parenthesis followed by opened parenthesis +interblk = re.compile( + r"(?P\d)(?P(( +| *((\n *)?\$|\nC)*\n *)[-+]?\d))" +) # two numbers separated by blank (or newline or comments) +intercls = re.compile( + r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)[-+]?\d))" +) # closed parenthesis followed by number +interopn = re.compile( + r"(?P\d)(?P(( *| *((\n *)?\$|\nC)*\n *)\())" +) # number followed by opened parenthesis +intercop = re.compile( + r"(?P\))(?P(( *| *((\n *)?\$|\nC)*\n *)\())" +) # closed parenthesis followed by opened parenthesis +colonamp = re.compile(r"[:&]") # colon or ampersand # used for remove redundant parenthesis function -mostinner=re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses -bracketsemi=re.compile(r"[\]\[;]") # square bracket or semicolon -blnkline=re.compile(r"^ *\n",re.M) # identify blank line -contline=re.compile(r"\n {0,4}(?P[^c^ ])",re.I) # identify character other than 'C' in fisrt 5 columns -comdollar=re.compile(r"\n(?P *)\$") # identify dollar on 'blank line' -startgeom=re.compile(r"(?P^ *)(?P[\-\+\d])") # identify beginning of the geomtric part -endgeom=re.compile(r"(?P\d)(?P *((\n *)?\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part -#endgeom=re.compile(r"(?P\d)(?P *(\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part +mostinner = re.compile(r"\([^\(^\)]*\)") # identify most inner parentheses +bracketsemi = re.compile(r"[\]\[;]") # square bracket or semicolon +blnkline = re.compile(r"^ *\n", re.M) # identify blank line +contline = re.compile( + r"\n {0,4}(?P[^c^ ])", re.I +) # identify character other than 'C' in fisrt 5 columns +comdollar = re.compile(r"\n(?P *)\$") # identify dollar on 'blank line' +startgeom = re.compile( + r"(?P^ *)(?P[\-\+\d])" +) # identify beginning of the geomtric part +endgeom = re.compile( + r"(?P\d)(?P *((\n *)?\$|\nc)?(\n *)?$)", re.I +) # identify end of the geomtric part +# endgeom=re.compile(r"(?P\d)(?P *(\$|\nc)?(\n *)?$)",re.I) # identify end of the geomtric part # other -rehash=re.compile(r"# *(\d+|\()") # find beginning of complementary operator (both cell and surf) -parent=re.compile(r"[\(|\)]") # position of open and close parenthesis (get_hashcell) -gline=re.compile(r"(^ ?[\(\):\-\+\d+\.\# ]+|\n {5}[\(\):\-\+\d+\.\# ]+)",re.I) # valid geometric part of the line (remove/restore_comments) -comments=re.compile(r"((\n *)?\$|\n *c)",re.I) # begining of comment part (remove/restore_comments) -#comments=re.compile(r"\$|\n *c",re.I) # begining of comment part (remove/restore_comments) -lastCR = re.compile(r"\n *$") #last newline "\n" on line string - - +rehash = re.compile( + r"# *(\d+|\()" +) # find beginning of complementary operator (both cell and surf) +parent = re.compile(r"[\(|\)]") # position of open and close parenthesis (get_hashcell) +gline = re.compile( + r"(^ ?[\(\):\-\+\d+\.\# ]+|\n {5}[\(\):\-\+\d+\.\# ]+)", re.I +) # valid geometric part of the line (remove/restore_comments) +comments = re.compile( + r"((\n *)?\$|\n *c)", re.I +) # begining of comment part (remove/restore_comments) +# comments=re.compile(r"\$|\n *c",re.I) # begining of comment part (remove/restore_comments) +lastCR = re.compile(r"\n *$") # last newline "\n" on line string + + # restore curve parentheses and colon characters def reverse_repl(m): - symb=m.group(0) - if symb == '[' : - return '(' - elif symb == ']' : - return ')' - else : - return ':' + symb = m.group(0) + if symb == "[": + return "(" + elif symb == "]": + return ")" + else: + return ":" + def countP(string): - lp=string.count('(') - rp=string.count(')') - return (lp,rp) - -def redundant(m,geom): - """ check if the inner parentheses are redundant """ - term = m.group() - - # Find first valid character at the left of the parenthese - leftOK= True - left = m.start()-1 - while left > -1: - if geom[left] in ('\n','C','$',' '): - left -= 1 - else: - if geom[left] not in ('(',':') : leftOK = False - break - - # check if no ':' (or) are inside the parenthese - # if not, parentheses are redundants - if (term.find(':') == -1) : return True - - # Find first valid character at the right of the parenthese - rightOK= True - right = m.end() - while right < len(geom) : - if geom[right] in ('\n','C','$',' '): - right += 1 - else: - if geom[right] not in (')',':') : rightOK = False - break - - # if parentheses are like: - # {( or : } ( ....... ) {) or :} - # parentheses are redundants - - if leftOK and rightOK : - return True - else: - return False - + lp = string.count("(") + rp = string.count(")") + return (lp, rp) + + +def redundant(m, geom): + """check if the inner parentheses are redundant""" + term = m.group() + + # Find first valid character at the left of the parenthese + leftOK = True + left = m.start() - 1 + while left > -1: + if geom[left] in ("\n", "C", "$", " "): + left -= 1 + else: + if geom[left] not in ("(", ":"): + leftOK = False + break + + # check if no ':' (or) are inside the parenthese + # if not, parentheses are redundants + if term.find(":") == -1: + return True + + # Find first valid character at the right of the parenthese + rightOK = True + right = m.end() + while right < len(geom): + if geom[right] in ("\n", "C", "$", " "): + right += 1 + else: + if geom[right] not in (")", ":"): + rightOK = False + break + + # if parentheses are like: + # {( or : } ( ....... ) {) or :} + # parentheses are redundants + + if leftOK and rightOK: + return True + else: + return False + + def remove_redundant(geom): - """ return cell without redundant parenthesis """ - - porg=countP(geom) - # Loop until no redundant parentheses are found - cont = True - while cont: - # Loop over most inner parentheses - pos = 0 - cont = False - while True : - m = mostinner.search(geom,pos) - if not m : break - cont = True - if redundant(m,geom): - # remove redundant parentheses - geom = geom[:m.start()]+ ' ' + geom[m.start()+1:m.end()-1]+ ' ' + geom[m.end():] - else: - # replace no redundant parentheses by [] and : by ; - term = geom[m.start()+1:m.end()-1].replace(':',';') - geom = geom[:m.start()] + '[' + term + ']' + geom[m.end():] - pos = m.end() - - # restore curved parenthesis and colon - geom=re.sub(bracketsemi,reverse_repl,geom) - - # remove possible blank line - geom=re.sub(blnkline,'',geom) - - # ensure 5 blanks continous line - geom=re.sub(contline, r'\n \g',geom) - - # remove last newline at the end of the line string - geom=re.sub(lastCR,'',geom) - - return geom + """return cell without redundant parenthesis""" + + porg = countP(geom) + # Loop until no redundant parentheses are found + cont = True + while cont: + # Loop over most inner parentheses + pos = 0 + cont = False + while True: + m = mostinner.search(geom, pos) + if not m: + break + cont = True + if redundant(m, geom): + # remove redundant parentheses + geom = ( + geom[: m.start()] + + " " + + geom[m.start() + 1 : m.end() - 1] + + " " + + geom[m.end() :] + ) + else: + # replace no redundant parentheses by [] and : by ; + term = geom[m.start() + 1 : m.end() - 1].replace(":", ";") + geom = geom[: m.start()] + "[" + term + "]" + geom[m.end() :] + pos = m.end() + + # restore curved parenthesis and colon + geom = re.sub(bracketsemi, reverse_repl, geom) + + # remove possible blank line + geom = re.sub(blnkline, "", geom) + + # ensure 5 blanks continous line + geom = re.sub(contline, r"\n \g", geom) + + # remove last newline at the end of the line string + geom = re.sub(lastCR, "", geom) + + return geom diff --git a/src/geouned/GEOUNED/Write/WriteFiles.py b/src/geouned/GEOUNED/Write/WriteFiles.py index 9746065d..d7b7c3db 100644 --- a/src/geouned/GEOUNED/Write/WriteFiles.py +++ b/src/geouned/GEOUNED/Write/WriteFiles.py @@ -5,62 +5,86 @@ from .SerpentFormat import Serpent_input -def writeGeometry(UniverseBox,MetaList,Surfaces,code_setting): +def writeGeometry(UniverseBox, MetaList, Surfaces, code_setting): - baseName = code_setting['geometryName'] + baseName = code_setting["geometryName"] - # write cells comments in file - if code_setting['cellCommentFile']: - OutFiles.commentsWrite(baseName,MetaList) - if code_setting['cellSummaryFile']: - OutFiles.summaryWrite(baseName,MetaList) + # write cells comments in file + if code_setting["cellCommentFile"]: + OutFiles.commentsWrite(baseName, MetaList) + if code_setting["cellSummaryFile"]: + OutFiles.summaryWrite(baseName, MetaList) - - if 'mcnp' in code_setting['outFormat']: - mcnpFilename = baseName + '.mcnp' - outBox = (UniverseBox.XMin,UniverseBox.XMax,UniverseBox.YMin,UniverseBox.YMax,UniverseBox.ZMin,UniverseBox.ZMax) - if code_setting['voidGen'] : - outSphere = (Surfaces['Sph'][-1].Index,Surfaces['Sph'][-1].Surf.Radius) - else: - outSphere = None + if "mcnp" in code_setting["outFormat"]: + mcnpFilename = baseName + ".mcnp" + outBox = ( + UniverseBox.XMin, + UniverseBox.XMax, + UniverseBox.YMin, + UniverseBox.YMax, + UniverseBox.ZMin, + UniverseBox.ZMax, + ) + if code_setting["voidGen"]: + outSphere = (Surfaces["Sph"][-1].Index, Surfaces["Sph"][-1].Surf.Radius) + else: + outSphere = None - MCNPfile = MCNP_input(MetaList,Surfaces,code_setting) - MCNPfile.setSDEF((outSphere,outBox)) - MCNPfile.writeInput(mcnpFilename) + MCNPfile = MCNP_input(MetaList, Surfaces, code_setting) + MCNPfile.setSDEF((outSphere, outBox)) + MCNPfile.writeInput(mcnpFilename) - if 'openMC_XML' in code_setting['outFormat'] or \ - 'openMC_PY' in code_setting['outFormat'] : - OMCFile = OpenMC_input(MetaList,Surfaces,code_setting) + if ( + "openMC_XML" in code_setting["outFormat"] + or "openMC_PY" in code_setting["outFormat"] + ): + OMCFile = OpenMC_input(MetaList, Surfaces, code_setting) - if 'openMC_XML' in code_setting['outFormat']: - omcFilename = baseName + '.xml' - OMCFile.writeXML(omcFilename) - + if "openMC_XML" in code_setting["outFormat"]: + omcFilename = baseName + ".xml" + OMCFile.writeXML(omcFilename) - if 'openMC_PY' in code_setting['outFormat']: - omcFilename = baseName + '.py' - OMCFile.writePY(omcFilename) + if "openMC_PY" in code_setting["outFormat"]: + omcFilename = baseName + ".py" + OMCFile.writePY(omcFilename) - if 'serpent' in code_setting['outFormat']: - serpentFilename = baseName + '.serp' - outBox = (UniverseBox.XMin,UniverseBox.XMax,UniverseBox.YMin,UniverseBox.YMax,UniverseBox.ZMin,UniverseBox.ZMax) - if code_setting['voidGen'] : - outSphere = (Surfaces['Sph'][-1].Index,Surfaces['Sph'][-1].Surf.Radius) - else: - outSphere = None + if "serpent" in code_setting["outFormat"]: + serpentFilename = baseName + ".serp" + outBox = ( + UniverseBox.XMin, + UniverseBox.XMax, + UniverseBox.YMin, + UniverseBox.YMax, + UniverseBox.ZMin, + UniverseBox.ZMax, + ) + if code_setting["voidGen"]: + outSphere = (Surfaces["Sph"][-1].Index, Surfaces["Sph"][-1].Surf.Radius) + else: + outSphere = None - Serpentfile = Serpent_input(MetaList,Surfaces,code_setting) - # Serpentfile.setSDEF((outSphere,outBox)) - Serpentfile.writeInput(serpentFilename) + Serpentfile = Serpent_input(MetaList, Surfaces, code_setting) + # Serpentfile.setSDEF((outSphere,outBox)) + Serpentfile.writeInput(serpentFilename) - if 'phits' in code_setting['outFormat']: - phitsFilename = baseName + '.inp' - PHITS_outBox = (UniverseBox.XMin,UniverseBox.XMax,UniverseBox.YMin,UniverseBox.YMax,UniverseBox.ZMin,UniverseBox.ZMax) - if code_setting['voidGen'] : - PHITS_outSphere = (Surfaces['Sph'][-1].Index,Surfaces['Sph'][-1].Surf.Radius) - else: - PHITS_outSphere = None + if "phits" in code_setting["outFormat"]: + phitsFilename = baseName + ".inp" + PHITS_outBox = ( + UniverseBox.XMin, + UniverseBox.XMax, + UniverseBox.YMin, + UniverseBox.YMax, + UniverseBox.ZMin, + UniverseBox.ZMax, + ) + if code_setting["voidGen"]: + PHITS_outSphere = ( + Surfaces["Sph"][-1].Index, + Surfaces["Sph"][-1].Surf.Radius, + ) + else: + PHITS_outSphere = None - PHITSfile = PHITS_input(MetaList,Surfaces,code_setting) - # PHITSfile.setSDEF_PHITS((PHITS_outSphere,PHITS_outBox)) - PHITSfile.writePHITS(phitsFilename) + PHITSfile = PHITS_input(MetaList, Surfaces, code_setting) + # PHITSfile.setSDEF_PHITS((PHITS_outSphere,PHITS_outBox)) + PHITSfile.writePHITS(phitsFilename) diff --git a/src/geouned/GEOUNED/__init__.py b/src/geouned/GEOUNED/__init__.py index 572ffeca..3cd34449 100644 --- a/src/geouned/GEOUNED/__init__.py +++ b/src/geouned/GEOUNED/__init__.py @@ -1,4 +1,4 @@ -#Init file of GEOUNED module +# Init file of GEOUNED module # # We load the STEP and the materials @@ -31,595 +31,729 @@ from .Write.WriteFiles import writeGeometry -class GEOUNED() : - - def __init__(self,title='Geouned conversion'): - """ """ - self.__dict__ = dict() - self.__dict__['stepFile'] = '' - self.__dict__['geometryName'] = '' - self.__dict__['matFile'] = '' - self.__dict__['outFormat'] = ('mcnp',) - self.__dict__['title'] = title - self.__dict__['voidGen'] = True - self.__dict__['debug'] = False - self.__dict__['compSolids'] = True - self.__dict__['volSDEF'] = False - self.__dict__['dummyMat'] = False - self.__dict__['volCARD'] = True - self.__dict__['UCARD'] = None - self.__dict__['simplify'] = 'No' - self.__dict__['cellRange'] = [] - self.__dict__['exportSolids'] = '' - self.__dict__['minVoidSize'] = 200 # units mm - self.__dict__['maxSurf'] = 50 - self.__dict__['maxBracket'] = 30 - self.__dict__['voidMat'] = [] - self.__dict__['voidExclude'] = [] - self.__dict__['startCell'] = 1 - self.__dict__['startSurf'] = 1 - self.__dict__['cellCommentFile'] = False - self.__dict__['cellSummaryFile'] = True - self.__dict__['sortEnclosure'] = False - - def SetOptions(self): - toleranceKwrd = ( 'relativeTolerance', 'relativePrecision', 'singleValue', 'generalDistance', 'generalAngle', - 'planeDistance', 'planeAngle', 'cylinderDistance', 'cylinderAngle', 'sphereDistance', 'coneDistance', - 'coneAngle', 'torusDistance', 'torusAngle','minArea') - numericKwrd = ('P_abc', 'P_d', 'P_xyz', 'S_r', 'S_xyz', 'C_r', 'C_xyz', 'K_tan2', 'K_xyz', 'T_r', 'T_xyz', 'GQ_1to6', 'GQ_7to9', 'GQ_10' ) - tolKwrdEquiv = {'relativeTolerance':'relativeTol' , 'relativePrecision':'relativePrecision', 'singleValue':'value', 'generalDistance':'distance', - 'generalAngle': 'angle', 'planeDistance':'pln_distance', 'planeAngle':'pln_angle', 'cylinderDistance':'cyl_distance', - 'cylinderAngle':'cyl_angle', 'sphereDistance':'sph_distance', 'coneDistance':'kne_distance', 'coneAngle': 'kne_angle', - 'torusDistance':'tor_distance', 'torusAngle':'tor_angle','minArea':'min_area'} - - config = configparser.ConfigParser() - config.optionxform = str - config.read(self.__dict__['title']) - for section in config.sections(): - if section == 'Files': - for key in config['Files'].keys() : - if key in ('geometryName','matFile','title') : - self.set(key, config.get('Files',key)) - - elif key == 'stepFile': - value = config.get('Files',key).strip() - lst = value.split() - if value[0] in ('(','[') and value[-1] in (']',')') : - data=value[1:-1].split(',') - data = [ x.strip() for x in data ] - self.set(key,data) - elif len(lst) > 1: - self.set(key,lst) - else : - self.set(key, value) - - elif key == 'outFormat': - raw = config.get('Files',key).strip() - values = tuple( x.strip() for x in raw.split(',') ) - outFormat = [] - for v in values: - if v.lower() == 'mcnp' : outFormat.append('mcnp') - elif v.lower() == 'openmc_xml' : outFormat.append('openMC_XML') - elif v.lower() == 'openmc_py' : outFormat.append('openMC_PY') - elif v.lower() == 'serpent' : outFormat.append('serpent') - elif v.lower() == 'phits' : outFormat.append('phits') - self.set(key, tuple(outFormat)) - - - elif section == 'Parameters': - for key in config['Parameters'].keys() : - if key in ('voidGen','debug','compSolids','volSDEF','volCARD', - 'dummyMat','cellSummaryFile','cellCommentFile','sortEnclosure') : - self.set(key, config.getboolean('Parameters',key)) - elif key in ('minVoidSize','maxSurf','maxBracket','startCell','startSurf') : - self.set(key, config.getint('Parameters',key)) - elif key in ('exportSolids','UCARD','simplify') : - self.set(key, config.get('Parameters',key)) - elif key == 'voidMat': - value = config.get('Parameters',key).strip() - data=value[1:-1].split(',') - self.set(key,(int(data[0]),float(data[1]),data[2])) - else: - value = config.get('Parameters',key).strip() - data=value[1:-1].split(',') - self.set(key,tuple(map(int,data))) - - elif section == 'Options': - for key in config['Options'].keys() : - if key in ('forceCylinder','newSplitPlane','delLastNumber','verbose','scaleUP',\ - 'quadricPY','Facets','prnt3PPlane','forceNoOverlap') : - setattr(Options,key, config.getboolean('Options',key)) - elif key in ('enlargeBox','nPlaneReverse','splitTolerance'): - setattr(Options,key, config.getfloat('Options',key)) - - elif section == 'Tolerances': - for key in config['Tolerances'].keys() : - if key == 'relativeTolerance' : - setattr(Tolerances,key, config.getboolean('Tolerances',key)) - elif key in toleranceKwrd : setattr(Tolerances,tolKwrdEquiv[key], config.getfloat('Tolerances',key)) - - elif section == 'MCNP_Numeric_Format': - PdEntry = False - for key in config['MCNP_Numeric_Format'].keys() : - if key in numericKwrd : setattr(MCNP_numeric_format,key, config.get('MCNP_Numeric_Format',key)) - if key == 'P_d': PdEntry = True - - - else: - print('bad section name : {}'.format(section)) - - if self.__dict__['geometryName'] == '' : - self.__dict__['geometryName'] = self.__dict__['stepFile'][:-4] - - if Options.prnt3PPlane and not PdEntry : - MCNP_numeric_format.P_d = '22.15e' - - print(self.__dict__) - - def set(self,kwrd,value): - - if kwrd not in self.__dict__.keys(): - print('Bad entry : {}'.format(kwrd)) - return - - if kwrd == 'stepFile' : - if isinstance(value,(list,tuple)) : - for v in value : - if not isinstance(v,str) : - print('elemt in {} list should be string'.format(kwrd)) - return - elif not isinstance(value,str) : - print('{} should be string or tuple of strings'.format(kwrd)) - return +class GEOUNED: + + def __init__(self, title="Geouned conversion"): + """ """ + self.__dict__ = dict() + self.__dict__["stepFile"] = "" + self.__dict__["geometryName"] = "" + self.__dict__["matFile"] = "" + self.__dict__["outFormat"] = ("mcnp",) + self.__dict__["title"] = title + self.__dict__["voidGen"] = True + self.__dict__["debug"] = False + self.__dict__["compSolids"] = True + self.__dict__["volSDEF"] = False + self.__dict__["dummyMat"] = False + self.__dict__["volCARD"] = True + self.__dict__["UCARD"] = None + self.__dict__["simplify"] = "No" + self.__dict__["cellRange"] = [] + self.__dict__["exportSolids"] = "" + self.__dict__["minVoidSize"] = 200 # units mm + self.__dict__["maxSurf"] = 50 + self.__dict__["maxBracket"] = 30 + self.__dict__["voidMat"] = [] + self.__dict__["voidExclude"] = [] + self.__dict__["startCell"] = 1 + self.__dict__["startSurf"] = 1 + self.__dict__["cellCommentFile"] = False + self.__dict__["cellSummaryFile"] = True + self.__dict__["sortEnclosure"] = False + + def SetOptions(self): + toleranceKwrd = ( + "relativeTolerance", + "relativePrecision", + "singleValue", + "generalDistance", + "generalAngle", + "planeDistance", + "planeAngle", + "cylinderDistance", + "cylinderAngle", + "sphereDistance", + "coneDistance", + "coneAngle", + "torusDistance", + "torusAngle", + "minArea", + ) + numericKwrd = ( + "P_abc", + "P_d", + "P_xyz", + "S_r", + "S_xyz", + "C_r", + "C_xyz", + "K_tan2", + "K_xyz", + "T_r", + "T_xyz", + "GQ_1to6", + "GQ_7to9", + "GQ_10", + ) + tolKwrdEquiv = { + "relativeTolerance": "relativeTol", + "relativePrecision": "relativePrecision", + "singleValue": "value", + "generalDistance": "distance", + "generalAngle": "angle", + "planeDistance": "pln_distance", + "planeAngle": "pln_angle", + "cylinderDistance": "cyl_distance", + "cylinderAngle": "cyl_angle", + "sphereDistance": "sph_distance", + "coneDistance": "kne_distance", + "coneAngle": "kne_angle", + "torusDistance": "tor_distance", + "torusAngle": "tor_angle", + "minArea": "min_area", + } + + config = configparser.ConfigParser() + config.optionxform = str + config.read(self.__dict__["title"]) + for section in config.sections(): + if section == "Files": + for key in config["Files"].keys(): + if key in ("geometryName", "matFile", "title"): + self.set(key, config.get("Files", key)) + + elif key == "stepFile": + value = config.get("Files", key).strip() + lst = value.split() + if value[0] in ("(", "[") and value[-1] in ("]", ")"): + data = value[1:-1].split(",") + data = [x.strip() for x in data] + self.set(key, data) + elif len(lst) > 1: + self.set(key, lst) + else: + self.set(key, value) + + elif key == "outFormat": + raw = config.get("Files", key).strip() + values = tuple(x.strip() for x in raw.split(",")) + outFormat = [] + for v in values: + if v.lower() == "mcnp": + outFormat.append("mcnp") + elif v.lower() == "openmc_xml": + outFormat.append("openMC_XML") + elif v.lower() == "openmc_py": + outFormat.append("openMC_PY") + elif v.lower() == "serpent": + outFormat.append("serpent") + elif v.lower() == "phits": + outFormat.append("phits") + self.set(key, tuple(outFormat)) + + elif section == "Parameters": + for key in config["Parameters"].keys(): + if key in ( + "voidGen", + "debug", + "compSolids", + "volSDEF", + "volCARD", + "dummyMat", + "cellSummaryFile", + "cellCommentFile", + "sortEnclosure", + ): + self.set(key, config.getboolean("Parameters", key)) + elif key in ( + "minVoidSize", + "maxSurf", + "maxBracket", + "startCell", + "startSurf", + ): + self.set(key, config.getint("Parameters", key)) + elif key in ("exportSolids", "UCARD", "simplify"): + self.set(key, config.get("Parameters", key)) + elif key == "voidMat": + value = config.get("Parameters", key).strip() + data = value[1:-1].split(",") + self.set(key, (int(data[0]), float(data[1]), data[2])) + else: + value = config.get("Parameters", key).strip() + data = value[1:-1].split(",") + self.set(key, tuple(map(int, data))) + + elif section == "Options": + for key in config["Options"].keys(): + if key in ( + "forceCylinder", + "newSplitPlane", + "delLastNumber", + "verbose", + "scaleUP", + "quadricPY", + "Facets", + "prnt3PPlane", + "forceNoOverlap", + ): + setattr(Options, key, config.getboolean("Options", key)) + elif key in ("enlargeBox", "nPlaneReverse", "splitTolerance"): + setattr(Options, key, config.getfloat("Options", key)) + + elif section == "Tolerances": + for key in config["Tolerances"].keys(): + if key == "relativeTolerance": + setattr(Tolerances, key, config.getboolean("Tolerances", key)) + elif key in toleranceKwrd: + setattr( + Tolerances, + tolKwrdEquiv[key], + config.getfloat("Tolerances", key), + ) + + elif section == "MCNP_Numeric_Format": + PdEntry = False + for key in config["MCNP_Numeric_Format"].keys(): + if key in numericKwrd: + setattr( + MCNP_numeric_format, + key, + config.get("MCNP_Numeric_Format", key), + ) + if key == "P_d": + PdEntry = True - elif kwrd == 'UCARD' : - if value == 'None' : - value = None - elif value.isdigit() : - value = int(value) - else: - print('{} value should be None or integer'.format(kwrd)) - return - elif kwrd == 'outFormat' : - if len(value) == 0: return - elif kwrd in ('geometryName','matFile','exportSolids'): - if not isinstance(value,str) : - print('{} value should be str instance'.format(kwrd)) - return - elif kwrd in ('cellRange','voidMat','voidExclude'): - if not isinstance(value,(list,tuple)) : - print('{} value should be list or tuple'.format(kwrd)) - return - elif kwrd in ('minVoidSize','maxSurf','maxBracket','startCell','startSurf'): - if not isinstance(value,int) : - print('{} value should be integer'.format(kwrd)) - return - elif kwrd in ('voidGen','debug','compSolids','simplifyCTable','volSDEF','volCARD', - 'dummyMat','cellSummaryFile','cellCommentFile','sortEnclosure') : - if not isinstance(value,bool) : - print('{} value should be boolean'.format(kwrd)) - return - - self.__dict__[kwrd] = value - if kwrd == 'stepFile' and self.__dict__['geometryName'] == '' : - if isinstance(value,(tuple,list)): - self.__dict__['geometryName'] == 'joined_step_files' - else: - self.__dict__['geometryName'] == value[:-4] - - - def Start(self): - - print('start') - FreeCAD_Version = '{V[0]:}.{V[1]:}.{V[2]:}'.format(V=FreeCAD.Version()) - print('GEOUNED version {} {} \nFreeCAD version {}'.format(GEOUNED_Version,GEOUNED_ReleaseDate,FreeCAD_Version)) - - code_setting = self.__dict__ - if code_setting is None: - raise ValueError('Cannot run the code. Input are missing') - if code_setting['stepFile'] == '': - raise ValueError('Cannot run the code. Step file name is missing') - - stepfile = code_setting['stepFile'] - matfile = code_setting['matFile'] - - if isinstance(stepfile,(tuple,list)): - for stp in stepfile: - if not path.isfile(stp) : - raise FileNotFoundError(f'Step file {stp} not found.\nStop.') - else: - if not path.isfile(stepfile) : - raise FileNotFoundError(f'Step file {stepfile} not found.\nStop.') - - startTime = datetime.now() - - if isinstance(stepfile,(list,tuple)): - MetaChunk = [] - EnclosureChunk = [] - for stp in stepfile : - print('read step file : {}'.format(stp)) - Meta,Enclosure = Load.LoadCAD(stp,matfile) - MetaChunk.append(Meta) - EnclosureChunk.append(Enclosure) - MetaList = joinMetaLists(MetaChunk) - EnclosureList = joinMetaLists(EnclosureChunk) - else: - print('read step file : {}'.format(stepfile)) - MetaList,EnclosureList = Load.LoadCAD(stepfile,matfile,code_setting['voidMat'],code_setting['compSolids']) - - print('End of loading phase') - tempstr1 = str(datetime.now()-startTime) - print(tempstr1) - tempTime = datetime.now() - - # Select a specific solid range from original STEP solids - if code_setting['cellRange'] : - MetaList = MetaList[code_setting['cellRange'][0]:code_setting['cellRange'][1]] - - # export in STEP format solids read from input file - # terminate excution - if code_setting['exportSolids'] != '': - solids=[] - for m in MetaList: - if m.IsEnclosure: continue - solids.extend(m.Solids) - Part.makeCompound(solids).exportStep(code_setting['exportSolids']) - msg = ( - f'Solids exported in file {code_setting["exportSolids"]}\n' - 'GEOUNED Finish. No solid translation performed.' - ) - raise ValueError(msg) - - # set up Universe - if EnclosureList : - UniverseBox = getUniverse(MetaList+EnclosureList) - else: - UniverseBox = getUniverse(MetaList) - Comsolids= [] - - surfOffset = code_setting['startSurf'] - 1 - Surfaces = UF.Surfaces_dict(offset=surfOffset) - - - warnSolids = [] - warnEnclosures = [] - coneInfo = dict() - tempTime0 = datetime.now() - if not Options.Facets: - - # decompose all solids in elementary solids (convex ones) - warningSolidList = DecomposeSolids(MetaList,Surfaces,UniverseBox,code_setting,True) - - # decompose Enclosure solids - if code_setting['voidGen'] and EnclosureList : - warningEnclosureList = DecomposeSolids(EnclosureList,Surfaces,UniverseBox,code_setting,False) - - print('End of decomposition phase') - - # start Building CGS cells phase - - for j,m in enumerate(MetaList): - if m.IsEnclosure : continue - print('Building cell: ', j+1) - cones = Conv.cellDef(m,Surfaces,UniverseBox) - if cones : coneInfo[m.__id__] = cones - if j in warningSolidList: - warnSolids.append(m) - if not m.Solids: - print('none',j,m.__id__) - print(m.Definition) - - if Options.forceNoOverlap : - Conv.noOverlappingCell(MetaList,Surfaces) - - else: - translate(MetaList,Surfaces,UniverseBox,code_setting) - # decompose Enclosure solids - if code_setting['voidGen'] and EnclosureList : - warningEnclosureList = DecomposeSolids(EnclosureList,Surfaces,UniverseBox,code_setting,False) - - tempstr2 = str(datetime.now()-tempTime) - print(tempstr2) - - - # building enclosure solids - - if code_setting['voidGen'] and EnclosureList : - for j,m in enumerate(EnclosureList): - print('Building Enclosure Cell: ', j+1) - cones = Conv.cellDef(m,Surfaces,UniverseBox) - if cones : coneInfo[m.__id__] = cones - if j in warningEnclosureList: - warnEnclosures.append(m) - - - tempTime1 = datetime.now() - - - # void generation phase - MetaVoid = [] - if code_setting['voidGen'] : - print('Build Void') - print(code_setting['voidExclude']) - if not code_setting['voidExclude']: - MetaReduced = MetaList - else : - MetaReduced = excludeCells(MetaList,code_setting['voidExclude']) - - if MetaList : - init = MetaList[-1].__id__ -len(EnclosureList) - else: - init = 0 - MetaVoid = Void.voidGeneration(MetaReduced,EnclosureList,Surfaces,UniverseBox,code_setting,init) - - #if code_setting['simplify'] == 'full' and not Options.forceNoOverlap: - if code_setting['simplify'] == 'full' : - Surfs = {} - for lst in Surfaces.values(): - for s in lst: - Surfs[s.Index] = s - - for c in MetaList: - if c.Definition.level == 0 or c.IsEnclosure: continue - print('simplify cell',c.__id__) - Box = UF.getBox(c) - CT = buildCTableFromSolids(Box,(c.Surfaces,Surfs),option='full') - c.Definition.simplify(CT) - c.Definition.clean() - if type(c.Definition.elements) is bool: - print('unexpected constant cell {} :{}'.format(c.__id__,c.Definition.elements)) - - tempTime2 = datetime.now() - print('build Time:',tempTime2-tempTime1) - - print(datetime.now()-startTime) - - cellOffSet = code_setting['startCell'] - 1 - if EnclosureList and code_setting['sortEnclosure'] : - # sort group solid cell / void cell sequence in each for each enclosure - # if a solid belong to several enclosure, its definition will be written - # for the highest enclosure level or if same enclosure level in the first - # enclosure found - MetaList = sortEnclosure(MetaList,MetaVoid,cellOffSet) - else: - # remove Null Cell and apply cell numbering offset - deleted = [] - idLabel = {0:0} - icount = cellOffSet - for i,m in enumerate(MetaList): - if m.NullCell or m.IsEnclosure : - deleted.append(i) - continue + else: + print("bad section name : {}".format(section)) + + if self.__dict__["geometryName"] == "": + self.__dict__["geometryName"] = self.__dict__["stepFile"][:-4] + + if Options.prnt3PPlane and not PdEntry: + MCNP_numeric_format.P_d = "22.15e" + + print(self.__dict__) - icount += 1 - m.label = icount - idLabel[m.__id__] = m.label + def set(self, kwrd, value): + + if kwrd not in self.__dict__.keys(): + print("Bad entry : {}".format(kwrd)) + return + + if kwrd == "stepFile": + if isinstance(value, (list, tuple)): + for v in value: + if not isinstance(v, str): + print("elemt in {} list should be string".format(kwrd)) + return + elif not isinstance(value, str): + print("{} should be string or tuple of strings".format(kwrd)) + return + + elif kwrd == "UCARD": + if value == "None": + value = None + elif value.isdigit(): + value = int(value) + else: + print("{} value should be None or integer".format(kwrd)) + return + elif kwrd == "outFormat": + if len(value) == 0: + return + elif kwrd in ("geometryName", "matFile", "exportSolids"): + if not isinstance(value, str): + print("{} value should be str instance".format(kwrd)) + return + elif kwrd in ("cellRange", "voidMat", "voidExclude"): + if not isinstance(value, (list, tuple)): + print("{} value should be list or tuple".format(kwrd)) + return + elif kwrd in ("minVoidSize", "maxSurf", "maxBracket", "startCell", "startSurf"): + if not isinstance(value, int): + print("{} value should be integer".format(kwrd)) + return + elif kwrd in ( + "voidGen", + "debug", + "compSolids", + "simplifyCTable", + "volSDEF", + "volCARD", + "dummyMat", + "cellSummaryFile", + "cellCommentFile", + "sortEnclosure", + ): + if not isinstance(value, bool): + print("{} value should be boolean".format(kwrd)) + return - for i in reversed(deleted): - del MetaList[i] + self.__dict__[kwrd] = value + if kwrd == "stepFile" and self.__dict__["geometryName"] == "": + if isinstance(value, (tuple, list)): + self.__dict__["geometryName"] == "joined_step_files" + else: + self.__dict__["geometryName"] == value[:-4] + + def Start(self): + + print("start") + FreeCAD_Version = "{V[0]:}.{V[1]:}.{V[2]:}".format(V=FreeCAD.Version()) + print( + "GEOUNED version {} {} \nFreeCAD version {}".format( + GEOUNED_Version, GEOUNED_ReleaseDate, FreeCAD_Version + ) + ) + + code_setting = self.__dict__ + if code_setting is None: + raise ValueError("Cannot run the code. Input are missing") + if code_setting["stepFile"] == "": + raise ValueError("Cannot run the code. Step file name is missing") + + stepfile = code_setting["stepFile"] + matfile = code_setting["matFile"] + + if isinstance(stepfile, (tuple, list)): + for stp in stepfile: + if not path.isfile(stp): + raise FileNotFoundError(f"Step file {stp} not found.\nStop.") + else: + if not path.isfile(stepfile): + raise FileNotFoundError(f"Step file {stepfile} not found.\nStop.") + + startTime = datetime.now() + + if isinstance(stepfile, (list, tuple)): + MetaChunk = [] + EnclosureChunk = [] + for stp in stepfile: + print("read step file : {}".format(stp)) + Meta, Enclosure = Load.LoadCAD(stp, matfile) + MetaChunk.append(Meta) + EnclosureChunk.append(Enclosure) + MetaList = joinMetaLists(MetaChunk) + EnclosureList = joinMetaLists(EnclosureChunk) + else: + print("read step file : {}".format(stepfile)) + MetaList, EnclosureList = Load.LoadCAD( + stepfile, matfile, code_setting["voidMat"], code_setting["compSolids"] + ) + + print("End of loading phase") + tempstr1 = str(datetime.now() - startTime) + print(tempstr1) + tempTime = datetime.now() + + # Select a specific solid range from original STEP solids + if code_setting["cellRange"]: + MetaList = MetaList[ + code_setting["cellRange"][0] : code_setting["cellRange"][1] + ] + + # export in STEP format solids read from input file + # terminate excution + if code_setting["exportSolids"] != "": + solids = [] + for m in MetaList: + if m.IsEnclosure: + continue + solids.extend(m.Solids) + Part.makeCompound(solids).exportStep(code_setting["exportSolids"]) + msg = ( + f'Solids exported in file {code_setting["exportSolids"]}\n' + "GEOUNED Finish. No solid translation performed." + ) + raise ValueError(msg) + + # set up Universe + if EnclosureList: + UniverseBox = getUniverse(MetaList + EnclosureList) + else: + UniverseBox = getUniverse(MetaList) + Comsolids = [] + + surfOffset = code_setting["startSurf"] - 1 + Surfaces = UF.Surfaces_dict(offset=surfOffset) + + warnSolids = [] + warnEnclosures = [] + coneInfo = dict() + tempTime0 = datetime.now() + if not Options.Facets: + + # decompose all solids in elementary solids (convex ones) + warningSolidList = DecomposeSolids( + MetaList, Surfaces, UniverseBox, code_setting, True + ) + + # decompose Enclosure solids + if code_setting["voidGen"] and EnclosureList: + warningEnclosureList = DecomposeSolids( + EnclosureList, Surfaces, UniverseBox, code_setting, False + ) + + print("End of decomposition phase") + + # start Building CGS cells phase + + for j, m in enumerate(MetaList): + if m.IsEnclosure: + continue + print("Building cell: ", j + 1) + cones = Conv.cellDef(m, Surfaces, UniverseBox) + if cones: + coneInfo[m.__id__] = cones + if j in warningSolidList: + warnSolids.append(m) + if not m.Solids: + print("none", j, m.__id__) + print(m.Definition) + + if Options.forceNoOverlap: + Conv.noOverlappingCell(MetaList, Surfaces) + + else: + translate(MetaList, Surfaces, UniverseBox, code_setting) + # decompose Enclosure solids + if code_setting["voidGen"] and EnclosureList: + warningEnclosureList = DecomposeSolids( + EnclosureList, Surfaces, UniverseBox, code_setting, False + ) + + tempstr2 = str(datetime.now() - tempTime) + print(tempstr2) + + # building enclosure solids + + if code_setting["voidGen"] and EnclosureList: + for j, m in enumerate(EnclosureList): + print("Building Enclosure Cell: ", j + 1) + cones = Conv.cellDef(m, Surfaces, UniverseBox) + if cones: + coneInfo[m.__id__] = cones + if j in warningEnclosureList: + warnEnclosures.append(m) + + tempTime1 = datetime.now() + + # void generation phase + MetaVoid = [] + if code_setting["voidGen"]: + print("Build Void") + print(code_setting["voidExclude"]) + if not code_setting["voidExclude"]: + MetaReduced = MetaList + else: + MetaReduced = excludeCells(MetaList, code_setting["voidExclude"]) - lineComment = """\ + if MetaList: + init = MetaList[-1].__id__ - len(EnclosureList) + else: + init = 0 + MetaVoid = Void.voidGeneration( + MetaReduced, EnclosureList, Surfaces, UniverseBox, code_setting, init + ) + + # if code_setting['simplify'] == 'full' and not Options.forceNoOverlap: + if code_setting["simplify"] == "full": + Surfs = {} + for lst in Surfaces.values(): + for s in lst: + Surfs[s.Index] = s + + for c in MetaList: + if c.Definition.level == 0 or c.IsEnclosure: + continue + print("simplify cell", c.__id__) + Box = UF.getBox(c) + CT = buildCTableFromSolids(Box, (c.Surfaces, Surfs), option="full") + c.Definition.simplify(CT) + c.Definition.clean() + if type(c.Definition.elements) is bool: + print( + "unexpected constant cell {} :{}".format( + c.__id__, c.Definition.elements + ) + ) + + tempTime2 = datetime.now() + print("build Time:", tempTime2 - tempTime1) + + print(datetime.now() - startTime) + + cellOffSet = code_setting["startCell"] - 1 + if EnclosureList and code_setting["sortEnclosure"]: + # sort group solid cell / void cell sequence in each for each enclosure + # if a solid belong to several enclosure, its definition will be written + # for the highest enclosure level or if same enclosure level in the first + # enclosure found + MetaList = sortEnclosure(MetaList, MetaVoid, cellOffSet) + else: + # remove Null Cell and apply cell numbering offset + deleted = [] + idLabel = {0: 0} + icount = cellOffSet + for i, m in enumerate(MetaList): + if m.NullCell or m.IsEnclosure: + deleted.append(i) + continue + + icount += 1 + m.label = icount + idLabel[m.__id__] = m.label + + for i in reversed(deleted): + del MetaList[i] + + lineComment = """\ ########################################################## VOID CELLS ##########################################################""" - mc = UF.GEOUNED_Solid(None) - mc.Comments = lineComment - MetaList.append(mc) - - deleted = [] - for i,m in enumerate(MetaVoid): - if m.NullCell : - deleted.append(i) - continue - icount += 1 - m.label = icount - updateComment(m,idLabel) - for i in reversed(deleted): - del MetaVoid[i] + mc = UF.GEOUNED_Solid(None) + mc.Comments = lineComment + MetaList.append(mc) + + deleted = [] + for i, m in enumerate(MetaVoid): + if m.NullCell: + deleted.append(i) + continue + icount += 1 + m.label = icount + updateComment(m, idLabel) + for i in reversed(deleted): + del MetaVoid[i] - MetaList.extend(MetaVoid) + MetaList.extend(MetaVoid) + printWarningSolids(warnSolids, warnEnclosures) - printWarningSolids(warnSolids,warnEnclosures) + # add plane definition to cone + processCones(MetaList, coneInfo, Surfaces, UniverseBox) - # add plane definition to cone - processCones(MetaList,coneInfo,Surfaces,UniverseBox) - - # write outputformat input - writeGeometry(UniverseBox,MetaList,Surfaces,code_setting) - - print('End of MCNP, OpenMC, Serpent and PHITS translation phase') + # write outputformat input + writeGeometry(UniverseBox, MetaList, Surfaces, code_setting) - print('Process finished') - print(datetime.now()-startTime) - - print('Translation time of solid cells', tempTime1-tempTime0) - print('Translation time of void cells', tempTime2-tempTime1) + print("End of MCNP, OpenMC, Serpent and PHITS translation phase") + print("Process finished") + print(datetime.now() - startTime) -def DecomposeSolids(MetaList,Surfaces,UniverseBox,setting,meta): + print("Translation time of solid cells", tempTime1 - tempTime0) + print("Translation time of void cells", tempTime2 - tempTime1) + + +def DecomposeSolids(MetaList, Surfaces, UniverseBox, setting, meta): totsolid = len(MetaList) warningSolids = [] - for i,m in enumerate(MetaList): - if meta and m.IsEnclosure: continue - print('Decomposing solid: {}/{} '.format(i+1,totsolid)) - if setting['debug'] : + for i, m in enumerate(MetaList): + if meta and m.IsEnclosure: + continue + print("Decomposing solid: {}/{} ".format(i + 1, totsolid)) + if setting["debug"]: print(m.Comments) - if not path.exists('debug') : - mkdir("debug") - if m.IsEnclosure : - m.Solids[0].exportStep(u'debug/origEnclosure_{}.stp'.format(i)) - else: - m.Solids[0].exportStep(u'debug/origSolid_{}.stp'.format(i)) - - comsolid,err=Decom.SplitSolid(Part.makeCompound(m.Solids),UniverseBox) - - if err != 0 : - if not path.exists('Suspicious_solids') : - mkdir("Suspicious_solids") - if m.IsEnclosure: - Part.CompSolid(m.Solids).exportStep('Suspicious_solids/Enclosure_original_{}.stp'.format(i)) - comsolid.exportStep( 'Suspicious_solids/Enclosure_split_{}.stp'.format(i)) - else: - Part.CompSolid(m.Solids).exportStep('Suspicious_solids/Solid_original_{}.stp'.format(i)) - comsolid.exportStep( 'Suspicious_solids/Solid_split_{}.stp'.format(i)) - - warningSolids.append(i) - - if setting['debug'] : - if m.IsEnclosure : - comsolid.exportStep(u'debug/compEnclosure_{}.stp'.format(i)) + if not path.exists("debug"): + mkdir("debug") + if m.IsEnclosure: + m.Solids[0].exportStep("debug/origEnclosure_{}.stp".format(i)) + else: + m.Solids[0].exportStep("debug/origSolid_{}.stp".format(i)) + + comsolid, err = Decom.SplitSolid(Part.makeCompound(m.Solids), UniverseBox) + + if err != 0: + if not path.exists("Suspicious_solids"): + mkdir("Suspicious_solids") + if m.IsEnclosure: + Part.CompSolid(m.Solids).exportStep( + "Suspicious_solids/Enclosure_original_{}.stp".format(i) + ) + comsolid.exportStep( + "Suspicious_solids/Enclosure_split_{}.stp".format(i) + ) + else: + Part.CompSolid(m.Solids).exportStep( + "Suspicious_solids/Solid_original_{}.stp".format(i) + ) + comsolid.exportStep("Suspicious_solids/Solid_split_{}.stp".format(i)) + + warningSolids.append(i) + + if setting["debug"]: + if m.IsEnclosure: + comsolid.exportStep("debug/compEnclosure_{}.stp".format(i)) else: - comsolid.exportStep(u'debug/compSolid_{}.stp'.format(i)) - Surfaces.extend(Decom.ExtractSurfaces(comsolid,'All',UniverseBox,MakeObj=True)) + comsolid.exportStep("debug/compSolid_{}.stp".format(i)) + Surfaces.extend( + Decom.ExtractSurfaces(comsolid, "All", UniverseBox, MakeObj=True) + ) m.setCADSolid() m.updateSolids(comsolid.Solids) - return warningSolids + return warningSolids -def updateComment(meta,idLabel): - if meta.__commentInfo__ is None: return - if meta.__commentInfo__[1] is None: return - newLabel = ( idLabel[i] for i in meta.__commentInfo__[1] ) +def updateComment(meta, idLabel): + if meta.__commentInfo__ is None: + return + if meta.__commentInfo__[1] is None: + return + newLabel = (idLabel[i] for i in meta.__commentInfo__[1]) meta.setComments(Void.voidCommentLine((meta.__commentInfo__[0], newLabel))) - -def processCones(MetaList,coneInfo,Surfaces,UniverseBox): - cellId = tuple(coneInfo.keys()) - for m in MetaList: - if m.__id__ not in cellId and not m.Void: continue - - if m.Void and m.__commentInfo__ is not None : - if m.__commentInfo__[1] is None : continue - cones = set() - for Id in m.__commentInfo__[1] : - if Id in cellId : - cones.update(-x for x in coneInfo[Id]) - Conv.addConePlane(m.Definition, cones, Surfaces,UniverseBox ) - elif not m.Void: - Conv.addConePlane(m.Definition, coneInfo[m.__id__], Surfaces,UniverseBox) + + +def processCones(MetaList, coneInfo, Surfaces, UniverseBox): + cellId = tuple(coneInfo.keys()) + for m in MetaList: + if m.__id__ not in cellId and not m.Void: + continue + + if m.Void and m.__commentInfo__ is not None: + if m.__commentInfo__[1] is None: + continue + cones = set() + for Id in m.__commentInfo__[1]: + if Id in cellId: + cones.update(-x for x in coneInfo[Id]) + Conv.addConePlane(m.Definition, cones, Surfaces, UniverseBox) + elif not m.Void: + Conv.addConePlane(m.Definition, coneInfo[m.__id__], Surfaces, UniverseBox) + def getUniverse(MetaList): - d = 10 - Box = MetaList[0].BoundBox - xmin = Box.XMin - xmax = Box.XMax - ymin = Box.YMin - ymax = Box.YMax - zmin = Box.ZMin - zmax = Box.ZMax - for m in MetaList[1:]: - # MIO. This was removed since in HELIAS the enclosure cell is the biggest one - # if m.IsEnclosure: continue - xmin = min(m.BoundBox.XMin,xmin) - xmax = max(m.BoundBox.XMax,xmax) - ymin = min(m.BoundBox.YMin,ymin) - ymax = max(m.BoundBox.YMax,ymax) - zmin = min(m.BoundBox.ZMin,zmin) - zmax = max(m.BoundBox.ZMax,zmax) - - return FreeCAD.BoundBox(FreeCAD.Vector(xmin-d,ymin-d,zmin-d),FreeCAD.Vector(xmax+d,ymax+d,zmax+d)) - - -def printWarningSolids(warnSolids,warnEnclosures): - - if warnSolids or warnEnclosures : - fic = open('Warning_Solids_definition.txt','w') + d = 10 + Box = MetaList[0].BoundBox + xmin = Box.XMin + xmax = Box.XMax + ymin = Box.YMin + ymax = Box.YMax + zmin = Box.ZMin + zmax = Box.ZMax + for m in MetaList[1:]: + # MIO. This was removed since in HELIAS the enclosure cell is the biggest one + # if m.IsEnclosure: continue + xmin = min(m.BoundBox.XMin, xmin) + xmax = max(m.BoundBox.XMax, xmax) + ymin = min(m.BoundBox.YMin, ymin) + ymax = max(m.BoundBox.YMax, ymax) + zmin = min(m.BoundBox.ZMin, zmin) + zmax = max(m.BoundBox.ZMax, zmax) + + return FreeCAD.BoundBox( + FreeCAD.Vector(xmin - d, ymin - d, zmin - d), + FreeCAD.Vector(xmax + d, ymax + d, zmax + d), + ) + + +def printWarningSolids(warnSolids, warnEnclosures): + + if warnSolids or warnEnclosures: + fic = open("Warning_Solids_definition.txt", "w") else: - return - - if warnSolids : - lines = 'Solids :\n' - for sol in warnSolids: - lines += '\n' - lines += '{}\n'.format(sol.label) - lines += '{}\n'.format(sol.Comments) - lines += '{}\n'.format(writeMCNPCellDef(sol.Definition)) - fic.write(lines) - - if warnEnclosures : - lines = 'Enclosures :\n' - for sol in warnEnclosures: - lines += '\n' - lines += '{}\n'.format(sol.label) - lines += '{}\n'.format(sol.Comments) - lines += '{}\n'.format(writeMCNPCellDef(sol.Definition)) - - fic.write(lines) + return + + if warnSolids: + lines = "Solids :\n" + for sol in warnSolids: + lines += "\n" + lines += "{}\n".format(sol.label) + lines += "{}\n".format(sol.Comments) + lines += "{}\n".format(writeMCNPCellDef(sol.Definition)) + fic.write(lines) + + if warnEnclosures: + lines = "Enclosures :\n" + for sol in warnEnclosures: + lines += "\n" + lines += "{}\n".format(sol.label) + lines += "{}\n".format(sol.Comments) + lines += "{}\n".format(writeMCNPCellDef(sol.Definition)) + + fic.write(lines) fic.close() def joinMetaLists(MList): - newMetaList = MList[0] - if MList[0]: - for M in MList[1:] : - lastID = newMetaList[-1].__id__+1 - for i,meta in enumerate(M) : - meta.__id__ = lastID + i - newMetaList.append(meta) + newMetaList = MList[0] + if MList[0]: + for M in MList[1:]: + lastID = newMetaList[-1].__id__ + 1 + for i, meta in enumerate(M): + meta.__id__ = lastID + i + newMetaList.append(meta) + + return newMetaList - return newMetaList -def excludeCells(MetaList,labelList): +def excludeCells(MetaList, labelList): voidMeta = [] for m in MetaList: - if m.IsEnclosure : continue + if m.IsEnclosure: + continue found = False for label in labelList: - if label in m.Comments : - found = True - break - if not found : - voidMeta.append(m) - - return voidMeta + if label in m.Comments: + found = True + break + if not found: + voidMeta.append(m) + return voidMeta -def sortEnclosure(MetaList,MetaVoid,offSet=0): +def sortEnclosure(MetaList, MetaVoid, offSet=0): newList = {} for m in MetaVoid: - if m.EnclosureID in newList.keys(): - newList[m.EnclosureID].append(m) - else: - newList[m.EnclosureID] = [m] - + if m.EnclosureID in newList.keys(): + newList[m.EnclosureID].append(m) + else: + newList[m.EnclosureID] = [m] + icount = offSet - idLabel = {0:0} + idLabel = {0: 0} newMeta = [] for m in MetaList: - if m.NullCell : continue - if m.IsEnclosure: - lineComment = """\ + if m.NullCell: + continue + if m.IsEnclosure: + lineComment = """\ ########################################################## ENCLOSURE {} -##########################################################""".format(m.EnclosureID) - mc = UF.GEOUNED_Solid(None) - mc.Comments = lineComment - newMeta.append(mc) - for e in newList[m.EnclosureID] : - if e.NullCell : continue - icount += 1 - e.label = icount - idLabel[e.__id__] = e.label - newMeta.append(e) - lineComment = """\ +##########################################################""".format( + m.EnclosureID + ) + mc = UF.GEOUNED_Solid(None) + mc.Comments = lineComment + newMeta.append(mc) + for e in newList[m.EnclosureID]: + if e.NullCell: + continue + icount += 1 + e.label = icount + idLabel[e.__id__] = e.label + newMeta.append(e) + lineComment = """\ ########################################################## END ENCLOSURE {} -##########################################################""".format(m.EnclosureID) - mc = UF.GEOUNED_Solid(None) - mc.Comments = lineComment - newMeta.append(mc) - - else: - icount += 1 - m.label = icount - idLabel[m.__id__] = m.label - newMeta.append(m) - +##########################################################""".format( + m.EnclosureID + ) + mc = UF.GEOUNED_Solid(None) + mc.Comments = lineComment + newMeta.append(mc) + + else: + icount += 1 + m.label = icount + idLabel[m.__id__] = m.label + newMeta.append(m) lineComment = """\ ########################################################## @@ -629,17 +763,19 @@ def sortEnclosure(MetaList,MetaVoid,offSet=0): mc.Comments = lineComment newMeta.append(mc) - for v in newList[0] : - if v.NullCell : continue + for v in newList[0]: + if v.NullCell: + continue icount += 1 v.label = icount idLabel[v.__id__] = v.label newMeta.append(v) - + for m in newMeta: - if not m.Void: continue - if m.IsEnclosure: continue - updateComment(m,idLabel) + if not m.Void: + continue + if m.IsEnclosure: + continue + updateComment(m, idLabel) return newMeta - diff --git a/testing/test.py b/testing/test.py index 390afb52..63999d94 100644 --- a/testing/test.py +++ b/testing/test.py @@ -3,29 +3,30 @@ import subprocess from pathlib import Path -sys.path.append(str(Path(__file__).parents[1]/'src')) -sys.path.append('/usr/lib64/freecad/lib64/') +sys.path.append(str(Path(__file__).parents[1] / "src")) +sys.path.append("/usr/lib64/freecad/lib64/") from geouned import GEOUNED -def setInput(inName,inpDir,outDir): - if inName.endswith('.step') : - filename = inName[0:-5] - elif inName.endswith('.stp') : - filename = inName[0:-4] - else : - filename = inName +def setInput(inName, inpDir, outDir): - if inpDir == '': - inpDir = '.' - if outDir == '': - outDir = '.' + if inName.endswith(".step"): + filename = inName[0:-5] + elif inName.endswith(".stp"): + filename = inName[0:-4] + else: + filename = inName - inName = '{}/{}'.format(inpDir,inName) - outName = '{}/{}'.format(outDir,filename) + if inpDir == "": + inpDir = "." + if outDir == "": + outDir = "." - template='''[Files] + inName = "{}/{}".format(inpDir, inName) + outName = "{}/{}".format(outDir, filename) + + template = """[Files] title = Input Test stepFile = {} geometryName = {} @@ -47,159 +48,177 @@ def setInput(inName,inpDir,outDir): splitTolerance = 0 newSplitPlane = True nPlaneReverse = 0 -'''.format(inName,outName) +""".format( + inName, outName + ) - file = open('config.ini','w') - file.write(template) - file.close() + file = open("config.ini", "w") + file.write(template) + file.close() -def getInputList(folder,ext=None): +def getInputList(folder, ext=None): filenameList = [] if ext is None: - return os.listdir(folder) + return os.listdir(folder) elif type(ext) is str: - if ext[0] != '.' : ext = '.' + ext - for f in os.listdir(folder) : - if f.endswith(ext) : - filenameList.append(f) - - elif type(ext) is list or type(ext) is tuple : - filenameList = [] - extList = [] - for e in ext: - if e[0] != '.' : e = '.' + e - extList.append(e) - - for f in os.listdir(folder) : - for e in extList: - if f.endswith(e) : + if ext[0] != ".": + ext = "." + ext + for f in os.listdir(folder): + if f.endswith(ext): filenameList.append(f) + elif type(ext) is list or type(ext) is tuple: + filenameList = [] + extList = [] + for e in ext: + if e[0] != ".": + e = "." + e + extList.append(e) + + for f in os.listdir(folder): + for e in extList: + if f.endswith(e): + filenameList.append(f) + return filenameList -def runMCNP(path,inpFile): - code = '/opt/mcnp5/last/bin/mcnp5' - xsdir = '/opt/mcnp.data/ascii/xsdir' - inp = inpFile - out = inpFile[0:-1]+'o' - mctal = inpFile[0:-1]+'m' - cmd = 'cd {} && {} i={} o={} mctal={} xsdir={}'.format(path,code,inp,out,mctal,xsdir) - os.system(cmd) +def runMCNP(path, inpFile): + code = "/opt/mcnp5/last/bin/mcnp5" + xsdir = "/opt/mcnp.data/ascii/xsdir" + inp = inpFile + out = inpFile[0:-1] + "o" + mctal = inpFile[0:-1] + "m" + cmd = "cd {} && {} i={} o={} mctal={} xsdir={}".format( + path, code, inp, out, mctal, xsdir + ) + os.system(cmd) + def clean(folder): - filename = '{}/runtpe'.format(folder) - if os.path.isfile(filename) : - os.remove(filename) + filename = "{}/runtpe".format(folder) + if os.path.isfile(filename): + os.remove(filename) + def cleanDir(folder): - for file in getInputList(folder,('.o','.m')): - filename = '{}/{}'.format(folder,file) - os.remove(filename) + for file in getInputList(folder, (".o", ".m")): + filename = "{}/{}".format(folder, file) + os.remove(filename) + def checkLost(outp): - cmd = 'grep \'particles got lost.\' {}'.format(outp) + cmd = "grep 'particles got lost.' {}".format(outp) stdout = subprocess.getoutput(cmd) - lineout = stdout.split('\n') + lineout = stdout.split("\n") lost = 0 - for l in lineout : - if l=='' or 'terminated' in l : continue - lost = int( l[0:l.index('particles')]) - return lost - + for l in lineout: + if l == "" or "terminated" in l: + continue + lost = int(l[0 : l.index("particles")]) + return lost + def getMctalValues(mctal): - file = open(mctal,'r') - while True: - line = file.readline() - if 'vals' in line: break - - rawData=[] - line = file.readline() - while 'tfc' not in line: - rawData.extend(line.split()) - line = file.readline() - file.close() - - values=[] - for i in range(int(len(rawData)/2)) : - val=float(rawData[2*i] ) - err=float(rawData[2*i+1]) - values.append((val,err)) - return values - -def printResults(f,res,lost): - - line='{} :\n'.format(f) - if lost != 0: line += '{} particles got lost.\n'.format(lost) - - for i,vals in enumerate(res): - line+=' {:<3d} : {:8.5f} {:7.5f}\n'.format(i+1,vals[0],vals[1]) + file = open(mctal, "r") + while True: + line = file.readline() + if "vals" in line: + break + + rawData = [] + line = file.readline() + while "tfc" not in line: + rawData.extend(line.split()) + line = file.readline() + file.close() + + values = [] + for i in range(int(len(rawData) / 2)): + val = float(rawData[2 * i]) + err = float(rawData[2 * i + 1]) + values.append((val, err)) + return values + + +def printResults(f, res, lost): + + line = "{} :\n".format(f) + if lost != 0: + line += "{} particles got lost.\n".format(lost) + + for i, vals in enumerate(res): + line += " {:<3d} : {:8.5f} {:7.5f}\n".format(i + 1, vals[0], vals[1]) print(line) -def mkGEOInp(inpDir,outDir): - for f in getInputList(inpDir,('stp','step')): - setInput(f,inpDir,outDir) - GEO = GEOUNED(inifile) - GEO.SetOptions() - GEO.Start() - del GEO - -def processMCNPfolder(outDir): - cleanDir(outDir) - for f in getInputList(outDir,'.mcnp'): - os.rename(f'{outDir}/{f}',f'{outDir}/{f[:-4]}i') - - for f in getInputList(outDir,'.i'): - runMCNP(outDir,f) - clean(outDir) +def mkGEOInp(inpDir, outDir): + for f in getInputList(inpDir, ("stp", "step")): + setInput(f, inpDir, outDir) + GEO = GEOUNED(inifile) + GEO.SetOptions() + GEO.Start() + del GEO -def postProcess(folder): - for fmct in getInputList(folder,'.m'): - fout = fmct[:-1]+'o' - mctal = '{}/{}'.format(folder,fmct) - outp = '{}/{}'.format(folder,fout) - res = getMctalValues(mctal) - lost = checkLost(outp) - printResults(fmct[:-1]+'i',res,lost) -# **************************************************** +def processMCNPfolder(outDir): + cleanDir(outDir) + for f in getInputList(outDir, ".mcnp"): + os.rename(f"{outDir}/{f}", f"{outDir}/{f[:-4]}i") -misInp = 'inputSTEP/Misc' -misOut = 'outMCNP/Misc' -cylInp = 'inputSTEP/DoubleCylinder' -cylOut = 'outMCNP/DoubleCylinder' -torInp = 'inputSTEP/Torus' -torOut = 'outMCNP/Torus' -lrgInp = 'inputSTEP/large' -lrgOut = 'outMCNP/large' -ms0Inp = 'inputSTEP/' -ms0Out = 'outMCNP/' + for f in getInputList(outDir, ".i"): + runMCNP(outDir, f) + clean(outDir) -inifile = 'config.ini' -folder = {'misc':(misInp,misOut),\ - 'cyl' :(cylInp,cylOut),\ - 'torus':(torInp,torOut),\ - 'large':(lrgInp,lrgOut),\ - 'misc0':(ms0Inp,ms0Out)} -test = 'all' +def postProcess(folder): + for fmct in getInputList(folder, ".m"): + fout = fmct[:-1] + "o" + mctal = "{}/{}".format(folder, fmct) + outp = "{}/{}".format(folder, fout) + res = getMctalValues(mctal) + lost = checkLost(outp) + printResults(fmct[:-1] + "i", res, lost) -if test == 'all': - for inpDir,outDir in folder.values(): - mkGEOInp(inpDir,outDir) - for inpDir,outDir in folder.values(): - processMCNPfolder(outDir) +# **************************************************** - for inpDir,outDir in folder.values(): - postProcess(outDir) +misInp = "inputSTEP/Misc" +misOut = "outMCNP/Misc" +cylInp = "inputSTEP/DoubleCylinder" +cylOut = "outMCNP/DoubleCylinder" +torInp = "inputSTEP/Torus" +torOut = "outMCNP/Torus" +lrgInp = "inputSTEP/large" +lrgOut = "outMCNP/large" +ms0Inp = "inputSTEP/" +ms0Out = "outMCNP/" + +inifile = "config.ini" +folder = { + "misc": (misInp, misOut), + "cyl": (cylInp, cylOut), + "torus": (torInp, torOut), + "large": (lrgInp, lrgOut), + "misc0": (ms0Inp, ms0Out), +} + +test = "all" + +if test == "all": + for inpDir, outDir in folder.values(): + mkGEOInp(inpDir, outDir) + + for inpDir, outDir in folder.values(): + processMCNPfolder(outDir) + + for inpDir, outDir in folder.values(): + postProcess(outDir) else: - inpDir,outDir = folder[test] - mkGEOInp(inpDir,outDir) - processMCNPfolder(outDir) - postProcess(outDir) + inpDir, outDir = folder[test] + mkGEOInp(inpDir, outDir) + processMCNPfolder(outDir) + postProcess(outDir) diff --git a/tests/test_volumes.py b/tests/test_volumes.py index 68934c74..96c856b6 100644 --- a/tests/test_volumes.py +++ b/tests/test_volumes.py @@ -1,9 +1,9 @@ - """ The tests check the resulting volume of the CSG cells using OpenMC. The tests assumes that the test_convert script has previously been run and that xml files exist in the tests_outputs folder. """ + import sys import math import os @@ -20,39 +20,37 @@ with open("cross_sections.xml", "w") as file: file.write( - """ + """ """ ) -openmc.config['cross_sections'] = Path("cross_sections.xml").resolve() +openmc.config["cross_sections"] = Path("cross_sections.xml").resolve() path_to_cad = Path("testing/inputSTEP") step_files = list(path_to_cad.rglob("*.stp")) + list(path_to_cad.rglob("*.step")) -step_files.remove(Path('testing/inputSTEP/Misc/rails.stp')) +step_files.remove(Path("testing/inputSTEP/Misc/rails.stp")) # # this checks if the tests are being run a github action runner or not if os.getenv("GITHUB_ACTIONS"): # reduced samples as github action runners have 2 threads and more samples # is not needed for the smaller models tested. This allows the CI to # quickly test the smaller models - samples=4_000_000 - rel_tol=0.05 + samples = 4_000_000 + rel_tol = 0.05 else: # samples for local run can be larger as threads is likely to be larger - samples=400_000_000 + samples = 400_000_000 # acceptable tolerance can also be smaller - rel_tol=0.01 + rel_tol = 0.01 @pytest.mark.skipif( sys.platform in ["win32", "darwin"], - reason="OpenMC doesn't install on Windows currently and is not well tested on Mac" -) -@pytest.mark.parametrize( - "input_step_file", step_files + reason="OpenMC doesn't install on Windows currently and is not well tested on Mac", ) +@pytest.mark.parametrize("input_step_file", step_files) def test_volumes(input_step_file): output_dir = Path("tests_outputs") / input_step_file.with_suffix("") @@ -77,8 +75,22 @@ def test_volumes(input_step_file): for solid, (cell_id, cell) in zip(result.Solids, cells.items()): bb = solid.BoundBox - llx, lly, llz, urx, ury, urz = bb.XMin, bb.YMin, bb.ZMin, bb.XMax, bb.YMax, bb.ZMax - llx, lly, llz, urx, ury, urz = llx/10, lly/10, llz/10, urx/10, ury/10, urz/10 + llx, lly, llz, urx, ury, urz = ( + bb.XMin, + bb.YMin, + bb.ZMin, + bb.XMax, + bb.YMax, + bb.ZMax, + ) + llx, lly, llz, urx, ury, urz = ( + llx / 10, + lly / 10, + llz / 10, + urx / 10, + ury / 10, + urz / 10, + ) cell_vol_calc = openmc.VolumeCalculation( domains=[cell], @@ -96,7 +108,7 @@ def test_volumes(input_step_file): settings.run_mode = "volume" model = openmc.Model(geometry, materials, settings) - model.export_to_model_xml(path=openmc_xml_file.with_name('model.xml')) + model.export_to_model_xml(path=openmc_xml_file.with_name("model.xml")) openmc.run(cwd=output_dir) for solid, (cell_id, cell) in zip(result.Solids, cells.items()):