1 # In this file are all the generation functions for manipulating the different created macro-objects
8 ##########################################################################################################
10 def Box11 (MacObject):
11 if Config.debug : print "Generating regular box"
13 dummy1 = geompy.MakeScaleAlongAxes( ElemBox11 (), None , MacObject.GeoPar[1][0], MacObject.GeoPar[1][1], 1)
14 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
16 MacObject.GeoChildren.append(RectFace)
17 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
19 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
22 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
23 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
25 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
26 Reg1D = MacObject.Mesh[0].Segment()
27 Reg1D.NumberOfSegments(MacObject.MeshPar[0])
29 MacObject.Mesh[0].Compute() # Generates the mesh
31 MacObject.DirectionalMeshParams = [MacObject.MeshPar[0],MacObject.MeshPar[0],MacObject.MeshPar[0],MacObject.MeshPar[0]]
34 Config.ListObj.append(MacObject)
37 ##########################################################################################################
39 def Box42 (MacObject):
40 if Config.debug : print "Generating box 4-2 reducer"
42 Z_Axis = geompy.MakeVectorDXDYDZ(0., 0., 1.)
43 RotAngle = {'SN' : lambda : 0,
44 'NS' : lambda : math.pi,
45 'EW' : lambda : math.pi/2,
46 'WE' : lambda : -math.pi/2, }[MacObject.MeshPar[1]]()
47 dummy0 = geompy.MakeRotation( ElemBox42 () , Z_Axis, RotAngle )
48 dummy1 = geompy.MakeScaleAlongAxes( dummy0, None , MacObject.GeoPar[1][0], MacObject.GeoPar[1][1], 1)
49 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
51 MacObject.GeoChildren.append(RectFace)
52 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
54 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
57 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
58 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
60 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
61 Reg1D = MacObject.Mesh[0].Segment()
62 Reg1D.NumberOfSegments(MacObject.MeshPar[0])
64 MacObject.Mesh[0].Compute() # Generates the mesh
68 x = MacObject.MeshPar[0]
69 MacObject.DirectionalMeshParams = {'SN' : lambda : [3*x, 3*x, 4*x, 2*x],
70 'NS' : lambda : [3*x, 3*x, 2*x, 4*x],
71 'EW' : lambda : [2*x, 4*x, 3*x, 3*x],
72 'WE' : lambda : [4*x, 2*x, 3*x, 3*x], }[MacObject.MeshPar[1]]()
74 Config.ListObj.append(MacObject)
78 ##########################################################################################################
80 def BoxAng32 (MacObject):
81 if Config.debug : print "Generating sharp angle"
82 Z_Axis = geompy.MakeVectorDXDYDZ(0., 0., 1.)
83 RotAngle = {'NE' : lambda : 0,
84 'NW' : lambda : math.pi/2,
85 'SW' : lambda : math.pi,
86 'SE' : lambda : -math.pi/2, }[MacObject.MeshPar[1]]()
87 dummy0 = geompy.MakeRotation( ElemEdge32 () , Z_Axis, RotAngle )
88 dummy1 = geompy.MakeScaleAlongAxes( dummy0, None , MacObject.GeoPar[1][0], MacObject.GeoPar[1][1], 1)
89 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
91 MacObject.GeoChildren.append(RectFace)
92 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
94 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
97 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
98 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
100 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
101 Reg1D = MacObject.Mesh[0].Segment()
102 Reg1D.NumberOfSegments(MacObject.MeshPar[0])
104 MacObject.Mesh[0].Compute() # Generates the mesh
108 x = MacObject.MeshPar[0]
109 MacObject.DirectionalMeshParams = {'NE' : lambda : [3*x, 2*x, 3*x, 2*x],
110 'NW' : lambda : [2*x, 3*x, 3*x, 2*x],
111 'SW' : lambda : [2*x, 3*x, 2*x, 3*x],
112 'SE' : lambda : [3*x, 2*x, 2*x, 3*x], }[MacObject.MeshPar[1]]()
114 Config.ListObj.append(MacObject)
116 ##########################################################################################################
117 def CompBox (MacObject):
118 if Config.debug : print "Generating composite box"
120 dummy1 = geompy.MakeScaleAlongAxes( ElemBox11 (), None , MacObject.GeoPar[1][0], MacObject.GeoPar[1][1], 1)
121 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
123 MacObject.GeoChildren.append(RectFace)
124 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
126 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
129 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
130 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
132 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
134 ReducedRatio = ReduceRatio(MacObject.GeoPar[1][0],MacObject.GeoPar[1][1])
137 Vec = [(1,0,0),(0,1,0)]
140 if IsParallel(Edge,Vec[i]):
141 if not Reference[i]: # If this is the first found edge to be parallel to this direction, apply user preferences for meshing
143 ApplyConstant1DMesh(MacObject.Mesh[0],Edge,int(round(ReducedRatio[i]*MacObject.MeshPar[0])))
145 else: # If there already exists an edge parallel to this direction, then use a 1D projection
146 Apply1DProjMesh(MacObject.Mesh[0],Edge,Reference[i])
149 MacObject.Mesh[0].Compute() # Generates the mesh
151 MacObject.DirectionalMeshParams = [MacObject.MeshPar[0]*ReducedRatio[1],MacObject.MeshPar[0]*ReducedRatio[1],MacObject.MeshPar[0]*ReducedRatio[0],MacObject.MeshPar[0]*ReducedRatio[0]]
154 Config.ListObj.append(MacObject)
157 ##########################################################################################################
159 def CompBoxF (MacObject):
160 if Config.debug : print "Generating composite box"
162 dummy1 = geompy.MakeScaleAlongAxes( ElemBox11 (), None , MacObject.GeoPar[1][0], MacObject.GeoPar[1][1], 1)
163 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
165 MacObject.GeoChildren.append(RectFace)
166 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
168 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
171 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
172 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
174 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
176 #ReducedRatio = ReduceRatio(MacObject.GeoPar[1][0],MacObject.GeoPar[1][1])
179 Vec = [(1,0,0),(0,1,0)]
182 if IsParallel(Edge,Vec[i]):
183 if not Reference[i]: # If this is the first found edge to be parallel to this direction, apply user preferences for meshing
185 ApplyConstant1DMesh(MacObject.Mesh[0],Edge,int(round(MacObject.MeshPar[0][i])))
187 else: # If there already exists an edge parallel to this direction, then use a 1D projection
188 Apply1DProjMesh(MacObject.Mesh[0],Edge,Reference[i])
191 MacObject.Mesh[0].Compute() # Generates the mesh
193 MacObject.DirectionalMeshParams = [MacObject.MeshPar[0][1],MacObject.MeshPar[0][1],MacObject.MeshPar[0][0],MacObject.MeshPar[0][0]]
196 Config.ListObj.append(MacObject)
198 ##########################################################################################################
200 def NonOrtho (MacObject):
201 if Config.debug : print "Generating Non-orthogonal quadrangle"
203 RectFace = Quadrangler (MacObject.PtCoor)
205 MacObject.GeoChildren.append(RectFace)
206 MacObject.GeoChildrenNames.append("Quad_"+ str(len(Config.ListObj)+1))
209 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
212 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
213 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
215 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
217 #ReducedRatio = ReduceRatio(MacObject.GeoPar[1][0],MacObject.GeoPar[1][1])
219 Vec = [MacObject.DirVectors(i) for i in range(4)]
221 Dir = [IsParallel(Edge,Vec[j]) for j in range(4)].index(True)
222 DirConv = [0,0,1,1][Dir]
223 ApplyConstant1DMesh(MacObject.Mesh[0],Edge,int(round(MacObject.MeshPar[0][DirConv])))
225 MacObject.Mesh[0].Compute() # Generates the mesh
227 MacObject.DirectionalMeshParams = [MacObject.MeshPar[0][1],MacObject.MeshPar[0][1],MacObject.MeshPar[0][0],MacObject.MeshPar[0][0]]
230 Config.ListObj.append(MacObject)
233 ##########################################################################################################
235 def QuartCyl (MacObject):
236 if Config.debug : print "Generating quarter cylinder"
237 Z_Axis = geompy.MakeVectorDXDYDZ(0., 0., 1.)
238 RotAngle = {'NE' : lambda : 0,
239 'NW' : lambda : math.pi/2,
240 'SW' : lambda : math.pi,
241 'SE' : lambda : -math.pi/2, }[MacObject.MeshPar[1]]()
242 dummy0 = geompy.MakeRotation( ElemQuartCyl(MacObject.MeshPar[2]) , Z_Axis, RotAngle )
243 dummy1 = geompy.MakeScaleAlongAxes( dummy0, None , MacObject.GeoPar[1][0]/10., MacObject.GeoPar[1][1]/10., 1)
244 RectFace = geompy.MakeTranslation(dummy1, MacObject.GeoPar[0][0], MacObject.GeoPar[0][1], 0)
246 MacObject.GeoChildren.append(RectFace)
247 MacObject.GeoChildrenNames.append("Box_"+ str(len(Config.ListObj)+1))
249 if Config.debug : Publish (MacObject.GeoChildren,MacObject.GeoChildrenNames)
252 MacObject.Mesh.append(smesh.Mesh(RectFace)) # Creation of a new mesh
253 Quad2D = MacObject.Mesh[0].Quadrangle() # Applying a quadrangle hypothesis
255 EdgeIDs = geompy.SubShapeAllSorted(RectFace,6) # List of Edge IDs belonging to RectFace, 6 = Edge in salome dictionary
256 Reg1D = MacObject.Mesh[0].Segment()
258 #if MacObject.MeshPar[0] == 2 and MacObject.MeshPar[2] <= 2.:
259 # print("Due to a bug in Salome 6.3, we are forced to either increase or decrease the local refinement by 50%, we choose in this case to increase the model's refinement.")
260 # MacObject.MeshPar[0] = 3
262 Reg1D.NumberOfSegments(MacObject.MeshPar[0])
264 MacObject.Mesh[0].Compute() # Generates the mesh
268 x = MacObject.MeshPar[0]
269 N = QuarCylParam(MacObject.MeshPar[2])+1
271 MacObject.DirectionalMeshParams = {'NE' : lambda : [2*x, N*x, 2*x, N*x],
272 'NW' : lambda : [N*x, 2*x, 2*x, N*x],
273 'SW' : lambda : [N*x, 2*x, N*x, 2*x],
274 'SE' : lambda : [2*x, N*x, N*x, 2*x], }[MacObject.MeshPar[1]]()
276 Config.ListObj.append(MacObject)
279 ##########################################################################################################
280 # Below this are the elementary calculation/visualization functions
281 ##########################################################################################################
283 def Publish (ObjToPublish,NamesToPublish):
285 for GeoObj in ObjToPublish :
286 geompy.addToStudy(GeoObj,NamesToPublish[i])
289 def IsParallel (Edge, Vector):
291 Function checks whether a given edge object is parallel to a reference vector.
292 Output can be 0 (not parallel) or 1 (parallel and same sense) or 2 (parallel and opposite sense).
293 If the reference vector is null, the function returns 0
295 if Vector == (0,0,0) : return 0
297 P1 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,0))
298 P2 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,1))
299 V0 = [ P1[0] - P2[0], P1[1] - P2[1], P1[2] - P2[2] ]
300 if Distance2Pt((0,0,0),CrossProd(V0,Vector))<1e-7 and DotProd(V0,Vector) > 0 : return 1
301 elif Distance2Pt((0,0,0),CrossProd(V0,Vector))<1e-7 and DotProd(V0,Vector) < 0 : return 2
304 def IsOnCircle (Edge, Center, Radius):
306 Function checks whether a given edge object belong to the periphery of a circle defined by its
308 Output can be 0 (does not belong) or 1 (belongs).
309 If the reference Radius is null, the function returns 0
310 Note that this function is basic in the sense that it only checks if the two border points of a
311 given edge belong to the arc of reference.
313 if Radius == 0 : return 0
315 P1 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,0))
316 P2 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,1))
317 if abs(Distance2Pt(Center,P1)-Radius) < 1e-6 and abs(Distance2Pt(Center,P2)-Radius) < 1e-6:
322 def CrossProd(V1,V2):
324 Determines the cross product of two 3D vectors
326 return ([V1[1]*V2[2]-V1[2]*V2[1], V1[2]*V2[0]-V1[0]*V2[2], V1[0]*V2[1]-V1[1]*V2[0]])
328 def QuarCylParam(PitchRatio):
329 R = float(PitchRatio)/(PitchRatio+1)
331 X = (R+Eps/2.)*math.sin(math.pi/4)+Eps/2.
332 N = int(math.floor((math.pi*R/4.)/(Eps/2.)))
337 Determines the dot product of two 3D vectors
339 if len(V1)==2 : V1.append(0)
340 if len(V2)==2 : V2.append(0)
342 return (V1[0]*V2[0]+V1[1]*V2[1]+V1[2]*V2[2])
344 def Distance2Pt(P1,P2):
346 Returns the distance between two points
348 return (math.sqrt((P1[0]-P2[0])**2+(P1[1]-P2[1])**2+(P1[2]-P2[2])**2))
350 def ApplyConstant1DMesh (ParentMsh, Edge, Nseg):
351 Reg1D = ParentMsh.Segment(geom=Edge)
352 Len = Reg1D.NumberOfSegments(Nseg)
354 def Apply1DProjMesh (ParentMsh, Edge, Ref):
355 Proj1D = ParentMsh.Projection1D(geom=Edge)
356 SrcEdge = Proj1D.SourceEdge(Ref,None,None,None)
358 def EdgeLength (Edge):
360 This function returns the edge object length.
362 P1 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,0))
363 P2 = geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,1))
364 return Distance2Pt(P1,P2)
368 return Angle*math.pi/180
371 return Angle*180/math.pi
373 def F2D (FloatNumber):
374 return round(FloatNumber*100.)/100.
376 def BezierGen (PointA, PointB, AngleA, AngleB):
378 if AngleA == 0 and AngleB == 0 : return (geompy.MakeEdge(PointA, PointB))
380 A = geompy.PointCoordinates(PointA)
381 B = geompy.PointCoordinates(PointB)
382 dAB = Distance2Pt(A,B)
383 dAC = dAB * (math.tan(AngleA)*math.tan(AngleB)) / (math.sin(AngleA) * ( math.tan(AngleA)+math.tan(AngleB) ) )
384 AngleOX_AB = math.acos((B[0]-A[0])/dAB)
385 PointC = geompy.MakeVertex(A[0]+math.cos(AngleA+AngleOX_AB)*dAC,A[1]+math.sin(AngleA+AngleOX_AB)*dAC,0)
386 CurveACB = geompy.MakeBezier([PointA,PointC,PointB])
389 def GetSideAngleForBezier (PointA , PointB):
391 This function takes for input two points A and B where the bezier line is needed. It calculates the incident
392 angle needed at point A so that the final curve is either at 0 or 90 degrees from the x'Ox axis
394 A = geompy.PointCoordinates(PointA)
395 B = geompy.PointCoordinates(PointB)
397 dAB = Distance2Pt(A,B)
398 Alpha = math.acos(ABx/dAB)
399 #print "New angle request"
400 #print ABx, dAB, R2D(Alpha)
401 if Alpha < math.pi/4 :
402 #print "returning", R2D(-Alpha)
404 elif Alpha < 3*math.pi/4 :
405 #print "returning", R2D(-(Alpha-math.pi/2))
406 return -(Alpha-math.pi/2)
408 #print "returning", R2D(-(Alpha-math.pi))
409 return -(Alpha-math.pi)
411 def VecDivRatio (Vec1, Vec2):
413 This function tries to find the ratio of Vec1 on Vec2 while neglecting any zero term in Vec1. This is used afterwards
414 for determining the global mesh parameter from automatically detected directional mesh params. If no compatibility is
415 possible, the function returns -1
418 for i in range(len(Vec1)) :
419 Vec3.append(float(Vec1[i])/Vec2[i])
422 if not (abs(i)<1e-7) : Ratio.append(i)
424 if min(Ratio) == max(Ratio) and min(Ratio)==int(min(Ratio)) : return(min(Ratio))
430 def ReduceRatio (dx, dy):
432 This function transforms a decimal ratio into a scale between two integers, for example : [0.2,0.05] --> [4,1] ;
436 if isinteger(ratio) : return [1,ratio]
437 elif dx == 1 : # when this function is called recursively!
438 for i in range(1,20) : # searches over 20 decimals
439 if isinteger(ratio * (10**i) ) :
440 Output = GetScale((10**i),int(round(ratio * (10**i) ) ) )
443 for n in range(0,i) :
444 if isinteger(ratio * ( 10**(i)-10**(n) )) :
445 Output = GetScale( 10**(i)-10**(n) , int(round(ratio * ( 10**(i)-10**(n) ) ) ) )
447 if not (Output==[0,0]) : break
450 for i in range(1,10) : # searches over 10 decimals
451 if isinteger(ratio * (10**i) ) :
452 Output = GetScale((10**i),int(round(ratio * (10**i) ) ) )
455 for n in range(0,i) :
456 if isinteger(ratio * ( 10**(i)-10**(n) )) :
457 Output = GetScale( 10**(i)-10**(n) , int(round(ratio * ( 10**(i)-10**(n) ) ) ) )
459 if not (Output==[0,0]) : break
462 print "We are having some trouble while interpreting the following ratio: ",ratio, "\nWe will try a recursive method which may in some cases take some time..."
464 A = ReduceRatio (dx, dy-dx)
465 return ([A[0],A[1]+A[0]])
467 A = ReduceRatio (dy, dx-dy)
468 return ([A[1]+A[0],A[0]])
474 This function is called within ReduceRatio and aims to reduce down two integers X and Y by dividing them with their common divisors;
475 Example: 25 and 5 ---> 5 and 1 / 63 and 12 ---> 21 and 4
478 Divisor = 2 # Initializing the divisor
479 while MaxDiv >= Divisor :
484 MaxDiv = max(MaxDiv,X0)
487 MaxDiv = max(MaxDiv,Y0)
492 Divisor = Divisor + 1
497 This functions applies a simple check if the entered value is an integer
499 x = float('%.5f' % (x)) #Truncate x to 5 digits after the decimal point
500 if math.ceil(x) == math.floor(x) : return True
502 ##########################################################################################
503 # Below this are the functions that create the elementary forms for the macro objects
504 ##########################################################################################
508 This function returns a simple square face of 1 side length
510 RectFace = geompy.MakeFaceHW(1, 1, 1)
515 This function returns a square face of 1 side length, partitioned
516 according to the elementary 4 to 2 reductor method
518 OrigRectFace = geompy.MakeFaceHW(1, 1, 1)
520 SouthPt1 = geompy.MakeVertex (-.25, -.5, 0)
521 SouthPt2 = geompy.MakeVertex (0, -.5, 0)
522 SouthPt3 = geompy.MakeVertex (.25, -.5, 0)
523 WestPt1 = geompy.MakeVertex (-.5, -.5+1./3, 0)
524 WestPt2 = geompy.MakeVertex (-.5, -.5+2./3, 0)
525 EastPt1 = geompy.MakeVertex (.5, -.5+1./3, 0)
526 EastPt2 = geompy.MakeVertex (.5, -.5+2./3, 0)
527 NorthPt = geompy.MakeVertex (0, .5, 0)
528 MidPt1 = geompy.MakeVertex (0, .05, 0)
529 MidPt2 = geompy.MakeVertex (.2, -.18, 0)
530 MidPt3 = geompy.MakeVertex (0, -.28, 0)
531 MidPt4 = geompy.MakeVertex (-.2, -.18, 0)
534 Cutter.append(geompy.MakeEdge(SouthPt2, MidPt3))
535 Cutter.append(geompy.MakeEdge(MidPt1, NorthPt))
536 Cutter.append(BezierGen(SouthPt1, MidPt4, GetSideAngleForBezier(SouthPt1,MidPt4), D2R(15)))
537 Cutter.append(BezierGen(SouthPt3, MidPt2, GetSideAngleForBezier(SouthPt3,MidPt2), D2R(-15)))
538 Cutter.append(BezierGen(WestPt1, MidPt4, GetSideAngleForBezier(WestPt1,MidPt4), D2R(-10)))
539 Cutter.append(BezierGen(EastPt1, MidPt2, GetSideAngleForBezier(EastPt1,MidPt2), D2R(10)))
540 Cutter.append(BezierGen(WestPt2, MidPt1, GetSideAngleForBezier(WestPt2,MidPt1), D2R(-10)))
541 Cutter.append(BezierGen(EastPt2, MidPt1, GetSideAngleForBezier(EastPt2,MidPt1), D2R(10)))
542 Cutter.append(BezierGen(MidPt2, MidPt1, D2R(-15), D2R(-15)))
543 Cutter.append(BezierGen(MidPt3, MidPt2, D2R(10), D2R(15)))
544 Cutter.append(BezierGen(MidPt3, MidPt4, D2R(-10), D2R(-15)))
545 Cutter.append(BezierGen(MidPt4, MidPt1, D2R(15), D2R(15)))
547 RectFace = geompy.MakePartition([OrigRectFace],Cutter, [], [],4, 0, [], 0) #Creating the partition object
549 #for SingleCut in Cutter :
550 # geompy.addToStudy(SingleCut,'Cutter'+str(i))
552 #geompy.addToStudy(RectFace,'RectFace')
557 This function returns a square face of 1 side length, partitioned
558 according to the elementary edge with 3 to 2 reductor
560 OrigRectFace = geompy.MakeFaceHW(1., 1., 1)
562 SouthPt1 = geompy.MakeVertex (-1./6, -0.5, 0.)
563 SouthPt2 = geompy.MakeVertex ( 1./6, -0.5, 0.)
564 WestPt1 = geompy.MakeVertex (-0.5, -1./6, 0.)
565 WestPt2 = geompy.MakeVertex (-0.5, 1./6, 0.)
566 EastPt = geompy.MakeVertex ( 0.5, 0., 0.)
567 NorthPt = geompy.MakeVertex (0., 0.5, 0.)
569 MidPt1 = geompy.MakeVertex (-0.2, -0.2, 0.)
570 MidPt2 = geompy.MakeVertex ( -0.02, -0.02, 0.)
573 Cutter.append(BezierGen(SouthPt1, MidPt1, GetSideAngleForBezier(SouthPt1,MidPt1) , D2R(-5)))
574 Cutter.append(BezierGen( WestPt1, MidPt1, GetSideAngleForBezier(WestPt1 ,MidPt1) , D2R(-5)))
575 Cutter.append(BezierGen(SouthPt2, MidPt2, GetSideAngleForBezier(SouthPt2,MidPt2) , D2R(-10)))
576 Cutter.append(BezierGen( EastPt, MidPt2, GetSideAngleForBezier(EastPt ,MidPt2) , D2R(5)))
577 Cutter.append(BezierGen( WestPt2, MidPt2, GetSideAngleForBezier(WestPt2 ,MidPt2) , D2R(-10)))
578 Cutter.append(BezierGen( MidPt2, NorthPt, GetSideAngleForBezier(NorthPt ,MidPt2) , D2R(-5)))
580 Cutter.append(geompy.MakeEdge(MidPt1, MidPt2))
582 RectFace = geompy.MakePartition([OrigRectFace],Cutter, [], [],4, 0, [], 0) #Creating the partition object
584 #for SingleCut in Cutter :
585 # geompy.addToStudy(SingleCut,'Cutter'+str(i))
587 #geompy.addToStudy(RectFace,'RectFace')
590 def Quadrangler (Points):
592 This function returns a quadranglar face based on four points, non of which 3 are non-colinear.
593 The points are defined by their 2D [(x1,y1),(x2,y2)..] coordinates.
594 Note that the list of points is already arranged upon the creation in MacObject
597 for Point in Points: Pt.append(geompy.MakeVertex(Point[0], Point[1], 0))
598 # The first point is added at the end of the list in order to facilitate the line creation
600 #Draw the lines in order to form the 4 side polygon
602 for i in range(4) : Ln.append(geompy.MakeLineTwoPnt(Pt[i],Pt[i+1]))
603 RectFace = geompy.MakeQuad (Ln[0],Ln[1],Ln[2],Ln[3])
608 This function returns a quarter cylinder to box relay of 1 side length, partitioned
609 with a pitch ratio of K, In other words the side of the box is R*(1+(1/K))
611 R = 10.*float(K)/(K+1)
614 Config.theStudy.SetReal("R" , R)
615 Config.theStudy.SetReal("minusR" , -R)
616 Config.theStudy.SetReal("Eps", Eps)
618 CylWire = geompy.MakeSketcher("Sketcher:F 'R' 0:R 0:L 'Eps':TT 10. 10.0:R 90:L 10.0:R 90:L 'Eps':R 90:C 'minusR' 90.0:WW", [0, 0, 0, 0, 0, 1, 1, 0, -0])
619 CylFace = geompy.MakeFace(CylWire, 1)
621 SouthPt = geompy.MakeVertex (R+Eps/2., 0., 0)
622 SouthWestPt = geompy.MakeVertex ( 0.,0., 0) #The origin can be used for practical partionning objectifs
623 WestPt = geompy.MakeVertex (0., R+Eps/2., 0)
625 N = int(math.floor((math.pi*R/4.)/(Eps/2.)))
626 X = 10.*(1.-1./(N+1))
629 EastPt = geompy.MakeVertex (10.0, X, 0.)
630 NorthPt = geompy.MakeVertex ( X, 10.0, 0.)
632 DivFactor = 8./(F2D(math.log(K))-0.223)
633 #MidPt = geompy.MakeVertex ((R+Eps)*math.cos(math.pi/4), (R+Eps)*math.sin(math.pi/4), 0.)
634 MidPt = geompy.MakeVertex (X-Eps/DivFactor, X-Eps/DivFactor, 0.)
637 Cutter.append(BezierGen(SouthWestPt, MidPt, GetSideAngleForBezier(SouthWestPt,MidPt) , D2R(-5)))
638 Cutter.append(BezierGen( EastPt, MidPt, GetSideAngleForBezier(EastPt,MidPt) , D2R(5)))
639 Cutter.append(BezierGen( MidPt, NorthPt, (-1)**((K<1.25)*1)*D2R(-5), GetSideAngleForBezier(NorthPt,MidPt)))
640 SMBezier = BezierGen( SouthPt, MidPt, GetSideAngleForBezier(SouthPt ,MidPt) , D2R((K<1.25)*180-5))
641 WMBezier = BezierGen( WestPt, MidPt, GetSideAngleForBezier(WestPt, MidPt) , D2R(-5))
642 Cutter.append(WMBezier)
643 Cutter.append(SMBezier)
645 for i in range(1,N) :
646 # Determining intermediate points on the bezier lines and then performing additional cuts
648 TempAnglePlus = (math.pi/4)*(1+float(i)/N)
649 SectionResult = CutnGroup.Go(WMBezier, [(0,0,0,math.sin(TempAnglePlus),-math.cos(TempAnglePlus),0)], [1], ['Dummy'], 0)
650 TempPt1 = SectionResult[1][0]
651 TempPt11 = geompy.MakeVertex ((N-i)*X/N, 10., 0)
653 TempAngleMinus = (math.pi/4)*(1-float(i)/N)
654 SectionResult = CutnGroup.Go(SMBezier, [(0,0,0,math.sin(TempAngleMinus),-math.cos(TempAngleMinus),0)], [1], ['Dummy'], 0)
655 TempPt2 = SectionResult[1][0]
656 TempPt21 = geompy.MakeVertex (10., (N-i)*X/N, 0)
658 Cutter.append(geompy.MakeEdge(SouthWestPt, TempPt1))
659 Cutter.append(geompy.MakeEdge(SouthWestPt, TempPt2))
660 Cutter.append(geompy.MakeEdge(TempPt1, TempPt11))
661 Cutter.append(geompy.MakeEdge(TempPt2, TempPt21))
663 CylFace = geompy.MakePartition([CylFace],Cutter, [], [],4, 0, [], 0) #Creating the partition object
664 CylFace = geompy.MakeTranslation(CylFace, -5., -5., 0.0)
668 def CompatibilityTest(MacObject):
669 Type = MacObject.Type
671 BaseDirPar = [1,1,1,1]
672 return int(VecDivRatio(MacObject.DirectionalMeshParams, BaseDirPar))
673 elif Type == 'Box42' :
674 BaseDirPar = {'SN' : lambda : [3, 3, 4, 2],
675 'NS' : lambda : [3, 3, 2, 4],
676 'EW' : lambda : [2, 4, 3, 3],
677 'WE' : lambda : [4, 2, 3, 3], }[MacObject.MeshPar[1]]()
678 return int(VecDivRatio(MacObject.DirectionalMeshParams, BaseDirPar))
679 elif Type == 'BoxAng32' :
680 BaseDirPar = {'NE' : lambda : [3, 2, 3, 2],
681 'NW' : lambda : [2, 3, 3, 2],
682 'SW' : lambda : [2, 3, 2, 3],
683 'SE' : lambda : [3, 2, 2, 3], }[MacObject.MeshPar[1]]()
684 return int(VecDivRatio(MacObject.DirectionalMeshParams, BaseDirPar))
685 elif Type == 'CompBox' :
686 #print "dx is: ", MacObject.GeoPar[1][1], ". dy is: ",MacObject.GeoPar[1][0]
687 ReducedRatio = ReduceRatio(MacObject.GeoPar[1][0], MacObject.GeoPar[1][1])
689 BaseDirPar = [ReducedRatio[1], ReducedRatio[1], ReducedRatio[0], ReducedRatio[0]]
690 return int(VecDivRatio(MacObject.DirectionalMeshParams, BaseDirPar))
692 elif Type == 'QuartCyl' :
693 N = QuarCylParam(MacObject.MeshPar[2])+1
694 BaseDirPar = {'NE' : lambda : [2, N, 2, N],
695 'NW' : lambda : [N, 2, 2, N],
696 'SW' : lambda : [N, 2, N, 2],
697 'SE' : lambda : [2, N, N, 2], }[MacObject.MeshPar[1]]()
698 return int(VecDivRatio(MacObject.DirectionalMeshParams, BaseDirPar))
699 elif Type == 'CompBoxF' :
700 RealRatio = MacObject.GeoPar[1][1]/MacObject.GeoPar[1][0]
703 if MacObject.DirectionalMeshParams[2]+MacObject.DirectionalMeshParams[3] :
704 A = int(max(MacObject.DirectionalMeshParams[2:4]))
705 Xd = int(VecDivRatio([A,0,0,0], [1,1,1,1]))
706 if MacObject.DirectionalMeshParams[0]+MacObject.DirectionalMeshParams[1] :
707 A = int(max(MacObject.DirectionalMeshParams[0:2]))
708 Yd = int(VecDivRatio([0,0,A,0], [1,1,1,1]))
710 if Xd == 0 and Yd : Xd = int(round(Yd/RealRatio))
711 elif Yd == 0 : Yd = int(round(RealRatio*Xd))
714 elif Type == 'NonOrtho' :
715 MeanDX = 0.5*(IntLen(MacObject.DirBoundaries(0))+IntLen(MacObject.DirBoundaries(1)))
716 MeanDY = 0.5*(IntLen(MacObject.DirBoundaries(2))+IntLen(MacObject.DirBoundaries(3)))
717 RealRatio = MeanDY/MeanDX
720 if MacObject.DirectionalMeshParams[2]+MacObject.DirectionalMeshParams[3] :
721 A = int(max(MacObject.DirectionalMeshParams[2:4]))
722 Xd = int(VecDivRatio([A,0,0,0], [1,1,1,1]))
723 if MacObject.DirectionalMeshParams[0]+MacObject.DirectionalMeshParams[1] :
724 A = int(max(MacObject.DirectionalMeshParams[0:2]))
725 Yd = int(VecDivRatio([0,0,A,0], [1,1,1,1]))
727 if Xd == 0 and Yd : Xd = int(round(Yd/RealRatio))
728 elif Yd == 0 : Yd = int(round(RealRatio*Xd))
732 def IntLen (Interval) :
734 This function returns the length of a given interval even if the latter is not sorted correctly.
736 return abs(Interval[1]-Interval[0])
738 def NextTo (RefBox, Direction, Extension):
740 This functions returns geometrical parameters for easy positioning of neighbouring objects.
741 The input (RefBox) and output are in the form : [(X0,Y0),(DX,DY)]
748 DirectionalCoef = {'Above' : lambda : [ 0, 1],
749 'Below' : lambda : [ 0,-1],
750 'Right' : lambda : [ 1, 0],
751 'Left ' : lambda : [-1, 0], }[Direction]()
753 X0_1 = X0_0+ DirectionalCoef[0] * (DX_0/2.+Extension/2.)
754 DX_1 = abs(DirectionalCoef[0]) * (Extension) + abs(DirectionalCoef[1])*DX_0
755 Y0_1 = Y0_0+ DirectionalCoef[1] * (DY_0/2.+Extension/2.)
756 DY_1 = abs(DirectionalCoef[1]) * (Extension) + abs(DirectionalCoef[0])*DY_0
758 return [(X0_1,Y0_1),(DX_1,DY_1)]
760 def GeomMinMax (PtA, PtB):
762 This function returns geometrical parameters in the format [(X0,Y0),(DX,DY)]. The input being
763 the coordinates of two points (Xa,Ya), (Xb,Yb).
765 # First test that the vector relying the two points is oblique
766 AB = [PtB[0]- PtA[0],PtB[1]- PtA[1]]
768 print ("Error: the two points are not correctly defined. In the orthonormal system XOY, it is impossible to define a rectangle with these two points")
771 X0 = 0.5*(PtA[0]+PtB[0])
772 Y0 = 0.5*(PtA[1]+PtB[1])
775 return [(X0,Y0),(DX,DY)]
777 def AddIfDifferent (List, Element):
778 if not(Element in List):
779 List = List+(Element,)
782 def IndexMultiOcc (Array,Element) :
784 This functions returns the occurrences indices of Element in Array.
785 As opposed to Array.index(Element) method, this allows determining
786 multiple entries rather than just the first one!
789 try : Array.index(Element)
790 except ValueError : print "No more occurrences"
791 else : Output.append(Array.index(Element))
793 if not(Output == []) and len(Array) > 1 :
794 for index, ArrElem in enumerate(Array[Output[0]+1:]) :
795 if ArrElem == Element : Output.append(index+Output[0]+1)
799 def SortList (ValList, CritList):
801 SortedCritList = copy.copy(CritList)
802 SortedCritList.sort()
803 for i in range(0,len(ValList)):
805 if not(SortedCritList[i]==SortedCritList[i-1]):
806 index = IndexMultiOcc(CritList,SortedCritList[i])
807 Output= Output + [ValList[j] for j in index]
809 index = IndexMultiOcc(CritList,SortedCritList[i])
810 Output= Output + [ValList[j] for j in index]
814 def SortPoints(Points):
816 This function sorts a list of the coordinates of N points as to start at
817 an origin that represents Xmin and Xmax and then proceed in a counter
821 Xmin = min([Points[i][0] for i in range(NbPts)])
822 Ymin = min([Points[i][1] for i in range(NbPts)])
823 Xmax = max([Points[i][0] for i in range(NbPts)])
824 Ymax = max([Points[i][1] for i in range(NbPts)])
825 Crit = [(abs(Point[0]-Xmin)+0.1*(Xmax-Xmin))*(abs(Point[1]-Ymin)+0.1*(Ymax-Ymin)) for Point in Points]
826 #print "Input Points : ", Points
827 #print "Sorting Criterion : ", Crit
828 Order = SortList (range(NbPts), Crit)
829 #print "Sorted Results : ", Order
831 Output.append(Points[Order[0]])
833 Point0 = Points[Order[0]]
834 #print "Reference point :", Point0
836 V = [[Point1[0]-Point0[0],Point1[1]-Point0[1]] for Point1 in Points]
837 Cosines = [-(vec[0]-1E-10)/(math.sqrt(DotProd(vec,vec)+1e-25)) for vec in V]
838 #print "Cosines criterion :", Cosines
839 Order = SortList(range(NbPts),Cosines)
840 #print "Ordered points:", Order
841 for PtIndex in Order[:-1]: Output.append(Points[PtIndex])