def LoadFile(self,filename): extension = os.path.basename(filename).split(".").pop().lower() start_time = time.time() if extension =="step" or extension == "stp": from OCC.Utils.DataExchange.STEP import STEPImporter stepReader = STEPImporter(str(filename)) stepReader.read_file() shape = stepReader.get_shapes() elif extension == "stl": from OCC import TopoDS, StlAPI shape = TopoDS.TopoDS_Shape() stl_reader = StlAPI.StlAPI_Reader() stl_reader.Read(shape,str(filename)) elif extension =="iges" or extension =="igs": from OCC import IGESControl i = IGESControl.IGESControl_Controller() i.Init() iges_reader = IGESControl.IGESControl_Reader() iges_reader.ReadFile(str(filename)) iges_reader.TransferRoots() shape = iges_reader.OneShape() elif extension == "brep": from OCC import TopoDS, BRep, BRepTools shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() BRepTools.BRepTools().Read(shape,str(filename),builder) else: return True self.canva._display.DisplayShape(shape) end_time = time.time() self.SetTitle("CAD Viewer - pythonOCC %s:%s"%(VERSION,filename)) duration = end_time-start_time print "%s STEP file loaded and displayed in %f seconds."%(filename,duration)
def file_to_shape(pth): '''get a Shape from an .iges or .step file''' assert os.path.isfile(pth), '%s is not a valid directory' % (pth) ext = os.path.splitext(pth)[1] print 'ext', ext assert ext in ['.iges', '.igs', '.stp', '.step', '.brep', '.stl'], '%s is not an readable format' % (ext) if ext in ['.iges', '.igs']: __i = IGESControl_Controller() __i.Init() reader = IGESControl_Reader() elif ext in ['.step', '.stp']: reader = STEPControl_Reader() elif ext == '.brep': from OCC import TopoDS, BRep, BRepTools shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() BRepTools.BRepTools().Read(shape, pth, builder) return shape elif ext == '.stl': from OCC import TopoDS, StlAPI shape = TopoDS.TopoDS_Shape() stl_reader = StlAPI.StlAPI_Reader() stl_reader.Read(shape, pth) return shape reader.ReadFile(pth) n_translated = reader.TransferRoots() shape = reader.OneShape() del reader return shape
def splitEdge(edge, p): "splits an edge at the supplied parameter, returns the new edges" "separationDist is the distance of the break between the two edges" (handleCurve, pstart, pend) = BRep.BRep_Tool().Curve(edge) return (edgeFromTwoPointsOnCurve(handleCurve, pstart, p), edgeFromTwoPointsOnCurve(handleCurve, p, pend))
def LoadFile(self, filename): extension = os.path.basename(filename).split(".").pop().lower() start_time = time.time() if extension =="step" or extension == "stp": stepReader = STEPControl.STEPControl_Reader() stepReader.ReadFile(str(filename)) numTranslated = stepReader.TransferRoots() shape = stepReader.OneShape() elif extension == "stl": shape = TopoDS.TopoDS_Shape() stl_reader = StlAPI.StlAPI_Reader() stl_reader.Read(shape,str(filename)) elif extension =="iges" or extension =="igs": i = IGESControl.IGESControl_Controller() i.Init() iges_reader = IGESControl.IGESControl_Reader() iges_reader.ReadFile(str(filename)) iges_reader.TransferRoots() shape = iges_reader.OneShape() elif extension == "brep": shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() BRepTools.BRepTools().Read(shape,str(filename),builder) else: return True self.canva._3dDisplay.EraseAll() self.canva._3dDisplay.DisplayShape(shape) wx.SafeYield() self.canva._3dDisplay.View_Iso() self.canva._3dDisplay.FitAll() end_time = time.time() self.SetTitle("pythonOCC Interactive Console %s:%s"%(VERSION,filename)) duration = end_time-start_time print "%s STEP file loaded and displayed in %f seconds."%(filename,duration)
def make_compound(listOfShapes): aRes = TopoDS.TopoDS_Compound() aBuilder = BRep.BRep_Builder() aBuilder.MakeCompound(aRes) for item in listOfShapes: aBuilder.Add(aRes, item) aBuilder._InputShapes = listOfShapes aRes._builder = aBuilder return aRes
def display_edges(): comp = TopoDS_Compound() builder = BRep.BRep_Builder() builder.MakeCompound(comp) for e in edges: #contour = BRepAlgo_Fuse(contour, e).Shape() builder.Add(comp, e) displays[curr_tab].DisplayColoredShape(comp, 'BLACK', False)
def compound(self): """ Create and returns a compound from the _shapes list""" # Create a compound compound = TopoDS.TopoDS_Compound() brep_builder = BRep.BRep_Builder() brep_builder.MakeCompound(compound) # Populate the compound for shape in self._shapes: brep_builder.Add(compound, shape) return compound
def TestShortenEdge(): #test trimming and such e1 = edgeFromTwoPoints(gp.gp_Pnt(0, 0, 0), gp.gp_Pnt(1, 1, 0)) display.DisplayColoredShape(e1, 'BLUE') #just for testing, get the parameters of the new edge. (handleCurve, p1, p2) = BRep.BRep_Tool().Curve(e1) p = (p1 + p2) / 2 display.DisplayColoredShape(splitEdge(e1, p, 0.1), 'RED') #display.DisplayColoredShape( shortenEdge(e1,p1,0.1), 'WHITE'); display.DisplayColoredShape(shortenEdge(e1, p2, 0.1), 'WHITE')
def get2dCurveFrom3dEdge(edge): """ returns a curve given an edge. here, we want to get a curve from a 3dEdge, since with this approach we'll only be getting existing curves from a 3d source """ #first, convert the curve to a 2d curve btool = BRep.BRep_Tool() handleCurve = btool.Curve(edge)[0] return GeomAPI.GeomAPI().To2d(handleCurve, gp.gp_Pln(gp.gp_Pnt(0, 0, 0), gp.gp().DZ()))
def get_vertices(shape, length): bt = BRep.BRep_Tool() t = Topo(shape) vertices = t.vertices() vert = [] for vertex in vertices: vert.append([ correctLengt(bt.Pnt(vertex).Coord()[0], length, None), correctLengt(bt.Pnt(vertex).Coord()[1], length, None), correctLengt(bt.Pnt(vertex).Coord()[2], length, None) ]) return vert
def fixShape(shape): """ fixes a shape """ log.info("Fixing holes and degenerated Meshes...") sf = ShapeFix.ShapeFix_Shape(shape) sf.SetMaxTolerance(TOLERANCE) msgRegistrator = ShapeExtend.ShapeExtend_MsgRegistrator() sf.SetMsgRegistrator(msgRegistrator.GetHandle()) sf.Perform() log.info("ShapeFix Complete.") for i in range(0, 18): log.info("ShapeFix Status %d --> %s" % (i, sf.Status(i))) fixedShape = sf.Shape() #fixedShape = shape; return fixedShape #if the resulting shape is a compound, we need to convert #each shell to a solid, and then re-create a new compound of solids if fixedShape.ShapeType() == TopAbs.TopAbs_COMPOUND: log.warn("Shape is a compound. Creating solids for each shell.") builder = BRep.BRep_Builder() newCompound = TopoDS.TopoDS_Compound() #newCompound = TopoDS.TopoDS_CompSolid(); builder.MakeCompound(newCompound) #builder.MakeCompSolid(newCompound); for shell in Topo(fixedShape).shells(): solidBuilder = BRepBuilderAPI.BRepBuilderAPI_MakeSolid(shell) solid = solidBuilder.Solid() sa = SolidAnalyzer(solid) print sa.friendlyDimensions() builder.Add(newCompound, solid) #time.sleep(4); #Topology.dumpTopology(newCompound); return newCompound #return temporarily after the first one else: log.info("Making Solid from the Shell...") solidBuilder = BRepBuilderAPI.BRepBuilderAPI_MakeSolid( ts.Shell(fixedShape)) return solidBuilder.Solid()
def shape_to_file(shape, pth, filename, format='iges'): '''write a Shape to a .iges .brep .stl or .step file''' _pth = os.path.join(pth, filename) assert not os.path.isdir(_pth), 'wrong path, filename' _file = "%s.%s" % (_pth, format) _formats = ['iges', 'igs', 'step', 'stp', 'brep', 'stl'] assert format in _formats, '%s is not a readable format, should be one of %s ' % ( format, _formats) if format in ['iges', 'igs']: i = IGESControl_Controller() i.Init() writer = IGESControl_Writer() writer.AddShape(shape) writer.Write(_file) return _file elif format in ['step', 'stp']: i = STEPControl_Controller() i.Init() writer = STEPControl_Writer() writer.Transfer(shape, STEPControl_AsIs) writer.Write(_file) return _file elif format == 'brep': from OCC import TopoDS, BRep, BRepTools #shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() BRepTools.BRepTools().Write(shape, _file) elif format == 'stl': from OCC import TopoDS, StlAPI #shape = TopoDS.TopoDS_Shape() stl_reader = StlAPI.StlAPI_Writer() stl_reader.Read(shape, _file) else: raise TypeError( 'format should be one of [iges,igs], [step,stp], brep, stl\ngot %s' % (format))
def __init__(self, edge): self.edge = edge hc = BRep.BRep_Tool().Curve(edge) self.curve = GeomAdaptor.GeomAdaptor_Curve(hc[0]) self.handleCurve = hc[0] self.firstParameter = hc[1] self.lastParameter = hc[2] p1 = self.curve.Value(self.firstParameter) p2 = self.curve.Value(self.lastParameter) #compute the first and last points, which are very commonly used if edge.Orientation() == TopAbs.TopAbs_FORWARD: self.reversed = False self.firstPoint = p1 self.lastPoint = p2 else: self.reversed = True self.firstPoint = p2 self.lastPoint = p1
def drillWithHolesFaster(shape): "returns a shape with a bunch of spheres removed from it" box = Bnd.Bnd_Box() b = BRepBndLib.BRepBndLib() b.Add(shape, box) (xMin, yMin, zMin, xMax, yMax, zMax) = box.Get() d = 0.05 * ((xMax - xMin)) di = 3.0 * d vec = gp.gp_Vec(gp.gp_Pnt(0, 0, 0), gp.gp_Pnt(0, 0, d)) cp = None compound = TopoDS.TopoDS_Compound() builder = BRep.BRep_Builder() builder.MakeCompound(compound) #drill holes in a rectangular grid for x in frange6(xMin, xMax, di): for y in frange6(yMin, yMax, di): for z in frange6(zMin, zMax, di): #make a sphere center = gp.gp_Pnt(x, y, z) hole = BRepPrimAPI.BRepPrimAPI_MakeSphere(center, d).Shape() #lets see if a square hole is faster! #w = squareWire(center,d ); #hb = BRepPrimAPI.BRepPrimAPI_MakePrism(w,vec,False,True); #hb.Build(); #hole = hb.Shape(); builder.Add(compound, hole) display.DisplayShape(compound) q = time.clock() cut = BRepAlgoAPI.BRepAlgoAPI_Cut(shape, compound) if cut.ErrorStatus() == 0: print "Cut Took %0.3f sec." % (time.clock() - q) return cut.Shape() else: print "Error Cutting: %d" % cut.ErrorStatus() return shape
def compound(self): """ Create and returns a compound from the _shapes list Returns ------- TopoDS.TopoDS_Compound Notes ----- Importing an iges box results in: 0 solid 0 shell 6 faces 24 edges """ # Create a compound compound = TopoDS.TopoDS_Compound() brep_builder = BRep.BRep_Builder() brep_builder.MakeCompound(compound) # Populate the compound for shape in self._shapes: brep_builder.Add(compound, shape) return compound
import TestWires import bresenham import hexagonlib2d from OCC.Display.SimpleGui import * display, start_display, add_menu, add_function_to_menu = init_display() import pixMapTileTest import breshamtest as bres #import bresenham as bres import numpy as np import networkx as nx import hexagonlib import hexagonlib2d brt = BRep.BRep_Tool() def tP(x, y): "convert x-y tuple to a gp pnt" return gp.gp_Pnt2d(x, y) def edgeFromTwoPoints(p1, p2): "make a linear edge from two 2d points. p1 and p2 are simple (x,y) tuples " builder = BRepBuilderAPI.BRepBuilderAPI_MakeEdge2d(tP(p1[0], p1[1]), tP(p2[0], p2[1])) builder.Build() if builder.IsDone(): return builder.Edge() else:
import time,os,sys,string; import itertools # OCC imports from OCC import BRep,gp,GeomAbs,GeomAPI,GCPnts,TopoDS,BRepTools,GeomAdaptor,TopAbs,TopTools,TopExp,Approx,BRepLib,Bnd,BRepBndLib from OCC import BRepGProp,BRepLProp, BRepBuilderAPI,BRepPrimAPI,GeomAdaptor,GeomAbs,BRepClass,GCPnts,BRepBuilderAPI,BRepOffsetAPI,BRepAdaptor from OCC import BRepExtrema,TColgp from OCC import ShapeAnalysis from OCC.Utils import Topo from OCC import ShapeFix,ShapeExtend # project files import TestObjects import OCCUtil brepTool = BRep.BRep_Tool(); """ Smart Wire Builder.. accepts edges, and then uses WireOrder to connect them together into the best possible edges """ class WireBuilder: def __init__(self): self.edges = []; self.fixer = ShapeFix.ShapeFix_Wire(); self.wireData = ShapeExtend.ShapeExtend_WireData(); def add(self,edge):
from OCC.Display.SimpleGui import * from OCC import BRep from OCC.BRepTools import * from OCC import TopoDS from OCC.Message import Message_PrinterOStream import sys fileName = 'input.brp' if (len(sys.argv) > 1): fileName = sys.argv[1] brep_instance = BRepTools() shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() printrerStream = Message_PrinterOStream() s = printrerStream.GetStream() brep_instance.Read(shape, str(fileName), builder)
def read_file(self): r"""Read the BREP file and stores the result in a TopoDS_Shape""" shape = TopoDS.TopoDS_Shape() builder = BRep.BRep_Builder() BRepTools.breptools_Read(shape, self._filename, builder) self._shape = shape
cyl = Geom.Geom_CylindricalSurface(gp.gp_Ax3(), c_rad) h_cyl = Geom.Handle_Geom_CylindricalSurface(cyl) intersect = GeomAPI.GeomAPI_IntSS(h_sph, h_cyl, 1e-7) edges = (BRepBuilderAPI.BRepBuilderAPI_MakeEdge(intersect.Line(i)) for i in xrange(1, intersect.NbLines() + 1)) wires = [BRepBuilderAPI.BRepBuilderAPI_MakeWire(e.Edge()) for e in edges] g_sph = gp.gp_Sphere(gp.gp_Ax3(), radius) faces = [BRepBuilderAPI.BRepBuilderAPI_MakeFace(w.Wire()) for w in wires] cyl_face = BRepBuilderAPI.BRepBuilderAPI_MakeFace(h_cyl) #cyl_face.Add(wires[0].Wire()) #cyl_face.Add(wires[1].Wire()) #shell = TopoDS.TopoDS_Shell() shell_builder = BRep.BRep_Builder() #shell_builder.MakeShell(shell) #shell_builder.Add(shell, cyl_face.Shape()) #for f in faces: # shell_builder.Add(shell, f.Shape()) #sewing = BRepBuilderAPI.BRepBuilderAPI_Sewing() #sewing.Add(shell) #sewing.Perform() #shell = BRepBuilderAPI.BRepBuilderAPI_MakeShell(h_cyl) view(cyl_face.Shape())
def startBottle(startOnly=True): # minus the neck fillet, shelling & threads partName = "Bottle-start" # The points we'll use to create the profile of the bottle's body aPnt1 = gp_Pnt(-width / 2.0, 0, 0) aPnt2 = gp_Pnt(-width / 2.0, -thickness / 4.0, 0) aPnt3 = gp_Pnt(0, -thickness / 2.0, 0) aPnt4 = gp_Pnt(width / 2.0, -thickness / 4.0, 0) aPnt5 = gp_Pnt(width / 2.0, 0, 0) aArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4) aSegment1 = GC_MakeSegment(aPnt1, aPnt2) aSegment2 = GC_MakeSegment(aPnt4, aPnt5) # Could also construct the line edges directly using the points instead of the resulting line aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) # Create a wire out of the edges aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge(), aEdge2.Edge(), aEdge3.Edge()) # Quick way to specify the X axis xAxis = gp_OX() # Set up the mirror aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) # Apply the mirror transformation aBRespTrsf = BRepBuilderAPI_Transform(aWire.Wire(), aTrsf) # Get the mirrored shape back out of the transformation and convert back to a wire aMirroredShape = aBRespTrsf.Shape() # A wire instead of a generic shape now aMirroredWire = topods.Wire(aMirroredShape) # Combine the two constituent wires mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # The face that we'll sweep to make the prism myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) # We want to sweep the face along the Z axis to the height aPrismVec = gp_Vec(0, 0, height) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face(), aPrismVec) # Add fillets to all edges through the explorer mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) anEdgeExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_EDGE) while anEdgeExplorer.More(): anEdge = topods.Edge(anEdgeExplorer.Current()) mkFillet.Add(thickness / 12.0, anEdge) anEdgeExplorer.Next() myBody = mkFillet.Shape() # Create the neck of the bottle neckLocation = gp_Pnt(0, 0, height) neckAxis = gp_DZ() neckAx2 = gp_Ax2(neckLocation, neckAxis) myNeckRadius = thickness / 4.0 myNeckHeight = height / 10.0 mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight) myBody = BRepAlgoAPI_Fuse(myBody, mkCylinder.Shape()) if startOnly: # quit here uid = win.getNewPartUID(myBody.Shape(), name=partName) win.redraw() return partName = "Bottle-complete" # Our goal is to find the highest Z face and remove it faceToRemove = None zMax = -1 # We have to work our way through all the faces to find the highest Z face aFaceExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_FACE) while aFaceExplorer.More(): aFace = topods.Face(aFaceExplorer.Current()) if face_is_plane(aFace): aPlane = geom_plane_from_face(aFace) # We want the highest Z face, so compare this to the previous faces aPnt = aPlane.Location() aZ = aPnt.Z() if aZ > zMax: zMax = aZ faceToRemove = aFace aFaceExplorer.Next() facesToRemove = TopTools_ListOfShape() facesToRemove.Append(faceToRemove) myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape(), facesToRemove, -thickness / 50.0, 0.001) # Set up our surfaces for the threading on the neck neckAx2_Ax3 = gp_Ax3(neckLocation, gp_DZ()) aCyl1 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 0.99) aCyl2 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 1.05) # Set up the curves for the threads on the bottle's neck aPnt = gp_Pnt2d(2.0 * math.pi, myNeckHeight / 2.0) aDir = gp_Dir2d(2.0 * math.pi, myNeckHeight / 4.0) anAx2d = gp_Ax2d(aPnt, aDir) aMajor = 2.0 * math.pi aMinor = myNeckHeight / 10.0 anEllipse1 = Geom2d_Ellipse(anAx2d, aMajor, aMinor) anEllipse2 = Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4.0) anArc1 = Geom2d_TrimmedCurve(Handle_Geom2d_Ellipse(anEllipse1), 0, math.pi) anArc2 = Geom2d_TrimmedCurve(Handle_Geom2d_Ellipse(anEllipse2), 0, math.pi) anEllipsePnt1 = anEllipse1.Value(0) anEllipsePnt2 = anEllipse1.Value(math.pi) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2) # Build edges and wires for threading anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(Handle_Geom2d_Curve(anArc1), Handle_Geom_Surface(aCyl1)) anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value(), Handle_Geom_Surface(aCyl1)) anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(Handle_Geom2d_Curve(anArc2), Handle_Geom_Surface(aCyl2)) anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value(), Handle_Geom_Surface(aCyl2)) threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1.Edge(), anEdge2OnSurf1.Edge()) threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2.Edge(), anEdge2OnSurf2.Edge()) # Compute the 3D representations of the edges/wires BRepLib.breplib.BuildCurves3d(threadingWire1.Shape()) BRepLib.breplib.BuildCurves3d(threadingWire2.Shape()) # Create the surfaces of the threading aTool = BRepOffsetAPI_ThruSections(True) aTool.AddWire(threadingWire1.Wire()) aTool.AddWire(threadingWire2.Wire()) aTool.CheckCompatibility(False) myThreading = aTool.Shape() # Build the resulting compound aRes = TopoDS_Compound() aBuilder = BRep.BRep_Builder() aBuilder.MakeCompound(aRes) aBuilder.Add(aRes, myBody.Shape()) aBuilder.Add(aRes, myThreading) uid = win.getNewPartUID(aRes, name=partName) win.redraw()
## X change naming of slice() to something else ## X recognize .stp in addition to .step ## X install guide ## X remove unneed dumpTopology and shapeDescription ## add 2d per-slice view on select of slice ## X add ability to easily select slice thickness ## add separate display for original object and slices ## X sew faces from crappy stl files into single faces somehow ## X remove reference to profile import ##### #utility class instances #available to all methods ##### brt = BRepTools.BRepTools() btool = BRep.BRep_Tool() ts = TopoDS.TopoDS() topexp = TopExp.TopExp() texp = TopExp.TopExp_Explorer() """ Utility class to provide timing information """ class Timer: def __init__(self): self.startTime = time.time() self.startAscTime = time.asctime() def start(self): return self.startTime
def hatch(self): """take the a slice and compute hatches computing the intersections of wires is very expensive, so it is important to do this as efficently as possible. Inputs: a set of boundary wires that define a face, a set of filling wires that cover a bounding box around the face. Outputs: trim covering wires/edges by the boundaries, trim boundaries by intersections with wires optimizations so far: * use active wire table to detect when to stop computing intersections with wires. each boundary must be activated before computation stops, and a boundary is finished after intersections have been found, and then stop occurring. More optimization can be used by Bnd_BoundSortBox-- which would compare all of the bounding boxes at once in c++, but with more glue code. """ q = time.clock() hatchWires = self._makeHatchLines() numCompares = 0 bbuilder = BRep.BRep_Builder() comp = TopoDS.TopoDS_Compound() bbuilder.MakeCompound(comp) #print "Time to Make hatch Lines: %0.3f" % ( time.clock() - q ) for b in self.boundaryWires: bbuilder.Add(comp, b) self.graphBuilder.addBoundaryWire(b) #print "There are %d boundary wires, %d hatch wires" % ( len(self.boundaryWires),len(hatchWires) ) #intersect each line with each boundary brp = BRepExtrema.BRepExtrema_DistShapeShape() brp.LoadS1(comp) for hatchLine in hatchWires: interSections = [] #list of intersections for just this single hatch line closePoints = [] #extrema that are not intersectionsf or this single hatch line brp.LoadS2(hatchLine) numCompares += 1 result = brp.Perform() """ tricky thing: for a given hatch line ( whether a line or a string of hexes ), we want to check for both intersections and close points that would result in overdrawing. if the line has zero intersections, then it is not in play, and should not be considered. if the line has at least one intersection, then it is in play, and extrema that are not intersections should also be included for later processing. """ if result and brp.Value( ) < 0.050: #if < tolerance we have an intersection. if < filament width we have a close sitation #print "intersection found, distance = %0.6f" % brp.Value() #TODO need to handle the somewhat unusual cases that the intersection is #on a vertex for k in range(1, brp.NbSolution() + 1): if brp.Value( ) < 0.001: #there is at least one intersection on this wire. there may also be extrema #print "spot on match" #try: #make the node #quite complex depending on where exactly the intersection is. if brp.SupportTypeShape1( k) == BRepExtrema.BRepExtrema_IsOnEdge: #well this sux-- have to check to ensure that the edge is not a local #minimum or maximum also. if OCCUtil.isEdgeLocalMinimum( OCCUtil.cast(brp.SupportOnShape1(k)), brp.ParOnEdgeS1(k), brp.PointOnShape1(k)): print "Warning: edge appears to be a local min/max. Is it a tangent?" continue else: #self.boundaryIntersectionsByEdge = {} #boundary intersections, hashed by edges self.graphBuilder.addPointOnBoundaryEdge( OCCUtil.cast(brp.SupportOnShape1(k)), brp.ParOnEdgeS1(k), brp.PointOnShape1(k)) if brp.SupportTypeShape2( k) == BRepExtrema.BRepExtrema_IsOnEdge: if brp.SupportTypeShape1( k) == BRepExtrema.BRepExtrema_IsVertex: #the intersection is on a vertex of the boundary. vertex = OCCUtil.cast(brp.SupportOnShape1(k)) #otherwise, vertex was not a local minimum, or was on an edge poe = eg.PointOnAnEdge( OCCUtil.cast(brp.SupportOnShape2(k)), brp.ParOnEdgeS2(k), brp.PointOnShape2(k)) interSections.append(poe) elif brp.SupportTypeShape2( k) == BRepExtrema.BRepExtrema_IsVertex: #how on earth to handle this one? #this actually means that a vertex can also have an infill node attached to it! #for right now let's just ignore it. print "WARNING: intersection on vertex of hatch line!" pass else: raise ValueError( "I dont know how to handle this kind of intersection" ) else: #brp.Value is between 0.001 and 0.05 #print "intersection is close"; #we know this is a place where the boundary is close to a fill contour. #our goal is to eventually remove it from the list. Support1 is the boundary. #print "found extremum close but not intersecting, distance = %0.3f" % ( brp.Value() ) if brp.SupportTypeShape1( k) == BRepExtrema.BRepExtrema_IsOnEdge: poeBound = eg.PointOnAnEdge( brp.SupportOnShape1(k), brp.ParOnEdgeS1(k), brp.PointOnShape1(k)) closePoints.append( (poeBound, 'EDGE', brp.SupportOnShape2(k))) elif brp.SupportTypeShape2( k) == BRepExtrema.BRepExtrema_IsVertex: #here a vertex is closest to a fill line. poeBound = eg.PointOnAnEdge( brp.SupportOnShape1(k), 0, brp.PointOnShape1(k)) closePoints.append( (poeBound, 'VERTEX', brp.SupportOnShape2(k))) if len(interSections) % 2 == 1: print "Detected Odd Number of intersection points. This is ignored for now." continue if len(interSections) == 0: #print "Hatch has no intersections-- discarding"; continue #at this point we have all the intersections for this hatch line. #we also know we have at least one intersection. if len(closePoints) > 0: #there were extrema ( points where this hatch is close to a boundary but doesnt intersect. #we do this here instead of inline because we have to avoid hatch lines that are close, but do not actually #intersect a wire. ( ie, they are 'just outside' of the boundary ) for cp in closePoints: self.graphBuilder.addPointsTooClose(cp[0], cp[1]) #display.DisplayShape(cp[0].edge ); #display.DisplayShape(cp[2] ); #add the edges 'inside' the shape to the graph #print "Splitting wire by %d intersection points" % len(interSections ) edgesInside = [] edgesInside = eg.splitWire(hatchLine, interSections) #returned value is a list of lists. each entry is a chain of edges for e in edgesInside: self.graphBuilder.addFillEdges(e) #test to see if we can break out of the loop. #we can stop if we've hit each boundary at least once #if len(interSections) == 0 and (len(boundariesFound) == len(self.boundaryWires)): # continueHatching = False; print "%d Total Intersections computed." % (numCompares) self.graphBuilder.buildGraph()
def trimmedEdge(edge, p1, p2): "returns a new edge that is a trimmed version of the underlying one" hc = BRep.BRep_Tool().Curve(edge) return edgeFromTwoPointsOnCurve(hc[0], p1, p2)