def makeWireFromPointList(points): edges = []; for (p,q) in Util.ntuples(points,2,True): print p,q edges.append(OCCUtil.edgeFromTwoPoints(OCCUtil.pnt(p[0],p[1]),OCCUtil.pnt(q[0],q[1]))); return OCCUtil.wireFromEdges(edges);
def testSplitWire1(): """ Test split wire function. there are two main cases: wires with intersection on different edges, and a wire with a single edge split in many places """ #case 1: a single edge with lots of intersections along its length e = OCCUtil.edgeFromTwoPoints( gp.gp_Pnt(0,0,0),gp.gp_Pnt(5,0,0)); w = OCCUtil.wireFromEdges([e]); #out of order on purpose p1 = PointOnAnEdge(e,1.0,gp.gp_Pnt(1.0,0,0)); p3 = PointOnAnEdge(e,3.0,gp.gp_Pnt(3.0,0,0)); p2 = PointOnAnEdge(e,2.0,gp.gp_Pnt(2.0,0,0)); p4 = PointOnAnEdge(e,4.0,gp.gp_Pnt(4.0,0,0)); ee = splitWire(w,[p1,p3,p2,p4] ); assert len(ee) == 2; length = 0; for e in ee: ew = Wrappers.Edge(e[0]); length += ew.distanceBetweenEnds(); assert length == 2.0;
def testSplitWire2(): "intersections on different edges. one edge completely inside" e1 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(0,0,0),gp.gp_Pnt(2,0,0)); e2 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(2,0,0),gp.gp_Pnt(5,0,0)); e3 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(5,0,0),gp.gp_Pnt(6,0,0)); #trick here. after building a wire, the edges change identity. #evidently, BRepBuilder_MakeWire makes copies of the underliying edges. w = OCCUtil.wireFromEdges([e1,e2,e3]); ee = Wrappers.Wire(w).edgesAsList(); #print "Original Edges: %d %d %d " % ( ee[0].__hash__(),ee[1].__hash__(),ee[2].__hash__()); p1 = PointOnAnEdge(ee[0],1.0,gp.gp_Pnt(1.0,0,0)); p2 = PointOnAnEdge(ee[2],0.5,gp.gp_Pnt(5.0,0,0)); ee = splitWire(w,[p2,p1]); assert len(ee) == 1; length = 0; for e in ee[0]: ew = Wrappers.Edge(e); length += ew.distanceBetweenEnds(); #print "length=%0.3f" % length; assert length == 4.5;
def makeOffsetTestWire(): "creates difficult test cases for offsetting" p1 = OCCUtil.pnt(11.0,0); p2 = OCCUtil.pnt(7.0,8.0); p3 = OCCUtil.pnt(7.0,12.0); p4 = OCCUtil.pnt(17.0,22.0); p5 = OCCUtil.pnt(0.0,22.0); p6 = OCCUtil.pnt(3.0,17.0); p7 = OCCUtil.pnt(4.0,8.0 ); c1 = OCCUtil.pnt(10.0,18.5); c2 = OCCUtil.pnt(6.0,3.0); edges = []; edges.append( OCCUtil.edgeFromTwoPoints( p1, p2 )); edges.append( OCCUtil.edgeFromTwoPoints( p2, p3 )); circle = GC.GC_MakeArcOfCircle(p3, c1, p4); #circle through 3 points e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle.Value()).Edge(); edges.append(e2); edges.append( OCCUtil.edgeFromTwoPoints( p4, p5 )); edges.append( OCCUtil.edgeFromTwoPoints( p5, p6 )); edges.append( OCCUtil.edgeFromTwoPoints( p6, p7 )); circle = GC.GC_MakeArcOfCircle(p1, c2, p7 ); #circle through 3 points e3 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle.Value() ).Edge(); edges.append(e3); return OCCUtil.wireFromEdges(edges);
def offsetOnce(self,distance): bo = BRepOffsetAPI.BRepOffsetAPI_MakeOffset(); map(bo.AddWire, self.lastWires); print "%d wires to offset at step 1, distance = %0.3f" % ( len(self.lastWires),distance); bo.Perform(distance,0.0); result1 = Topo(bo.Shape()); #now offset back outwards bo2 = BRepOffsetAPI.BRepOffsetAPI_MakeOffset(); for w in result1.wires(): bo2.AddWire(w); print "Offsetting %0.3f" % ( (-0.5)*distance); bo2.Perform((-0.5)*distance, 0.0); result2 = Topo(bo2.Shape()); returnList= []; #compound result can be a compound of edges and/or wires. weird weird for c in OCCUtil.childShapes(bo2.Shape() ): #display.DisplayColoredShape(c,'BLUE') if c.ShapeType() == TopAbs.TopAbs_WIRE: returnList.append(c); #these are actually the wires we want to keep self.otherWires.append(c); elif c.ShapeType() == TopAbs.TopAbs_EDGE: w = OCCUtil.wireFromEdges([c]) returnList.append(w); self.otherWires.append(w); else: print "Warning: compound resulting from offset i am confused about-- not an edge or a wire." if len(returnList) == 0: return returnList; #do nothing further if the offset computed no curves else: print "2nd step yielded %d wires" % len(returnList) #for each original edge, compute its descendant edges #self.edgeMap will contain entries with the original edges, pointing to the generated #edges and the corresponding wire: # e1 --> [ (e2, w2 ), (e3 , w3 ) ]; for w in self.lastWires: originalWire = Topo(w); for oe in originalWire.edges(): self.edgeMap[oe.__hash__()] = []; #find generated values from first transformation generatedStep1 = OCCUtil.listFromTopToolsListOfShape(bo.Generated(oe)); for ne in generatedStep1: #find edges generated from that original edge generatedStep2 = OCCUtil.listFromTopToolsListOfShape(bo2.Generated(ne)); for ge in generatedStep2: #get wire this belongs to this returns a list but how could there ever be more than one? gwires = [] for g in result2.wires_from_edge(ge): gwires.append(g); self.edgeMap[oe.__hash__()].append ( (ge,gwires[0] )); self.lastWires = returnList; return returnList;
def makeOffsetTestWire(): "creates difficult test cases for offsetting" p1 = OCCUtil.pnt(11.0, 0) p2 = OCCUtil.pnt(7.0, 8.0) p3 = OCCUtil.pnt(7.0, 12.0) p4 = OCCUtil.pnt(17.0, 22.0) p5 = OCCUtil.pnt(0.0, 22.0) p6 = OCCUtil.pnt(3.0, 17.0) p7 = OCCUtil.pnt(4.0, 8.0) c1 = OCCUtil.pnt(10.0, 18.5) c2 = OCCUtil.pnt(6.0, 3.0) edges = [] edges.append(OCCUtil.edgeFromTwoPoints(p1, p2)) edges.append(OCCUtil.edgeFromTwoPoints(p2, p3)) circle = GC.GC_MakeArcOfCircle(p3, c1, p4) #circle through 3 points e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle.Value()).Edge() edges.append(e2) edges.append(OCCUtil.edgeFromTwoPoints(p4, p5)) edges.append(OCCUtil.edgeFromTwoPoints(p5, p6)) edges.append(OCCUtil.edgeFromTwoPoints(p6, p7)) circle = GC.GC_MakeArcOfCircle(p1, c2, p7) #circle through 3 points e3 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle.Value()).Edge() edges.append(e3) return OCCUtil.wireFromEdges(edges)
def makeWireFromPointList(points): edges = [] for (p, q) in Util.ntuples(points, 2, True): print p, q edges.append( OCCUtil.edgeFromTwoPoints(OCCUtil.pnt(p[0], p[1]), OCCUtil.pnt(q[0], q[1]))) return OCCUtil.wireFromEdges(edges)
def makeHeartWire(): "make a heart wire" e1 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(0,0,0), gp.gp_Pnt(4.0,4.0,0)); circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(2,4,0),gp.gp().DZ()),2); e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(4,4,0),gp.gp_Pnt(0,4,0)).Edge(); circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(-2,4,0),gp.gp().DZ()),2); e3 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(0,4,0),gp.gp_Pnt(-4,4,0)).Edge(); e4 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(-4,4,0), gp.gp_Pnt(0,0,0)); return OCCUtil.wireFromEdges([e1,e2,e3,e4]);
def makeHeartWire(): "make a heart wire" e1 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(0, 0, 0), gp.gp_Pnt(4.0, 4.0, 0)) circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(2, 4, 0), gp.gp().DZ()), 2) e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(4, 4, 0), gp.gp_Pnt(0, 4, 0)).Edge() circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(-2, 4, 0), gp.gp().DZ()), 2) e3 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(0, 4, 0), gp.gp_Pnt(-4, 4, 0)).Edge() e4 = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(-4, 4, 0), gp.gp_Pnt(0, 0, 0)) return OCCUtil.wireFromEdges([e1, e2, e3, e4])
def _makeHatchLines(self): """ make straight hatch lines. TODO: need to use fillAngle to rotate the lines as well. Trsf object """ xMin = self.bounds[0] - ( self.HATCH_PADDING); yMin = self.bounds[1] - ( self.HATCH_PADDING); xMax = self.bounds[2] + (self.HATCH_PADDING); yMax = self.bounds[3] + (self.HATCH_PADDING) ; wires = []; for y in Util.frange6(yMin,yMax,self.spacing): e = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(xMin,y,self.zLevel),gp.gp_Pnt(xMax,y,self.zLevel)); wires.append(OCCUtil.wireFromEdges([e])); return wires;
def _makeHatchLines(self): """ make straight hatch lines. TODO: need to use fillAngle to rotate the lines as well. Trsf object """ xMin = self.bounds[0] - (self.HATCH_PADDING) yMin = self.bounds[1] - (self.HATCH_PADDING) xMax = self.bounds[2] + (self.HATCH_PADDING) yMax = self.bounds[3] + (self.HATCH_PADDING) wires = [] for y in Util.frange6(yMin, yMax, self.spacing): e = OCCUtil.edgeFromTwoPoints(gp.gp_Pnt(xMin, y, self.zLevel), gp.gp_Pnt(xMax, y, self.zLevel)) wires.append(OCCUtil.wireFromEdges([e])) return wires
def approximatedWire(wire): "returns a bezier approximation of the specified wire as an edge" #make a parameterized approximation of the wire adaptor = BRepAdaptor.BRepAdaptor_CompCurve(wire) curve = BRepAdaptor.BRepAdaptor_HCompCurve(adaptor) curveHandle = curve.GetHandle() #approximate the curve using a tolerance approx = Approx.Approx_Curve3d(curveHandle, 0.01, GeomAbs.GeomAbs_C2, 1000, 8) if approx.IsDone() and approx.HasResult(): # have the result anApproximatedCurve = approx.Curve() builder = BRepLib.BRepLib_MakeEdge(anApproximatedCurve) e = builder.Edge() return OCCUtil.wireFromEdges([e])
def offsetOnceSimple(self, distance): bo = BRepOffsetAPI.BRepOffsetAPI_MakeOffset() map(bo.AddWire, self.lastWires) print "%d wires to offset at step 1, distance = %0.3f" % (len( self.lastWires), distance) bo.Perform(distance * (0.5), 0.0) result1 = Topo(bo.Shape()) returnList = [] #compound result can be a compound of edges and/or wires. weird weird for c in OCCUtil.childShapes(bo.Shape()): display.DisplayColoredShape(c, 'BLUE') if c.ShapeType() == TopAbs.TopAbs_WIRE: returnList.append(c) #these are actually the wires we want to keep elif c.ShapeType() == TopAbs.TopAbs_EDGE: w = OCCUtil.wireFromEdges([c]) returnList.append(w) else: print "Warning: compound resulting from offset i am confused about-- not an edge or a wire." #for each original edge, compute its descendant edges #self.edgeMap will contain entries with the original edges, pointing to the generated #edges and the corresponding wire: # e1 --> [ (e2, w2 ), (e3 , w3 ) ]; for w in self.lastWires: originalWire = Topo(w) for oe in originalWire.edges(): self.edgeMap[oe.__hash__()] = [] #find generated values from first transformation generatedStep1 = OCCUtil.listFromTopToolsListOfShape( bo.Generated(oe)) for ne in generatedStep1: #get wire this belongs to this returns a list but how could there ever be more than one? gwires = [] for g in result1.wires_from_edge(ne): gwires.append(g) self.edgeMap[oe.__hash__()].append((ne, gwires[0])) self.lastWires = returnList self.otherWires.extend(returnList) return returnList
def makePeriodic(self, center, positive=1.0): """ center is the center of the first hex, as an (x,y,z) tuple. positive is 1 for the upper portion, -1 for the lower portion makes the upper part of a periodic hex pattern. Note that the upper and lower flats are adjusted for line width, so that they can be stacked and allow double-drawing of the horizontal flats. this offset is controlled by the linewidth parameter. the points are numbered below (2) (3) /-----\ ____/ + \_____ (0) (1) (4) (5) """ cX = center[0] cY = center[1] cZ = center[2] (XA, YA) = self.lineWidthAdjust() baselineY = (cY + YA) * positive topY = (cY + (self.width / 2.0 - YA)) * positive p0 = gp.gp_Pnt(cX - self.cartesianSpacing()[0], baselineY, cZ) p1 = gp.gp_Pnt(cX - self.centerToCorner() + XA, baselineY, cZ) p2 = gp.gp_Pnt(cX - self.halfAflat() - XA, topY, cZ) p3 = gp.gp_Pnt(cX + self.halfAflat() + XA, topY, cZ) p4 = gp.gp_Pnt(cX + self.centerToCorner() - XA, baselineY, cZ) p5 = gp.gp_Pnt(cX + self.cartesianSpacing()[0], baselineY, cZ) #make the edges and the wires edges = [] edges.append(OCCUtil.edgeFromTwoPoints(p0, p1)) edges.append(OCCUtil.edgeFromTwoPoints(p1, p2)) edges.append(OCCUtil.edgeFromTwoPoints(p2, p3)) edges.append(OCCUtil.edgeFromTwoPoints(p3, p4)) edges.append(OCCUtil.edgeFromTwoPoints(p4, p5)) wire = OCCUtil.wireFromEdges(edges) return wire
def makeCircleWire2(): circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(0,2,0),gp.gp().DZ()),.75); e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(0,1.25,0),gp.gp_Pnt(0,1.25,0)).Edge(); return OCCUtil.wireFromEdges([e2]);
def followWires(self, startNearPoint, pathWidth): outputWires = self.outputWires #list wires we must draw. we want to connect them in a sane order #make sure to start at a point far outside the face so we start outside! toDraw = self.originalWires + self.otherWires #find starting vertex and wire #must start on outer wire only lastPoint = startNearPoint initialPoint = OCCUtil.nearestVertex(self.originalWires, startNearPoint) lastVector = gp.gp_Vec((gp.gp_Pnt(0, 0, 0)), startNearPoint) #assume initial vector is sideways for now. At the beginning of a layer, the start vector is not relevant, #so anythign will work i think. here we assume the first vector is from the origin if initialPoint is None: raise Exception( "Cannot find initial starting point on outer wire!") (currentWire, currentVertex, currentPoint, distance) = OCCUtil.nearestVertex(self.originalWires, startNearPoint) while len(toDraw) > 0: currentPoint = brepTool.Pnt(currentVertex) toDraw.remove(currentWire) #trim the wire at this point #TODO: simplify syntax for this! jrequest = WireJoiner.JointRequest(lastPoint, lastVector, pathWidth, currentWire) wj = WireJoiner.WireJoiner(jrequest, pathWidth * (2.0)) solution = wj.build() trimmedWire = solution.wire trimmedEdge = solution.trimmedEdge trimmedPoint = solution.trimmedPoint trimmedVec = solution.trimmedVec joinEdge = OCCUtil.edgeFromTwoPoints(lastPoint, currentPoint) joinWire = OCCUtil.wireFromEdges([joinEdge]) outputWires.append(joinWire) if solution.isJoint: #display.DisplayColoredShape(joinWire,'RED'); pass else: #display.DisplayColoredShape(joinWire,'YELLOW'); pass outputWires.append(trimmedWire) #display.DisplayColoredShape(trimmedWire,'GREEN'); #look for another edge which was created by the trimmedEdge. this is where we should search for a connecting point. (nextVertex, nextEdge, nextWire) = self.getNextEdge(trimmedEdge, trimmedPoint) if nextVertex: #connect edges and chain to the this wire currentVertex = nextVertex currentWire = nextWire else: #no next edge found. find next closest wire to last point, but don't connect it #here we should assume the next move is a rapid and not connect it. result = OCCUtil.nearestVertex(toDraw, currentPoint) if result: (currentWire, currentVertex, point, distance) = result lastPoint = trimmedPoint else: #couldnt find next vertex either -- not sure this should ever happen? #TODO this is a total hack, need to fix the loop to avoid this extra check if len(toDraw) > 0: raise Exception( "Could not find a next vertex, but there are wires left. how did this happen?" ) else: break lastPoint = trimmedPoint lastVector = trimmedVec
def followWires (self,startNearPoint,pathWidth): outputWires = self.outputWires; #list wires we must draw. we want to connect them in a sane order #make sure to start at a point far outside the face so we start outside! toDraw = self.originalWires + self.otherWires; #find starting vertex and wire #must start on outer wire only lastPoint = startNearPoint; initialPoint = OCCUtil.nearestVertex(self.originalWires,startNearPoint); lastVector = gp.gp_Vec((gp.gp_Pnt(0,0,0)), startNearPoint); #assume initial vector is sideways for now. At the beginning of a layer, the start vector is not relevant, #so anythign will work i think. here we assume the first vector is from the origin if initialPoint is None: raise Exception ("Cannot find initial starting point on outer wire!"); (currentWire,currentVertex,currentPoint,distance) = OCCUtil.nearestVertex(self.originalWires,startNearPoint); while len(toDraw) > 0: currentPoint = brepTool.Pnt(currentVertex); toDraw.remove(currentWire); #trim the wire at this point #TODO: simplify syntax for this! jrequest = WireJoiner.JointRequest( lastPoint,lastVector,pathWidth,currentWire); wj = WireJoiner.WireJoiner(jrequest,pathWidth*(2.0) ); solution = wj.build(); trimmedWire = solution.wire; trimmedEdge = solution.trimmedEdge; trimmedPoint = solution.trimmedPoint; trimmedVec = solution.trimmedVec; joinEdge = OCCUtil.edgeFromTwoPoints(lastPoint,currentPoint); joinWire = OCCUtil.wireFromEdges([joinEdge]); outputWires.append(joinWire); if solution.isJoint: #display.DisplayColoredShape(joinWire,'RED'); pass; else: #display.DisplayColoredShape(joinWire,'YELLOW'); pass; outputWires.append(trimmedWire); #display.DisplayColoredShape(trimmedWire,'GREEN'); #look for another edge which was created by the trimmedEdge. this is where we should search for a connecting point. (nextVertex,nextEdge,nextWire) = self.getNextEdge(trimmedEdge, trimmedPoint); if nextVertex: #connect edges and chain to the this wire currentVertex = nextVertex; currentWire = nextWire; else: #no next edge found. find next closest wire to last point, but don't connect it #here we should assume the next move is a rapid and not connect it. result = OCCUtil.nearestVertex(toDraw, currentPoint); if result: (currentWire,currentVertex,point, distance) = result; lastPoint = trimmedPoint; else: #couldnt find next vertex either -- not sure this should ever happen? #TODO this is a total hack, need to fix the loop to avoid this extra check if len(toDraw) > 0: raise Exception("Could not find a next vertex, but there are wires left. how did this happen?") else: break; lastPoint = trimmedPoint; lastVector = trimmedVec;
def makeCircleWire2(): circle = gp.gp_Circ(gp.gp_Ax2(gp.gp_Pnt(0, 2, 0), gp.gp().DZ()), .75) e2 = BRepBuilderAPI.BRepBuilderAPI_MakeEdge(circle, gp.gp_Pnt(0, 1.25, 0), gp.gp_Pnt(0, 1.25, 0)).Edge() return OCCUtil.wireFromEdges([e2])