def onChanged(self,obj,prop): if hasattr(obj,"IfcRole"): role = obj.IfcRole elif hasattr(obj,"Role"): role = obj.Role else: role = None self.hideSubobjects(obj,prop) if prop in ["Shape","ResetNodes","NodesOffset"]: # ResetNodes is not a property but it allows us to use this function to force reset the nodes nodes = None extdata = self.getExtrusionData(obj) if extdata: nodes = extdata[0] nodes.Placement = nodes.Placement.multiply(extdata[2]) if role not in ["Slab"]: if obj.Tool: nodes = obj.Tool.Shape elif extdata[1].Length > 0: if hasattr(nodes,"CenterOfMass"): import Part nodes = Part.LineSegment(nodes.CenterOfMass,nodes.CenterOfMass.add(extdata[1])).toShape() offset = FreeCAD.Vector() if hasattr(obj,"NodesOffset"): offset = FreeCAD.Vector(0,0,obj.NodesOffset.Value) if obj.Nodes and (prop != "ResetNodes"): if hasattr(self,"nodes"): if self.nodes: if obj.Nodes != self.nodes: # nodes are set manually: don't touch them return else: # nodes haven't been calculated yet, but are set (file load) # we set the nodes now but don't change the property if nodes: self.nodes = [v.Point.add(offset) for v in nodes.Vertexes] return # we set the nodes if nodes: self.nodes = [v.Point.add(offset) for v in nodes.Vertexes] obj.Nodes = self.nodes ArchComponent.Component.onChanged(self,obj,prop)
def flipEdge(edge): '''flipEdge(edge) Flips given edge around so the new Vertexes[0] was the old Vertexes[-1] and vice versa, without changing the shape. Currently only lines, line segments, circles and arcs are supported.''' if Part.Line == type(edge.Curve) and not edge.Vertexes: return Part.Edge(Part.Line(edge.valueAt(edge.LastParameter), edge.valueAt(edge.FirstParameter))) elif Part.Line == type(edge.Curve) or Part.LineSegment == type(edge.Curve): return Part.Edge(Part.LineSegment(edge.Vertexes[-1].Point, edge.Vertexes[0].Point)) elif Part.Circle == type(edge.Curve): # Create an inverted circle circle = Part.Circle(edge.Curve.Center, -edge.Curve.Axis, edge.Curve.Radius) # Rotate the circle appropriately so it starts at edge.valueAt(edge.LastParameter) circle.rotate(FreeCAD.Placement(circle.Center, circle.Axis, 180 - math.degrees(edge.LastParameter + edge.Curve.AngleXU))) # Now the edge always starts at 0 and LastParameter is the value range arc = Part.Edge(circle, 0, edge.LastParameter - edge.FirstParameter) return arc elif Part.BSplineCurve == type(edge.Curve): spline = edge.Curve mults = spline.getMultiplicities() weights = spline.getWeights() knots = spline.getKnots() poles = spline.getPoles() perio = spline.isPeriodic() ratio = spline.isRational() degree = spline.Degree ma = max(knots) mi = min(knots) knots = [ma+mi-k for k in knots] mults.reverse() weights.reverse() poles.reverse() knots.reverse() flipped = Part.BSplineCurve() flipped.buildFromPolesMultsKnots(poles, mults , knots, perio, degree, weights, ratio) return Part.Edge(flipped) PathLog.warning(translate('PathGeom', "%s not support for flipping") % type(edge.Curve))
def testSketcher(self): """ Mixup of Label and Name (bug #2407)""" sketch = self.doc.addObject('Sketcher::SketchObject', 'Sketch') sheet = self.doc.addObject('Spreadsheet::Sheet', 'Spreadsheet') sheet.setAlias('A1', 'Length') self.doc.recompute() sheet.set('A1', '47,11') self.doc.recompute() index = sketch.addGeometry(Part.LineSegment(v(0, 0, 0), v(10, 10, 0)), False) sketch.addConstraint(Sketcher.Constraint('Distance', index, 14.0)) self.doc.recompute() sketch.setExpression('Constraints[0]', u'Spreadsheet.Length') self.doc.recompute() sheet.Label = "Calc" self.doc.recompute() self.assertEqual(sketch.ExpressionEngine[0][1], 'Calc.Length') self.assertIn('Up-to-date', sketch.State)
def ricreaShapeElementare(sh, begin, end): # controllo il tipo passato # Wire? if isinstance(sh, Part.Wire): # Estraggo le edges edges = sh.Edges if (len(edges) == 1): # Ho una sola edge, la converto con i nuovi punti di inizio e fine ed esco return ([ricreaShapeElementare(edges[0], begin, end)]) elif (len(edges) > 1): # Ho più edges, converto la prima con il nuovo inizio e l'ultima con la nuova fine, le altre senza modificare inizio e fine list = ricreaShapeElementare( edges[0], begin, edges[0].valueAt(edges[0].LastParameter)) for e in edges[1:-1]: list.append( ricreaShapeElementare(e, e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter))) list.append( ricreaShapeElementare( edges[-1], edges[-1].valueAt(edges[-1].FirstParameter), end)) return (list) # Edge? elif isinstance(sh, Part.Edge): # Line? if isinstance(sh.Curve, Part.Line): return ([Part.LineSegment(begin, end).toShape()]) # Circle? elif isinstance(sh.Curve, Part.Circle): return ([ Part.ArcOfCircle( begin, sh.valueAt((sh.FirstParameter + sh.LastParameter) / 2.0), end).toShape() ]) else: print("Part.Edge ma non Line o Circle :-o") print(sh.ShapeType) print(sh.Curve) return ([]) else: print("Né Wire né Line o Circle") return ([])
def getWire(self,obj): import Part if obj.Base: if not hasattr(obj.Base,'Shape'): FreeCAD.Console.PrintError(translate("Arch","The base object is not a Part")+"\n") return if len(obj.Base.Shape.Wires) != 1: FreeCAD.Console.PrintError(translate("Arch","Too many wires in the base shape")+"\n") return if obj.Base.Shape.Wires[0].isClosed(): FreeCAD.Console.PrintError(translate("Arch","The base wire is closed")+"\n") return w = obj.Base.Shape.Wires[0] else: if obj.Length.Value == 0: return w = Part.Wire([Part.LineSegment(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,obj.Length.Value)).toShape()]) return w
def testSimpleSubtractivePipeCase(self): self.Body = self.Doc.addObject('PartDesign::Body', 'Body') self.ProfileSketch = self.Doc.addObject('Sketcher::SketchObject', 'ProfileSketch') self.Body.addObject(self.ProfileSketch) TestSketcherApp.CreateCircleSketch(self.ProfileSketch, (0, 0), 1) self.Doc.recompute() self.SpineSketch = self.Doc.addObject('Sketcher::SketchObject', 'SpineSketch') self.Body.addObject(self.SpineSketch) self.SpineSketch.MapMode = 'FlatFace' self.SpineSketch.Support = (self.Doc.XZ_Plane, ['']) self.Doc.recompute() self.SpineSketch.addGeometry( Part.LineSegment(App.Vector(0.0, 0.0, 0), App.Vector(0, 1, 0)), False) self.SpineSketch.addConstraint( Sketcher.Constraint('Coincident', 0, 1, -1, 1)) self.SpineSketch.addConstraint( Sketcher.Constraint('PointOnObject', 0, 2, -2)) self.SpineSketch.addConstraint( Sketcher.Constraint('DistanceY', 0, 1, 0, 2, 1)) self.Doc.recompute() self.PadSketch = self.Doc.addObject('Sketcher::SketchObject', 'PadSketch') self.Body.addObject(self.PadSketch) TestSketcherApp.CreateRectangleSketch(self.PadSketch, (-5, -5), (10, 10)) self.Doc.recompute() self.Pad = self.Doc.addObject("PartDesign::Pad", "Pad") self.Body.addObject(self.Pad) self.Pad.Profile = self.PadSketch self.Pad.Length = 1.0 self.Doc.recompute() self.SubtractivePipe = self.Doc.addObject( "PartDesign::SubtractivePipe", "SubtractivePipe") self.Body.addObject(self.SubtractivePipe) self.SubtractivePipe.Profile = self.ProfileSketch self.SubtractivePipe.Spine = self.SpineSketch self.Doc.recompute() self.assertAlmostEqual(self.SubtractivePipe.Shape.Volume, 100 - 3.14159265)
def calculateSections(self, obj, postPlacements, postLength, sectionLength): import Part shapes = [] # For the colorization algorithm we have to store the number of faces for each section # It is possible that a section is clipped. Then the number of faces is not equals to the # number of faces in the original section faceNumbers = [] for i in range(obj.NumberOfSections): startPlacement = postPlacements[i] endPlacement = postPlacements[i + 1] sectionLine = Part.LineSegment( startPlacement.Base, endPlacement.Base) sectionBase = sectionLine.value(postLength) if startPlacement.Rotation.isSame(endPlacement.Rotation): sectionRotation = endPlacement.Rotation else: direction = endPlacement.Base.sub(startPlacement.Base) sectionRotation = FreeCAD.Rotation(EAST, direction) placement = FreeCAD.Placement() placement.Base = sectionBase placement.Rotation = sectionRotation sectionCopy = obj.Section.Shape.copy() if sectionLength > sectionLine.length(): # Part.show(Part.Shape([sectionLine]), 'line') sectionCopy = self.clipSection( sectionCopy, sectionLength, sectionLine.length() - postLength) sectionCopy.Placement = placement shapes.append(sectionCopy) faceNumbers.append(len(sectionCopy.Faces)) return (shapes, faceNumbers)
def set_GeometryAndMedia(qwm_doc): qwm_doc.addObject('Sketcher::SketchObject', 'sketch_vtape') qwm_doc.sketch_vtape.Placement = FreeCAD.Placement( FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Rotation(0.0, 0.0, 0.0, 1.0)) qwm_doc.sketch_vtape.addGeometry( Part.LineSegment(FreeCAD.Vector(-6.0, -3.0, 0), FreeCAD.Vector(6.0, -3.0, 0))) qwm_doc.sketch_vtape.addGeometry( Part.LineSegment(FreeCAD.Vector(6.0, -3.0, 0), FreeCAD.Vector(6.0, 3.0, 0))) qwm_doc.sketch_vtape.addGeometry( Part.LineSegment(FreeCAD.Vector(6.0, 3.0, 0), FreeCAD.Vector(-6.0, 3.0, 0))) qwm_doc.sketch_vtape.addGeometry( Part.LineSegment(FreeCAD.Vector(-6.0, 3.0, 0), FreeCAD.Vector(-6.0, -3.0, 0))) qwm_doc.addObject('Sketcher::SketchObject', 'sketch_vtape1') qwm_doc.sketch_vtape1.Placement = FreeCAD.Placement( FreeCAD.Vector(0.0, 0.0, 30.0), FreeCAD.Rotation(0.0, 0.0, 0.0, 1.0)) qwm_doc.sketch_vtape1.addGeometry( Part.LineSegment(FreeCAD.Vector(-4.0, -1.5, 0), FreeCAD.Vector(4.0, -1.5, 0))) qwm_doc.sketch_vtape1.addGeometry( Part.LineSegment(FreeCAD.Vector(4.0, -1.5, 0), FreeCAD.Vector(4.0, 1.5, 0))) qwm_doc.sketch_vtape1.addGeometry( Part.LineSegment(FreeCAD.Vector(4.0, 1.5, 0), FreeCAD.Vector(-4.0, 1.5, 0))) qwm_doc.sketch_vtape1.addGeometry( Part.LineSegment(FreeCAD.Vector(-4.0, 1.5, 0), FreeCAD.Vector(-4.0, -1.5, 0))) qwm_doc.addObject("Part::Loft", "vtape1") qwm_doc.vtape1.Sections = [qwm_doc.sketch_vtape, qwm_doc.sketch_vtape1] qwm_doc.vtape1.Solid = True qwm_doc.vtape1.Ruled = False qwm_doc.vtape1.Closed = False vtape1_viewObject = qwm_doc.vtape1.ViewObject vtape1_viewObject.Transparency = 60 qwm_doc.vtape1.Medium = QW_Modeller.getQWMedium("air")
def barrel(neckd, fret): """ Create neck barrell shape from Nut to JointFret Args: necks : NeckData fret : end fret """ with traceTime("Make Neck Barrell"): profile = getNeckProfile(neckd.profileName) line = neckd.lineToFret(fret) wire = Part.Wire( Part.LineSegment(geom.vec(line.start), geom.vec(line.end)).toShape()) return geom.makeTransition(wire.Edges[0], profile, neckd.widthAt, neckd.thicknessAt, steps=8, ruled=False)
def param(self, par): if (par >= self.edge.FirstParameter) and (par <= self.edge.LastParameter): self._par = par self.p1 = MarkerOnShape([self.edge.valueAt(self._par)], edge) tangent = self.edge.tangentAt( self._par) # TODO change tangent to cross-tangent tangent.normalize() tangent.multiply(1e12) l = Part.LineSegment( self.edge.valueAt(self._par).sub(tangent), self.edge.valueAt(self._par).add(tangent)) self.tangent = l.toShape() self.p2 = MarkerOnShape([self.tangent.valueAt(self._scale)], self.tangent) else: FreeCAD.Console.PrintError( "Bad parameter value, setting to middle of edge") self._par = self.edge.FirstParameter + 0.5 * ( self.edge.LastParameter - self.edge.FirstParameter)
def execute(self,obj): import Part geoms = [] dist = 0 if obj.Distances: if len(obj.Distances) == len(obj.Angles): for i in range(len(obj.Distances)): if hasattr(obj.Length,"Value"): l = obj.Length.Value else: l = obj.Length dist += obj.Distances[i] ang = math.radians(obj.Angles[i]) p1 = Vector(dist,0,0) p2 = Vector(dist+(l/math.cos(ang))*math.sin(ang),l,0) geoms.append(Part.LineSegment(p1,p2).toShape()) if geoms: sh = Part.Compound(geoms) sh.Placement = obj.Placement obj.Shape = sh
def _add_vertical_sketch_segment(geometries, constraints, length, ver_vec_start, ver_vec_end, reverse): Console.PrintMessage("_add_vertical_sketch_segment({},{})\n".format( length, reverse)) segment_count = len(geometries) geometries.append(Part.LineSegment(ver_vec_start, ver_vec_end)) constraints.append(Sketcher.Constraint("Vertical", segment_count)) if segment_count > 0: constraints.append( Sketcher.Constraint("Coincident", segment_count - 1, SKETCH_GEOMETRY_VERTEX_END_INDEX, segment_count, SKETCH_GEOMETRY_VERTEX_START_INDEX)) constraints.append( Sketcher.Constraint("DistanceY", segment_count, SKETCH_GEOMETRY_VERTEX_START_INDEX, segment_count, SKETCH_GEOMETRY_VERTEX_END_INDEX, (-1 if reverse else 1) * length))
def calc(self): import Part if (self.p1 != None) and (self.p2 != None): points = [DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True),\ DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True)] if self.p3 != None: p1 = self.p1 p4 = self.p2 if DraftVecUtils.equals(p1,p4): proj = None else: base = Part.LineSegment(p1,p4).toShape() proj = DraftGeomUtils.findDistance(self.p3,base) if not proj: p2 = p1 p3 = p4 else: p2 = p1.add(proj.negative()) p3 = p4.add(proj.negative()) points = [DraftVecUtils.tup(p1),DraftVecUtils.tup(p2),DraftVecUtils.tup(p3),DraftVecUtils.tup(p4)] self.coords.point.setValues(0,4,points)
def heelTransition(neckd, line, startd, h, transitionLength, transitionTension): """ Create transition from neck to heel shape. Args: neckd : NeckData line : linexy, reference line startd : starting point distance from line.start h : Heel height """ with traceTime("Make Heel Transition"): if transitionLength <= 0 or transitionTension <= 0: return None trline = linexy(line.lerpPointAt(startd), line.lerpPointAt(startd + transitionLength * 2)) length = trline.length Transition = transitionDatabase[neckd.transitionFunction] transition = Transition(neckd.widthAt, neckd.thicknessAt, transitionTension, transitionTension, startd, length) profile = getNeckProfile(neckd.profileName) wire = Part.Wire( Part.LineSegment(geom.vec(trline.start), geom.vec(trline.end)).toShape()) steps = int(trline.length / 4) + 1 limit = geom.extrusion(neckd.fbd.neckFrame.polygon, 0, Vector(0, 0, -h)) tr = geom.makeTransition(wire.Edges[0], profile, transition.width, transition.height, steps=steps, limits=limit, ruled=False) return tr
def addCycleSketch(name, wire): """Add a sketch of a cycle (closed wire) to a FC document. Parameters ---------- name : wire : Returns ------- """ assert wire.isClosed() doc = FreeCAD.ActiveDocument if doc.getObject(name) is not None: raise ValueError(f"Sketch with name '{name}' already exists.") # makeSketch() could handle constraints itself and does recompute() well, # but sometimes we may have invalid wires, which it handles badly (fixsometime) # ~ return Draft.makeSketch([wire], name=name, autoconstraints=True) sketch = doc.addObject("Sketcher::SketchObject", name) for i, edge in enumerate(wire.Edges): v0 = vec(tuple(edge.Vertexes[0].Point)) v1 = vec(tuple(edge.Vertexes[1].Point)) if i > 0: if (v0 - old_v1).Length > 1e-5: # fix invalid wire segments v1 = vec(tuple(edge.Vertexes[0].Point)) v0 = vec(tuple(edge.Vertexes[1].Point)) old_v1 = v1 sketch.addGeometry(Part.LineSegment(v0, v1)) if i > 0: sketch.addConstraint( Sketcher.Constraint("Coincident", i - 1, 2, i, 1)) sketch.addConstraint(Sketcher.Constraint("Coincident", i, 2, 0, 1)) doc.recompute() return sketch
def addFrame(s, p1, p2, p3, p4, p5, p6, p7, p8): "adds two rectangles to the given sketch" idx = s.GeometryCount s.addGeometry(Part.LineSegment(p1, p2)) s.addGeometry(Part.LineSegment(p2, p3)) s.addGeometry(Part.LineSegment(p3, p4)) s.addGeometry(Part.LineSegment(p4, p1)) s.addConstraint( Sketcher.Constraint('Coincident', idx, 2, idx + 1, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 1, 2, idx + 2, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 2, 2, idx + 3, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 3, 2, idx, 1)) s.addConstraint(Sketcher.Constraint('Horizontal', idx)) s.addConstraint(Sketcher.Constraint('Horizontal', idx + 2)) s.addConstraint(Sketcher.Constraint('Vertical', idx + 1)) s.addConstraint(Sketcher.Constraint('Vertical', idx + 3)) s.addGeometry(Part.LineSegment(p5, p6)) s.addGeometry(Part.LineSegment(p6, p7)) s.addGeometry(Part.LineSegment(p7, p8)) s.addGeometry(Part.LineSegment(p8, p5)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 4, 2, idx + 5, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 5, 2, idx + 6, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 6, 2, idx + 7, 1)) s.addConstraint( Sketcher.Constraint('Coincident', idx + 7, 2, idx + 4, 1)) s.addConstraint(Sketcher.Constraint('Horizontal', idx + 4)) s.addConstraint(Sketcher.Constraint('Horizontal', idx + 6)) s.addConstraint(Sketcher.Constraint('Vertical', idx + 5)) s.addConstraint(Sketcher.Constraint('Vertical', idx + 7))
def getline(data): """Turns an OCA line definition into a FreeCAD Part.Edge. Parameters ---------- data : list Different types of data. Returns ------- Part.Edge An edge object from the points in `data`. """ FCC.PrintMessage("found line %s \n" % data) verts = [] for p in range(len(data)): if data[p] == "P": verts.append(getpoint(data[p:p + 4])) elif data[p][0] == "P": verts.append(getpoint([data[p]])) L = Part.LineSegment(verts[0], verts[1]) return L.toShape()
def extendFace(self, edges, checkedEdges, face, extendDist=0): ''' extend the selected edges ''' newEdges = edges if len(checkedEdges): for e in checkedEdges: origEdge = newEdges[int(e) -1] if origEdge: p1 = origEdge.Vertexes[0].Point p2 = origEdge.Vertexes[1].Point ## work out the direction the edge needs to be extended vec = p2.sub(p1) offsetDir = self.rotate(vec, 1.5708) offsetDir = offsetDir.normalize() cen = face.BoundBox.Center if cen.distanceToPoint(p1.add(offsetDir)) < cen.distanceToPoint(p1): offsetDir = offsetDir.negative() ## the direction is a normalised vector. multiply that by the distance required offset = offsetDir.multiply(extendDist) for i, repEdge in enumerate(newEdges): rev = repEdge.Vertexes for j, v in enumerate(rev): jOpp = 1 - j if self.isSamePoint(v.Point, p1) or self.isSamePoint(v.Point, p2): tempVerts = newEdges[i].Vertexes newEdge = Part.Edge(Part.LineSegment(tempVerts[j].Point.add(offset), tempVerts[jOpp].Point)) newEdges.pop(i) newEdges.insert(i, newEdge) ## clear the selection to ensure no weird graphics FreeCADGui.Selection.clearSelection() newFace = self.createFace(newEdges) if not newFace: FreeCAD.Console.PrintError('Face Extension Failed') else: return newFace
def testUnconnectedCurve(self): SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'UnconnectedCurve') SketchFeature.addGeometry( Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) SketchFeature.addConstraint( Sketcher.Constraint('Coincident', 0, 1, -1, 1)) SketchFeature.addConstraint( Sketcher.Constraint('DistanceX', 0, 1, 0, 2, 1)) SketchFeature.addConstraint( Sketcher.Constraint('DistanceY', 0, 1, 0, 2, 1)) arc = Part.ArcOfCircle( Part.Circle(App.Vector(3, 1, 0), App.Vector(0, 0, 1), 1.75), -3.14, -2.17) SketchFeature.addGeometry(arc) SketchFeature.addConstraint( Sketcher.Constraint('DistanceX', -1, 1, 1, 3, 3.0)) SketchFeature.addConstraint( Sketcher.Constraint('DistanceY', -1, 1, 1, 3, 1.0)) SketchFeature.addConstraint( Sketcher.Constraint('Distance', 0, 2, 1, 1, 0.25)) self.Doc.recompute()
def compute_path_cp(self): free_turns = self.turns - 2 skew = Part.LineSegment( Vector(2 * pi, self.wire_diam, 0), Vector((self.turns - 1) * 2 * pi, self.length - self.wire_diam, 0)) tan = skew.tangent(skew.FirstParameter)[0] tan.normalize() tan.multiply(self.wire_diam / 2.) p1 = Vector(-tan.y, tan.x, 0) ls = Part.Line(skew.StartPoint + p1, skew.EndPoint - p1) h1 = Part.Line(Vector(0, self.wire_diam / 2., 0), Vector(1, self.wire_diam / 2., 0)) h2 = Part.Line(Vector(0, self.length - self.wire_diam / 2., 0), Vector(1, self.length - self.wire_diam / 2., 0)) pts = [Vector2d(0, self.wire_diam / 2.)] i1 = h1.intersect(ls)[0] i2 = h2.intersect(ls)[0] pts.append(Vector2d(i1.X, i1.Y)) pts.append(Vector2d(i2.X, i2.Y)) pts.append( Vector2d(self.turns * 2 * pi, self.length - self.wire_diam / 2.)) return pts
def circleFrom2LinesRadius(edge1, edge2, radius): """circleFrom2LinesRadius(edge,edge,radius)""" int = findIntersection(edge1, edge2, True, True) if not int: return None int = int[0] bis12 = angleBisection(edge1, edge2) bis21 = Part.LineSegment(bis12.Vertexes[0].Point, DraftVecUtils.rotate(vec(bis12), math.pi / 2.0)) ang12 = abs(DraftVecUtils.angle(vec(edge1), vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) dist21 = radius / math.sin(ang21 * 0.5) circles = [] cen = Vector.add(int, vec(bis12).multiply(dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis12).multiply(-dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis21).multiply(dist21)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis21).multiply(-dist21)) circles.append(Part.Circle(cen, NORM, radius)) return circles
def cappedShoulderLines(self, max_x, minor_y, outerShape, innerShape): major = FreeCAD.Vector(self._length, 0) minor = FreeCAD.Vector(0, self._radius) innerMajor = FreeCAD.Vector(max_x, 0) innerMinor = FreeCAD.Vector(self._thickness, minor_y) end2 = FreeCAD.Vector(0, self._shoulderRadius) end3 = FreeCAD.Vector(-self._shoulderLength, self._shoulderRadius) end4 = FreeCAD.Vector(-self._shoulderLength, 0) end5 = FreeCAD.Vector(self._shoulderThickness - self._shoulderLength, 0) end6 = FreeCAD.Vector(self._shoulderThickness - self._shoulderLength, self._shoulderRadius - self._shoulderThickness) end7 = FreeCAD.Vector(self._thickness, self._shoulderRadius - self._shoulderThickness) line1 = Part.LineSegment(major, innerMajor) line2 = Part.LineSegment(minor, end2) line3 = Part.LineSegment(end2, end3) line4 = Part.LineSegment(end3, end4) line5 = Part.LineSegment(end4, end5) line6 = Part.LineSegment(end5, end6) line7 = Part.LineSegment(end6, end7) line8 = Part.LineSegment(end7, innerMinor) return [ outerShape.toShape(), line1.toShape(), line2.toShape(), line3.toShape(), line4.toShape(), line5.toShape(), line6.toShape(), line7.toShape(), line8.toShape(), innerShape.toShape() ]
def test03(self): """Verify isVertical/isHorizontal for Edges""" # lines self.assertTrue(PathGeom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, -1, 8))))) self.assertFalse(PathGeom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(1, -1, 8))))) self.assertFalse(PathGeom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, 1, 8))))) self.assertTrue(PathGeom.isHorizontal(Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(-1, -1, -1))))) self.assertTrue(PathGeom.isHorizontal(Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, -1, -1))))) self.assertTrue(PathGeom.isHorizontal(Part.Edge(Part.LineSegment(Vector(1, 1, -1), Vector(-1, -1, -1))))) self.assertFalse(PathGeom.isHorizontal(Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(1, -1, 8))))) self.assertFalse(PathGeom.isHorizontal(Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, 1, 8))))) # circles self.assertTrue(PathGeom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 0))))) self.assertTrue(PathGeom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 0))))) self.assertTrue(PathGeom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 0))))) self.assertFalse(PathGeom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1))))) self.assertTrue(PathGeom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 0, 1))))) self.assertFalse(PathGeom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 1))))) self.assertFalse(PathGeom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 1))))) self.assertFalse(PathGeom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1)))))
def getTransitionCurve(startProfile, end, height, hLerp, angle, profile, pos, voluteOffset): """ Generate mid points of the transition. Returns: Vector[] -- List of mid points for transition using bspline curve. """ # Search start point pos = Vector(pos.x - voluteOffset, pos.y, pos.z) # ! TODO: Barrel Slope s = profile.hPointAt(abs(pos.x), pos).Vertexes[0].Point c = end.CenterOfMass length = c.x - pos.x # Horizontal Ref hl = Part.LineSegment( Vector(s), Vector(c.x, c.y, s.z) # ! TODO: Barrel Slope ) # Vertical Ref vbz = c.z - height - end.Length hbx = length * hLerp # Bezier curve = Part.BSplineCurve( [hl.value(0), hl.value(hbx), Vector(c.x, s.y, vbz)]) # Nearest end vertex a = end.Edges[0].Vertexes[0].Point b = end.Edges[0].Vertexes[1].Point p = a if a.x < b.x else b limit = p.x # Generate points points = [w for w in curve.discretize(20) if w.x > s.x and w.x < limit] return points, vbz, hbx
def edgestofaces(edges, algo=3, eps=0.001): #edges=[] #for shapeobj in (objs): # edges.extend(shapeobj.Shape.Edges) #taken from Drafttools #from draftlibs import fcvec, fcgeo import Part #wires = fcgeo.findWires(edges) wires = edgestowires(edges, eps) facel = [] for w in wires: #assert(len(w.Edges)>1) if not w.isClosed(): p0 = w.Vertexes[0].Point p1 = w.Vertexes[-1].Point edges2 = w.Edges[:] try: edges2.append(Part.LineSegment(p1, p0).toShape()) w = Part.Wire(edges2) #w = Part.Wire(fcgeo.sortEdges(edges2)) except OCCError: comp = Part.Compound(edges2) w = comp.connectEdgesToWires(False, eps).Wires[0] facel.append(Part.Face(w)) #if w.isValid: #debugging # facel.append(Part.Face(w)) #else: # Part.show(w) if algo is None: return facel elif algo == 1: #stable behavior return subtractfaces(facel) elif algo == 0: #return all faces return Part.Compound(facel) elif algo == 2: return subtractfaces2(facel) elif algo == 3: return Overlappingfaces(facel).makeshape()
def calculateSections(self, obj, postPlacements, postLength, sectionLength): import Part shapes = [] for i in range(obj.NumberOfSections): startPlacement = postPlacements[i] endPlacement = postPlacements[i + 1] sectionLine = Part.LineSegment(startPlacement.Base, endPlacement.Base) sectionBase = sectionLine.value(postLength) if startPlacement.Rotation.isSame(endPlacement.Rotation): sectionRotation = endPlacement.Rotation else: direction = endPlacement.Base.sub(startPlacement.Base) sectionRotation = FreeCAD.Rotation(EAST, direction) placement = FreeCAD.Placement() placement.Base = sectionBase placement.Rotation = sectionRotation sectionCopy = obj.Section.Shape.copy() if sectionLength > sectionLine.length(): # Part.show(Part.Shape([sectionLine]), 'line') sectionCopy = self.clipSection( sectionCopy, sectionLength, sectionLine.length() - postLength) sectionCopy.Placement = placement shapes.append(sectionCopy) return shapes
def Process_comp_outline(doc, comp_outline, comp_height): """Process_comp_outline(doc,comp_outline,comp_height)->part shape Create solid component shape base on its outline""" vertex_index = -1 #presume no vertex out_shape = [] if comp_outline == []: #force 0.2mm circle shape for components without place outline definition comp_outline.append([0.0, 0.0, 0.0]) comp_outline.append([0.1, 0.0, 360.0]) for point in comp_outline: vertex = Base.Vector(point[0], point[1], 0) vertex_index += 1 if vertex_index > 0: if point[2] != 0 and point[2] != 360: out_shape.append( Part.Arc(prev_vertex, mid_point(prev_vertex, vertex, point[2]), vertex)) FreeCAD.Console.PrintMessage("mid point " + str(mid_point) + "\n") elif point[2] == 360: per_point = Per_point(prev_vertex, vertex) out_shape.append( Part.Arc(per_point, mid_point(per_point, vertex, point[2] / 2), vertex)) out_shape.append( Part.Arc(per_point, mid_point(per_point, vertex, -point[2] / 2), vertex)) else: out_shape.append(Part.LineSegment(prev_vertex, vertex)) prev_vertex = vertex out_shape = Part.Shape(out_shape) out_shape = Part.Wire(out_shape.Edges) out_shape = Part.Face(out_shape) out_shape = out_shape.extrude(Base.Vector(0, 0, comp_height)) #Part.show(out_shape) return out_shape
def joinWalls(walls,delete=False): """joins the given list of walls into one sketch-based wall. If delete is True, merged wall objects are deleted""" import Part if not walls: return None if not isinstance(walls,list): walls = [walls] if not areSameWallTypes(walls): return None deleteList = [] base = walls.pop() if base.Base: if base.Base.Shape.Faces: return None if Draft.getType(base.Base) == "Sketch": sk = base.Base else: sk = Draft.makeSketch(base.Base,autoconstraints=True) if sk: base.Base = sk for w in walls: if w.Base: if not w.Base.Shape.Faces: for e in w.Base.Shape.Edges: l = e.Curve if isinstance(l,Part.Line): l = Part.LineSegment(e.Vertexes[0].Point,e.Vertexes[-1].Point) sk.addGeometry(l) deleteList.append(w.Name) if delete: for n in deleteList: FreeCAD.ActiveDocument.removeObject(n) FreeCAD.ActiveDocument.recompute() base.ViewObject.show() return base
def circleFrom2PointsRadius(p1, p2, radius): """circleFrom2PointsRadiust(Vector, Vector, radius)""" if DraftVecUtils.equals(p1, p2): return None p1_p2 = Part.LineSegment(p1, p2).toShape() dist_p1p2 = DraftVecUtils.dist(p1, p1) mid = findMidpoint(p1_p2) if dist_p1p2 == 2 * radius: circle = Part.Circle(mid, NORM, radius) if circle: return [circle] else: return None dir = vec(p1_p2) dir.normalize() perpDir = dir.cross(Vector(0, 0, 1)) perpDir.normalize() dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) cen1 = Vector.add(mid, Vector(perpDir).multiply(dist)) cen2 = Vector.add(mid, Vector(perpDir).multiply(-dist)) circles = [] if cen1: circles.append(Part.Circle(cen1, NORM, radius)) if cen2: circles.append(Part.Circle(cen2, NORM, radius)) if circles: return circles else: return None
def create_wall( base, dist1: float = 0, dist2: float = 0, relative: bool = True, ): label = base.Label + '_walltrace' if relative: d1 = dist1 * base.Length.Value d2 = dist2 * base.Length.Value else: d1 = dist1 * 1000 d2 = dist2 * 1000 length = d2 - d1 max_length = base.Length.Value - d1 if length > max_length: d2 = max_length e = base.Shape.Edges[0] start_p = e.valueAt(d1) end_p = e.valueAt(d2) trace = Part.LineSegment(start_p, end_p) wall_trace = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject", "WallTrace") wall_trace.Placement.Base.z = base.Start.z wall_trace.Label = label wall_trace.addGeometry(trace) wall = Arch.makeWall(wall_trace) wall.Length = length wall.addProperty('App::PropertyInteger', 'weight', 'Wall') wall.addProperty('App::PropertyString', 'loadpat', 'Wall') wall.addProperty('App::PropertyLink', 'base', 'Wall').base = base if FreeCAD.GuiUp: wall.ViewObject.Transparency = 40 wall.ViewObject.LineWidth = 1 wall.ViewObject.PointSize = 1 wall.recompute() return wall