-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathPipe_torus_to_cylinder.py
More file actions
212 lines (190 loc) · 8.79 KB
/
Pipe_torus_to_cylinder.py
File metadata and controls
212 lines (190 loc) · 8.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# Python Script, API Version = V17
import math
Tolerance = 1e-5
def checkSurface (aSolid):
"check the torus and sketch surface"
sketchFaces = [] # for two sketch faces at the two side of the pipe
Tori = []
for iFace in aSolid.Faces:
if type (iFace.Shape.Geometry) is Torus :
Tori.append(iFace)
if type (iFace.Shape.Geometry) is Plane :
for iEdge in iFace.Edges:
Good = True
if type(iEdge.Shape.Geometry) is not Circle:
print "The sketch face contains non-circle edges, please check."
Good = False
if not Good:
return [[], []] # return a empty list of solid
else:
sketchFaces.append(iFace)
return [Tori, sketchFaces]
def createMidPlane(aSolid, FaceAngle):
"create the mid plane of the pipe"
# build the mid plane from mid-point of two scketch plane center, and the torus axis
[Tori, sketchFaces] = checkSurface(aSolid)
pointA = sketchFaces[0].Edges[0].Shape.Geometry.Frame.Origin
pointB = sketchFaces[1].Edges[0].Shape.Geometry.Frame.Origin
midPoint = Point.Create( (pointA.X + pointB.X)/2, (pointA.Y + pointB.Y)/2, (pointA.Z + pointB.Z)/2 )
midDatumPoint = DatumPoint.Create(GetRootPart(),"point", midPoint)
torusAxis = DatumLine.Create(GetRootPart(),"axis", Tori[0].Shape.Geometry.Axis)
aList = List[IDocObject]()
aList.Add(torusAxis)
# if FaceAngle == 0.0 or FaceAngle == 180.0 : # only if 180 degree
# if math.fabs (FaceAngle - ( -1.0 )) <Tolerance or math.fabs ( FaceAngle - ( 1.0 )) <Tolerance: # only if 180 degree
if sketchFaces[0].Shape.Geometry.IsCoincident (sketchFaces[1].Shape.Geometry) : # only if 180 degree
#in this case the midpoint is in the torus axis,
# we create another axis through the midpoint and pependicular to the torus axis
aAxis = Line.Create(midPoint, sketchFaces[0].Edges[0].Shape.Geometry.Axis.Direction)
newAxis = DatumLine.Create(GetRootPart(),"axisB", aAxis)
aList.Add(newAxis)
aList.Add(midDatumPoint)
midPlane = DatumPlane.GetPlane(aList)
Delete.Execute(Selection.Create(aList))
return midPlane
def calCosine(vec1, vec2):
"calculate the cosine of the angle"
#fix tolerenace problem that cause mis calculation of the angle
aX = vec1.X if math.fabs(vec1.X) > Tolerance else 0.0
aY = vec1.Y if math.fabs(vec1.Y) > Tolerance else 0.0
aZ = vec1.Z if math.fabs(vec1.Z) > Tolerance else 0.0
vec1 = Vector.Create(aX, aY, aZ)
aX = vec2.X if math.fabs(vec2.X) > Tolerance else 0.0
aY = vec2.Y if math.fabs(vec2.Y) > Tolerance else 0.0
aZ = vec2.Z if math.fabs(vec2.Z) > Tolerance else 0.0
vec2 = Vector.Create(aX, aY, aZ)
# FaceAngle = math.acos(Vector.Dot(vec1, vec2) ) * 180 / math.pi
FaceAngle = Vector.Dot(vec1, vec2)
return FaceAngle
def dividePipe(aSolid):
"divide the pipe if larger than 90 degree"
#check the surface
[Tori, sketchFaces] = checkSurface(aSolid)
if len(Tori) == 0 or len(Tori) > 2 :
print "This solid is not a pipe, or contain more than 1 pipe segments, or have unsupported surface type."
return [] # return a empty list of solid
if len (sketchFaces) != 2 :
print "This solid is not a pipe,the sketch face is strange."
return [] # return a empty list of solid
# check the angle split the solid
aSolidList = []
vec1 = sketchFaces[0].Edges[0].Shape.Geometry.Axis.Direction.UnitVector
vec2 = sketchFaces[1].Edges[0].Shape.Geometry.Axis.Direction.UnitVector
FaceAngle = calCosine(vec1, vec2)
# if FaceAngle > 0 and FaceAngle <= 90
if FaceAngle > (0 - Tolerance) and FaceAngle < (1- Tolerance):
# no need to split
aSolidList.append(aSolid)
return aSolidList
else:
## split the solid
selection = Selection.Create(aSolid)
midPlane = createMidPlane(aSolid, FaceAngle)
try:
SplitResults = SplitBody.Execute(selection, midPlane)
except:
print "Split failed!"
return []
splitBodies = SplitResults.CreatedBodies
#add current body also into the list for recursive decomposed
splitBodies.Add(aSolid)
return splitBodies # we assume the pipe is bended no larger than 180 degree
def pullPipe (sketchFace, midPlane, midPoint):
"pull the pipe based on the sketch plane"
options = ExtrudeFaceOptions()
selection = Selection.Create(sketchFace)
midDatumPlane = DatumPlane.Create(GetRootPart(),"plane",midPlane)
upToSelection = Selection.Create(midDatumPlane)
options.ExtrudeType = ExtrudeType.ForceIndependent
#note: without options.PullSymmetric = True the pipe will not pull always straightly (sometimes it creates again a torus )
#pull a symetric solid, and cut it and throw away one side.
options.PullSymmetric = True
try :
result = ExtrudeFaces.UpTo(selection, sketchFace.Edges[0].Shape.Geometry.Axis.Direction, upToSelection, midPoint, options)
except :
print "extrude failed!"
Delete.Execute(Selection.Create(midDatumPlane))
return None
aSolid = result.CreatedBodies[0]
selection = Selection.Create(aSolid)
try:
SplitResults = SplitBody.Execute(selection, sketchFace.Shape.Geometry)
except:
print "Split failed!"
return None
#clean up
Delete.Execute(Selection.Create(midDatumPlane))
splitBody = SplitResults.CreatedBodies[0]
# check the correct one, and delete another one
found = False
for iFace in aSolid.Faces:
if iFace.Shape.Geometry.IsCoincident( midPlane ):
found = True
if found:
Delete.Execute(Selection.Create(splitBody))
return aSolid
else:
Delete.Execute(Selection.Create(aSolid))
return splitBody
def tor2cyl(aSolid) :
"convert torus to two joined cylinder "
### we found out it has higher chance of success when copy the solid to a new document###
result = Copy.ToClipboard( Selection.Create(aSolid) ); ##time.sleep(0.2)
# remembering the parent
comp =aSolid.Parent.Parent
if aSolid.Parent == GetRootPart() :
comp = GetRootPart()
#create a new document to save the solid to STEP file
DocumentHelper.CreateNewDocument();
result = Paste.FromClipboard();
bSolid = Selection.GetActive().Items[0]
# do the job
[Tori, sketchFaces] = checkSurface(bSolid)
vec1 = sketchFaces[0].Edges[0].Shape.Geometry.Axis.Direction.UnitVector
vec2 = sketchFaces[1].Edges[0].Shape.Geometry.Axis.Direction.UnitVector
FaceAngle = calCosine(vec1, vec2)
midPlane = createMidPlane(bSolid, FaceAngle)
pointA = sketchFaces[0].Edges[0].Shape.Geometry.Frame.Origin
pointB = sketchFaces[1].Edges[0].Shape.Geometry.Frame.Origin
midPoint = Point.Create( (pointA.X + pointB.X)/2, (pointA.Y + pointB.Y)/2, (pointA.Z + pointB.Z)/2 )
# the solid should be hide first, otherwise the pull option is add or cut this solid
ViewHelper.SetObjectVisibility(Selection.Create(bSolid), VisibilityType.Hide, False)
#pull two sketch faces toward the midplane
#sometime one is failed, try to mirror another one
newSolid = pullPipe (sketchFaces[0], midPlane, midPoint)
if newSolid is None:
newSolid = pullPipe (sketchFaces[1], midPlane, midPoint)
if newSolid is None:
print "Not able to convert the pipe due to failure of pulling"
ViewHelper.SetObjectVisibility(Selection.Create(bSolid), VisibilityType.Show, False)
return
#mirror the one
selection = Selection.Create(newSolid)
midDatumPlane = DatumPlane.Create(GetRootPart(),"plane",midPlane)
mirrorPlane = Selection.Create(midDatumPlane)
options = MirrorOptions()
options.MergeObjects = False
options.CreateRelationships = False
result = Mirror.Execute(selection, mirrorPlane, options, None)
#clean up
Delete.Execute(Selection.Create(bSolid))
Delete.Execute(Selection.Create(midDatumPlane))
#copy all solids to the working document
Copy.ToClipboard( Selection.Create( GetRootPart().GetBodies()))
CloseWindow()
# delete the original solid
if type(comp) is Part :
ComponentHelper.SetRootActive()
else :
ComponentHelper.SetActive(comp)
Delete.Execute(Selection.GetActive())
result = Paste.FromClipboard()
##Main process
SelectSolids = Selection.GetActive().Items
for iSel in SelectSolids :
#check if solid body. Components will be filtered
if ( (type(iSel) is DesignBody) or ( hasattr(iSel, "Master") and (type(iSel.Master) is DesignBody) ) ):
#check if needed and divide the pipe
dividedPipes = dividePipe(iSel)
for iSolid in dividedPipes:
tor2cyl(iSolid)