Example #1
0
 def execute(self, fp):
   if fp.OD>fp.OD2:
     if fp.calcH or fp.Height==0:
       fp.Height=3*(fp.OD-fp.OD2)
     fp.Profile=str(fp.OD)+"x"+str(fp.OD2)
     if fp.conc:
       sol = Part.makeCone(fp.OD/2,fp.OD2/2,fp.Height)
       if fp.thk<fp.OD/2 and fp.thk2<fp.OD2/2:
         fp.Shape=sol.cut(Part.makeCone(fp.OD/2-fp.thk,fp.OD2/2-fp.thk2,fp.Height))
       else:
         fp.Shape=sol
       fp.Ports=[FreeCAD.Vector(),FreeCAD.Vector(0,0,float(fp.Height))]
     else:
       C=Part.makeCircle(fp.OD/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1))
       c=Part.makeCircle(fp.OD2/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1))
       c.translate(FreeCAD.Vector((fp.OD-fp.OD2)/2,0,fp.Height))
       sol=Part.makeLoft([c,C],True)
       if fp.thk<fp.OD/2 and fp.thk2<fp.OD2/2:
         C=Part.makeCircle(fp.OD/2-fp.thk,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1))
         c=Part.makeCircle(fp.OD2/2-fp.thk2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1))
         c.translate(FreeCAD.Vector((fp.OD-fp.OD2)/2,0,fp.Height))
         fp.Shape=sol.cut(Part.makeLoft([c,C],True))
       else:
         fp.Shape=sol
       fp.Ports=[FreeCAD.Vector(),FreeCAD.Vector((fp.OD-fp.OD2)/2,0,float(fp.Height))]
   super(Reduct,self).execute(fp) # perform common operations
Example #2
0
 def execute(self, fp):
   if fp.BendAngle<180:
     if fp.thk>fp.OD/2:
       fp.thk=fp.OD/2
     fp.ID=fp.OD-2*fp.thk
     fp.Profile=str(fp.OD)+"x"+str(fp.thk)
     CenterOfBend=FreeCAD.Vector(fp.BendRadius,fp.BendRadius,0)
     ## make center-line ##
     R=Part.makeCircle(fp.BendRadius,CenterOfBend,FreeCAD.Vector(0,0,1),225-float(fp.BendAngle)/2,225+float(fp.BendAngle)/2)
     ## move the cl so that Placement.Base is the center of elbow ##
     from math import pi, cos, sqrt
     d=(fp.BendRadius*sqrt(2)-fp.BendRadius/cos(fp.BendAngle/180*pi/2))
     P=FreeCAD.Vector(-d*cos(pi/4),-d*cos(pi/4),0)
     R.translate(P)
     ## calculate Ports position ##
     fp.Ports=[R.valueAt(R.FirstParameter),R.valueAt(R.LastParameter)]
     ## make the shape of the elbow ##
     c=Part.makeCircle(fp.OD/2,fp.Ports[0],R.tangentAt(R.FirstParameter)*-1)
     b=Part.makeSweepSurface(R,c)
     p1=Part.Face(Part.Wire(c))
     p2=Part.Face(Part.Wire(Part.makeCircle(fp.OD/2,fp.Ports[1],R.tangentAt(R.LastParameter))))
     sol=Part.Solid(Part.Shell([b,p1,p2]))
     planeFaces=[f for f in sol.Faces if type(f.Surface)==Part.Plane]
     #elbow=sol.makeThickness(planeFaces,-fp.thk,1.e-3)
     #fp.Shape = elbow
     if fp.thk<fp.OD/2:
       fp.Shape=sol.makeThickness(planeFaces,-fp.thk,1.e-3)
     else:
       fp.Shape=sol
     super(Elbow,self).execute(fp) # perform common operations
Example #3
0
 def update(self, names, pos):
     """ Update the 3D view printing annotations.
     @param names Weight names.
     @param pos Weight positions (FreeCAD::Base::Vector).
     """
     # Destroy all previous entities
     self.clean()
     for i in range(0, len(names)):
         # Draw gravity line
         line = Part.makeLine((pos[i].x,pos[i].y,pos[i].z),(pos[i].x,pos[i].y,pos[i].z - 9.81))
         Part.show(line)
         objs = FreeCAD.ActiveDocument.Objects
         self.objects.append(objs[-1])
         objs[-1].Label = names[i] + 'Line'
         # Draw circles
         circle = Part.makeCircle(0.5, pos[i], Base.Vector(1.0,0.0,0.0))
         Part.show(circle)
         objs = FreeCAD.ActiveDocument.Objects
         self.objects.append(objs[-1])
         objs[-1].Label = names[i] + 'CircleX'            
         circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,1.0,0.0))
         Part.show(circle)
         objs = FreeCAD.ActiveDocument.Objects
         self.objects.append(objs[-1])
         objs[-1].Label = names[i] + 'CircleY'            
         circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,0.0,1.0))
         Part.show(circle)
         objs = FreeCAD.ActiveDocument.Objects
         self.objects.append(objs[-1])
         objs[-1].Label = names[i] + 'CircleZ'            
         # Draw annotation
         self.objects.append(DrawText(names[i] + 'Text', names[i], Base.Vector(pos[i].x+1.0,pos[i].y,pos[i].z)))
Example #4
0
    def test72(self):
        '''Flip a circle'''
        edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1))
        self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge))

        edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1))
        self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge))
Example #5
0
def circle_hollow(params,document):
        od = params['D']
        t = params['t']
        l = params['l']
        name = params['name']

        id = od - t

        outer = Part.Wire(Part.makeCircle(0.5*od))
        inner = Part.Wire(Part.makeCircle(0.5*id))
        face = Part.makeFace([outer, inner], "Part::FaceMakerBullseye")

        if params['arch']:
                part = Arch.makeStructure(name=name)

                prof = document.addObject("Part::Feature","Profile")
                prof.Shape = face
                part.Base = prof

                part.Height = l
        else:
                part = document.addObject("Part::Feature","BOLTS_part")
                part.Label = name

                beam = face.extrude(Vector(0,0,l))
                part.Shape = beam
Example #6
0
 def execute(self, fp):
   fp.thread="M"+str(float(fp.d))
   c=Part.makeCircle(fp.C/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),0,180)
   l1=Part.makeLine((fp.C/2,0,0),(fp.C/2,fp.C/2-fp.H,0))
   l2=Part.makeLine((-fp.C/2,0,0),(-fp.C/2,fp.C/2-fp.H,0))
   p=Part.Face(Part.Wire(Part.makeCircle(fp.d/2,c.valueAt(c.FirstParameter),c.tangentAt(c.FirstParameter))))
   path=Part.Wire([c,l1,l2])
   fp.Shape=path.makePipe(p)
   fp.Ports=[FreeCAD.Vector(0,0,1)]
    def test04(self):
        '''Verify isWireClockwise for unoriented wires.'''
        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1),   0, 180)
        e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter))
        self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e3])))

        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1),   0, 180)
        e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter))
        self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e3])))
    def test03(self):
        '''Verify isWireClockwise for two edge wires with an arc.'''
        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1),   0, 180)
        e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter))
        self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e2])))

        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1),   0, 180)
        e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter))
        self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e2])))
    def test02(self):
        '''Verify isWireClockwise for two half circle wires.'''
        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1),   0, 180)
        e1 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 180, 360)
        self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e1])))

        e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1),   0, 180)
        e1 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 180, 360)
        self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e1])))
Example #10
0
	def execute(self, fp):
		"Create all of the assosiated goemetry"	
		radius = fp.CenterPoint.sub(fp.StartPoint).Length #length between start point and center point
		centerBase = fp.CenterPoint
		centerDir = fp.StartPoint.sub(fp.CenterPoint).normalize()
		angle1 = 0.0
		angle2 = degrees(centerDir.getAngle(fp.EndPoint.sub(fp.CenterPoint).normalize())) ###############PROBLEM HERE, ONLY 180deg MAX#############
		fp.Shape = Part.makeCircle(radius,centerBase,centerDir,angle1,angle2) #this is just the basic  arc shape
		#create snap points (start and end points of line)
		sps = []
		sps.append(fp.StartPoint)
		sps.append(fp.EndPoint)
		fp.SnapPoints = sps
		#create all the snap line direction vectors
		startVec = fp.StartPoint.sub(fp.CenterPoint).normalize()
		endVec = fp.EndPoint.sub(fp.CenterPoint).normalize()
		startVecPerp = FreeCAD.Vector(startVec.y,-startVec.x,startVec.z)
		endVecPerp = FreeCAD.Vector(endVec.y,-endVec.x,endVec.z)
		vert = FreeCAD.Vector(0,1,0)#vertical
		horiz = FreeCAD.Vector(1,0,0)#horizontal
		#fill out index list. index and vector list must be same length
		fp.SnapLinesIndex = [0,0,0,0,1,1,1,1]
		#create assosiated (with index list) vector list
		spvs = [startVec,startVecPerp,vert,horiz,endVec,endVecPerp,vert,horiz]
		fp.SnapDirections = spvs # I don't know why I have to do it like this and not just add directly
Example #11
0
    def execute(self, fp):
        "Do something when doing a recomputation, this method is mandatory"

        circle = Part.makeCircle(fp.Radius)
        cylinder = circle.extrude(Base.Vector(0, 0, fp.Length))
        fp.Shape = cylinder
        FreeCAD.Console.PrintMessage("Recompute Python Missile_body feature\n")
Example #12
0
def makeCylinder(p1,p2,p3,p4):
	s=Part.makePolygon([p1,p2,p3,p1])
	f=Part.makeFilledFace(s.Edges)
	n=f.Faces[0].normalAt(0,0)
	# Drehung 
	n2=FreeCAD.Vector(0,0,1)
	r=FreeCAD.Rotation(n,n2)


	k1=r.multVec(p1)
	sp1=sympy.point.Point2D(k1.x,k1.y)
	z=k1.z
	sp1
	k2=r.multVec(p2)
	sp2=sympy.point.Point2D(k2.x,k2.y)
	sp2
	k3=r.multVec(p3)
	sp3=sympy.point.Point2D(k3.x,k3.y)
	sp3

	k4=r.multVec(p4)
	sp4=sympy.point.Point2D(k4.x,k4.y)
	sp4

	t=sympy.Triangle(sp1,sp2,sp3)
	rad=t.circumradius.evalf()
	center=t.circumcenter
	print rad
	print center
	x=center.x.evalf()
	y=center.y.evalf()

	circ=Part.makeCircle(rad,FreeCAD.Vector(x,y,z))
	Part.show(circ)
	cb=App.ActiveDocument.ActiveObject


	h=k4.z-k3.z

	# und wieder zurueck
	r2=FreeCAD.Rotation(n2,n)

	ex=App.ActiveDocument.addObject("Part::Extrusion","Extrude")
	ex.Base = cb
	ex.Dir = (0,0,h)
	ex.Solid = (True)
	ex.Placement.Rotation=r2
	ex.ViewObject.Transparency=80

	cb.ViewObject.hide()


	s2=Part.makePolygon([p1,p2,p3,p4])
	Part.show(s2)
	for p in [p1,p2,p3,p4]:
		k1=App.ActiveDocument.addObject("Part::Sphere","Sphere")
		k1.Placement.Base=p
		k1.Radius=0.5
		k1.ViewObject.ShapeColor=(1.0,0.0,0.0)
		App.activeDocument().recompute()
Example #13
0
def makeSquareTool(s, m):
  # makes a cylinder with an inner square hole, used as cutting tool
  # create square face
  msq = Base.Matrix()
  msq.rotateZ(math.radians(90.0))
  polygon = []
  vsq = Base.Vector(s / 2.0, s / 2.0, -m * 0.1)
  for i in range(4):
     polygon.append(vsq)
     vsq = msq.multiply(vsq)
  polygon.append(vsq)
  square = Part.makePolygon(polygon)
  square = Part.Face(square)

  # create circle face
  circ = Part.makeCircle(s * 3.0, Base.Vector(0.0, 0.0, -m * 0.1))
  circ = Part.Face(Part.Wire(circ))

  # Create the face with the circle as outline and the square as hole
  face=circ.cut(square)
 
  # Extrude in z to create the final cutting tool
  exSquare = face.extrude(Base.Vector(0.0, 0.0, m * 1.2))
  # Part.show(exHex)
  return exSquare
def arcoCoronaCircular(rInt,rExt,vectorCentro,angIni,angFin):
    # Devuelve el arco de la corona circular (en el plano XY) definido por:
    # rInt: radio interior
    # rExt: radio exterior
    # vectorCentro: centro del círculo (coordenadas x,y)
    # angIni: ángulo inicial (0 a 360º)
    # angFin: ángulo final (0 a 360º)
    # Los ángulos crecen en sentido contrario a las agujas del reloj
    arcoExt=Part.makeCircle(rExt,vectorCentro,Base.Vector(0,0,1),angIni,angFin)
    arcoInt=Part.makeCircle(rInt,vectorCentro,Base.Vector(0,0,1),angIni,angFin)
    angIni=angIni*math.pi/180.0
    angFin=angFin*math.pi/180.0
    r1=Part.makeLine(vectorCentro.add(Base.Vector(rInt*math.cos(angIni),rInt*math.sin(angIni))),vectorCentro.add(Base.Vector(rExt*math.cos(angIni),rExt*math.sin(angIni))))
    r2=Part.makeLine(vectorCentro.add(Base.Vector(rInt*math.cos(angFin),rInt*math.sin(angFin))),vectorCentro.add(Base.Vector(rExt*math.cos(angFin),rExt*math.sin(angFin))))
    arcCoron=Part.Face(Part.Wire([arcoExt,r1,arcoInt,r2]))
    return arcCoron
Example #15
0
	def execute(self, fp):
		edges = fp.Edges
		if edges < 3:
			edges = 3
		length = fp.Length
		radius = fp.Radius
		height = fp.Height

		m=Base.Matrix()
		m.rotateZ(math.radians(360.0/edges))

		# create polygon
		polygon = []
		v=Base.Vector(length,0,0)
		for i in range(edges):
			polygon.append(v)
			v = m.multiply(v)
		polygon.append(v)
		wire = Part.makePolygon(polygon)

		# create circle
		circ=Part.makeCircle(radius)

		# Create the face with the polygon as outline and the circle as hole
		face=Part.Face([wire,Part.Wire(circ)])

		# Extrude in z to create the final solid
		extrude=face.extrude(Base.Vector(0,0,height))
		fp.Shape = extrude
def makeBase(l,z,lpol,zpol,lone,zone,zero):

	lines=[]
	f=np.sqrt(len2(lpol,zero))
	e=np.sqrt(len2(lone,zero))
	dist=e*f*l/((l-1)*e+f)
	pa=pointat(zero,lpol,dist)
	print (l,z,dist,pa)

#	lines.append(Part.makeLine(vec(zpol),vec(pa)))	
#	lines.append(Part.makeCircle(10000,vec(pa)))

	f=np.sqrt(len2(zpol,zero))
	e=np.sqrt(len2(zone,zero))
	dist=e*f*z/((z-1)*e+f)
	pb=pointat(zero,zpol,dist)
	print (l,z,dist,pb)

#	lines.append(Part.makeLine(vec(lpol),vec(pb)))	
#	lines.append(Part.makeCircle(10000,vec(pb)))
	pc=schnittpunkt(lpol,pb,zpol,pa)
	print (pa,pb,pc)
	lines.append(Part.makeCircle(15000,vec(pc)))
	comp=Part.makeCompound(lines)
#	Part.show(comp)

	return pc
Example #17
0
def Process_board_outline(doc, board_outline, drills, board_thickness):
    """Process_board_outline(doc,board_outline,drills,board_thickness)-> number proccesed loops

        adds emn geometry from emn file"""
    vertex_index = -1
    # presume no vertex
    lines = -1  # presume no lines
    out_shape = []
    out_face = []
    for point in board_outline:
        vertex = Base.Vector(point[1], point[2], 0)
        vertex_index += 1
        if vertex_index == 0:
            lines = point[0]
        elif lines == point[0]:
            if point[3] != 0 and point[3] != 360:
                out_shape.append(Part.Arc(prev_vertex, mid_point(prev_vertex, vertex, point[3]), vertex))
                FreeCAD.Console.PrintMessage("mid point " + str(mid_point) + "\n")
            elif point[3] == 360:
                per_point = Per_point(prev_vertex, vertex)
                out_shape.append(Part.Arc(per_point, mid_point(per_point, vertex, point[3] / 2), vertex))
                out_shape.append(Part.Arc(per_point, mid_point(per_point, vertex, -point[3] / 2), vertex))
            else:
                out_shape.append(Part.LineSegment(prev_vertex, vertex))
        else:
            out_shape = Part.Shape(out_shape)
            out_shape = Part.Wire(out_shape.Edges)
            out_face.append(Part.Face(out_shape))
            out_shape = []
            vertex_index = 0
            lines = point[0]
        prev_vertex = vertex
    if lines != -1:
        out_shape = Part.Shape(out_shape)
        out_shape = Part.Wire(out_shape.Edges)
        out_face.append(Part.Face(out_shape))
        outline = out_face[0]
        FreeCAD.Console.PrintMessage("Added outline\n")
        if len(out_face) > 1:
            for otl_cut in out_face[1:]:
                outline = outline.cut(otl_cut)
                FreeCAD.Console.PrintMessage("Cutting shape inside outline\n")
        for drill in drills:
            FreeCAD.Console.PrintMessage("Cutting hole inside outline\n")
            out_shape = Part.makeCircle(drill[0] / 2, Base.Vector(drill[1], drill[2], 0))
            out_shape = Part.Wire(out_shape.Edges)
            outline = outline.cut(Part.Face(out_shape))
        doc_outline = doc.addObject("Part::Feature", "Board_outline")
        doc_outline.Shape = outline
        # FreeCADGui.Selection.addSelection(doc_outline)
        # FreeCADGui.runCommand("Draft_Upgrade")
        # outline=FreeCAD.ActiveDocument.getObject("Union").Shape
        # FreeCAD.ActiveDocument.removeObject("Union")
        # doc_outline=doc.addObject("Part::Feature","Board_outline")
        doc_outline.Shape = outline.extrude(Base.Vector(0, 0, -board_thickness))
        grp = doc.addObject("App::DocumentObjectGroup", "Board_Geoms")
        grp.addObject(doc_outline)
        doc.Board_outline.ViewObject.ShapeColor = (0.0, 0.5, 0.0, 0.0)
    return lines + 1
Example #18
0
    def testScale(self):
        """
        Tests scaling a shape and whether the dimensions are correct afterwards
        """
        e = Shape.cast(Part.makeCircle(2.0, FreeCAD.Base.Vector(1, 2, 3)))
        e2 = e.scale(0.5)

        self.assertAlmostEquals(2.0, e2.BoundingBox(tolerance=0.0001).xlen, 3)
        self.assertAlmostEquals(2.0, e2.BoundingBox(tolerance=0.0001).ylen, 3)
Example #19
0
    def testCopy(self):
        """
        Tests making a copy of a shape object and whether the new one has the
        same properties as the original.
        """
        e = Shape.cast(Part.makeCircle(2.0, FreeCAD.Base.Vector(1, 2, 3)))
        e2 = e.copy()

        self.assertEquals(e.BoundingBox().xlen, e2.BoundingBox().xlen)
        self.assertEquals(e.BoundingBox().ylen, e2.BoundingBox().ylen)
Example #20
0
def makeWorkplane(shape):
    """
    Creates a workplane circle at the ZMin level.
    """
    PathLog.track()
    loc = FreeCAD.Vector(shape.BoundBox.Center.x,
                         shape.BoundBox.Center.y,
                         shape.BoundBox.ZMin)
    c = Part.makeCircle(10, loc)
    return c
Example #21
0
 def recompute(self):
     if self.circle: self.sep.removeChild(self.circle)
     self.circle = None
     if self.endangle < self.startangle:
         c = Part.makeCircle(1,Vector(0,0,0),FreeCAD.DraftWorkingPlane.axis,self.endangle,self.startangle)
     else:
         c = Part.makeCircle(1,Vector(0,0,0),FreeCAD.DraftWorkingPlane.axis,self.startangle,self.endangle)
     buf=c.writeInventor(2,0.01)
     ivin = coin.SoInput()
     ivin.setBuffer(buf)
     ivob = coin.SoDB.readAll(ivin)
     # In case reading from buffer failed
     if ivob and ivob.getNumChildren() > 1:
         self.circle = ivob.getChild(1).getChild(0)
         self.circle.removeChild(self.circle.getChild(0))
         self.circle.removeChild(self.circle.getChild(0))
         self.sep.addChild(self.circle)
     else:
         FreeCAD.Console.PrintWarning("arcTracker.recompute() failed to read-in Inventor string\n")
Example #22
0
 def makeCircle(cls, radius, center, normal):
     """
         Makes a Circle centered at the provided point, having normal in the provided direction
         :param radius: floating point radius of the circle, must be > 0
         :param center: vector representing the center of the circle
         :param normal: vector representing the direction of the plane the circle should lie in
         :return:
     """
     w = Wire(FreeCADPart.Wire([FreeCADPart.makeCircle(radius, center.wrapped, normal.wrapped)]))
     return w
    def makeBubbles(self):
        import Part

        def getNode():
            # make sure we already have the complete node built
            r = self.ViewObject.RootNode
            if r.getChildren().getLength() > 2:
                if r.getChild(2).getChildren().getLength() > 0:
                    if r.getChild(2).getChild(0).getChildren().getLength() > 0:
                        return self.ViewObject.RootNode.getChild(2).getChild(0).getChild(0)
            return None
        
        rn = getNode()
        if rn:
            if self.bubbles:
                rn.removeChild(self.bubbles)
                self.bubbles = None
            self.bubbles = coin.SoSeparator()
            isep = coin.SoSeparator()
            self.bubblestyle = coin.SoDrawStyle()
            self.bubblestyle.linePattern = 0xffff
            self.bubbles.addChild(self.bubblestyle)
            for i in range(len(self.ViewObject.Object.Distances)):
                invpl = self.ViewObject.Object.Placement.inverse()
                verts = self.ViewObject.Object.Shape.Edges[i].Vertexes
                p1 = invpl.multVec(verts[0].Point)
                p2 = invpl.multVec(verts[1].Point)
                dv = p2.sub(p1)
                dv.normalize()
                rad = self.ViewObject.BubbleSize
                center = p2.add(dv.scale(rad,rad,rad))
                ts = Part.makeCircle(rad,center).writeInventor()
                cin = coin.SoInput()
                cin.setBuffer(ts)
                cob = coin.SoDB.readAll(cin)
                co = cob.getChild(1).getChild(0).getChild(2)
                li = cob.getChild(1).getChild(0).getChild(3)
                self.bubbles.addChild(co)
                self.bubbles.addChild(li)
                st = coin.SoSeparator()
                tr = coin.SoTransform()
                tr.translation.setValue((center.x,center.y-rad/4,center.z))
                fo = coin.SoFont()
                fo.name = "Arial,Sans"
                fo.size = rad*100
                tx = coin.SoText2()
                tx.justification = coin.SoText2.CENTER
                tx.string = self.getNumber(i)
                st.addChild(tr)
                st.addChild(fo)
                st.addChild(tx)
                isep.addChild(st)
            self.bubbles.addChild(isep)
            rn.addChild(self.bubbles)
Example #24
0
    def execute(self, fp):
        inner_diameter = fp.module.Value * fp.teeth
        outer_diameter = inner_diameter + fp.height.Value * 2
        inner_circle = Part.Wire(Part.makeCircle(inner_diameter / 2.))
        outer_circle = Part.Wire(Part.makeCircle(outer_diameter / 2.))
        inner_circle.reverse()
        face = Part.Face([outer_circle, inner_circle])
        solid = face.extrude(App.Vector([0., 0., -fp.thickness.Value]))

        ### cutting obj
        alpha_w = np.deg2rad(fp.pressure_angle.Value)
        m = fp.module.Value
        t = fp.teeth
        t_c = t
        t_i = fp.other_teeth
        rm = inner_diameter / 2
        y0 = m * 0.5
        y1 = m + y0
        y2 = m
        r0 = inner_diameter / 2 - fp.height.Value * 0.1
        r1 = outer_diameter / 2 + fp.height.Value * 0.3
        polies = []
        for r_i in np.linspace(r0, r1, fp.num_profiles):
            pts = self.profile(m, r_i, rm, t_c, t_i, alpha_w, y0, y1, y2)
            poly = Wire(makePolygon(list(map(fcvec, pts))))
            polies.append(poly)
        loft = makeLoft(polies, True)
        rot = App.Matrix()
        rot.rotateZ(2 * np.pi / t)
        if fp.construct:
            cut_shapes = [solid]
            for _ in range(t):
                loft = loft.transformGeometry(rot)
                cut_shapes.append(loft)
            fp.Shape = Part.Compound(cut_shapes)
        else:
            for i in range(t):
                loft = loft.transformGeometry(rot)
                solid = solid.cut(loft)
            fp.Shape = solid
Example #25
0
    def recompute(self):
        import Part, re

        if self.circle:
            self.sep.removeChild(self.circle)
        self.circle = None
        if self.endangle < self.startangle:
            c = Part.makeCircle(1, Vector(0, 0, 0), self.normal, self.endangle, self.startangle)
        else:
            c = Part.makeCircle(1, Vector(0, 0, 0), self.normal, self.startangle, self.endangle)
        buf = c.writeInventor(2, 0.01)
        try:
            ivin = coin.SoInput()
            ivin.setBuffer(buf)
            ivob = coin.SoDB.readAll(ivin)
        except:
            # workaround for pivy SoInput.setBuffer() bug
            buf = buf.replace("\n", "")
            pts = re.findall("point \[(.*?)\]", buf)[0]
            pts = pts.split(",")
            pc = []
            for p in pts:
                v = p.strip().split()
                pc.append([float(v[0]), float(v[1]), float(v[2])])
            coords = coin.SoCoordinate3()
            coords.point.setValues(0, len(pc), pc)
            line = coin.SoLineSet()
            line.numVertices.setValue(-1)
            self.circle = coin.SoSeparator()
            self.circle.addChild(coords)
            self.circle.addChild(line)
            self.sep.addChild(self.circle)
        else:
            if ivob and ivob.getNumChildren() > 1:
                self.circle = ivob.getChild(1).getChild(0)
                self.circle.removeChild(self.circle.getChild(0))
                self.circle.removeChild(self.circle.getChild(0))
                self.sep.addChild(self.circle)
            else:
                FreeCAD.Console.PrintWarning("arcTracker.recompute() failed to read-in Inventor string\n")
Example #26
0
def secTirante(tipo,tam):
    if 'Fi' in tipo:
        d=eval(tipo)[tam]['d']
        secPerfil=Part.makeCircle(d/2.0,Base.Vector(0,0,0),Base.Vector(0,1,0))
        secPerfil=Part.Face(Part.Wire([secPerfil]))
    elif 'Cuad' in tipo:
        d=eval(tipo)[tam]['d']
        secPerfil=Part.makePlane(d,d,Base.Vector(0,0,0),Base.Vector(0,1,0))
    elif 'Rect' in tipo:
        b=eval(tipo)[tam]['b']
        d=eval(tipo)[tam]['d']
        secPerfil=Part.makePlane(b,d,Base.Vector(0,0,0),Base.Vector(0,1,0))
    return secPerfil
def fillet2D(Pini,P2recta1,P1recta2,Pfin,radioConSigno):
    # Devuelve dos segmentos de las rectas definidas por los ptos Pini-P2recta1 y P1recta2-Pfin y el arco de circunferencia de radio igual al valor absoluto de radioConSigno que es tangente a ellas.
    # Pini: pto. 1 de la recta 1, será el 1er pto. de la línea que devuelve la función
    # P2recta1: pto. 2 de la recta 1
    # P1recta2:  pto. 1 de la recta 2
    # Pfin: pto. 2 de la recta 2, será el último pto. de la línea que devuelve la función
    # radioConSigno: radio del arco de circunferencia tangente signo + si de Pini a Pfin gira en el sentido contrario a las agujas del reloj, - en caso contrario.
    signo=radioConSigno/abs(radioConSigno)
    v1=P2recta1.sub(Pini)
    v1.normalize() #vector de dirección de la recta 1
    v2=Pfin.sub(P1recta2)
    v2.normalize() #vector de dirección de la recta 2
    vP1=Base.Vector(-1*signo*v1.y,signo*v1.x)
    vP1.normalize() #vector de dirección perpendicular a la recta 1
    vP1.multiply(abs(radioConSigno))
    vP2=Base.Vector(-1*signo*v2.y,signo*v2.x)
    vP2.normalize() #vector de dirección perpendicular a la recta 2
    vP2.multiply(abs(radioConSigno))
    Paux1=Pini.add(vP1)
    Paux2=Paux1.add(v1)
    Paux3=Pfin.add(vP2)
    Paux4=Paux3.add(v2)
    centro=int2rectas(Paux1,Paux2,Paux3,Paux4)
    vP1.multiply(-1)
    vP2.multiply(-1)
    Pfin1=centro.add(vP1)
    Pini2=centro.add(vP2)
    segm1=Part.makeLine(Pini,Pfin1)
    ang1=angVector2DEjeX(vP1)
    ang2=angVector2DEjeX(vP2)
    if signo==1:
        arco=Part.makeCircle(abs(radioConSigno),centro,Base.Vector(0,0,1),ang1,ang2)
    else:
        arco=Part.makeCircle(abs(radioConSigno),centro,Base.Vector(0,0,1),ang2,ang1)

    segm2=Part.makeLine(Pini2,Pfin)
    linea=Part.Wire([segm1,arco,segm2])
    return linea
Example #28
0
File: fer.py Project: marnout/Fer
	def arcTo(self, alpha, x, y):
		""" a is the start angle of the arc from the current point
		(x, y) is the end point
		draw an arc from the current point to (x, y)
		update the current point
		"""
		a = radians(alpha)
		x0, y0 = self.x, self.y # start point
		self.x, self.y = x, y # update current start point
		p = x*x + y*y - x0*x0 - y0*y0
		q = x0*cos(a) + y0*sin(a)
		d = (x - x0)*sin(a) - (y - y0)*cos(a)
		X = (.5*sin(a)*p - (y-y0)*q) / d # center of arc
		Y = ((x-x0)*q -.5*cos(a)*p) / d
		r = hypot(X - x, Y - y)
		g = (y - y0)*cos(a) - (x - x0)*sin(a)
		a = degrees(copysign(acos((x0 - X)/r), y0 - Y))
		b = degrees(copysign(acos((x - X)/r), y - Y))
		if g > 0:
			e = Part.makeCircle(r, fv(X, Y, 0), fv(0, 0, 1), a, b)
		else: 
			e = Part.makeCircle(r, fv(X, Y, 0), fv(0, 0, 1), b, a)
		self.addEdge(e)
Example #29
0
 def execute(self, fp):
   base=Part.Face(Part.Wire(Part.makeCircle(fp.D/2)))
   if fp.d>0:
     base=base.cut(Part.Face(Part.Wire(Part.makeCircle(fp.d/2))))
   if fp.n>0:
     hole=Part.Face(Part.Wire(Part.makeCircle(fp.f/2,FreeCAD.Vector(fp.df/2,0,0),FreeCAD.Vector(0,0,1))))
     hole.rotate(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),360.0/fp.n/2)
     for i in list(range(fp.n)):
       base=base.cut(hole)
       hole.rotate(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),360.0/fp.n)
   flange = base.extrude(FreeCAD.Vector(0,0,fp.t))
   try: # Flange2: raised-face and welding-neck
     if fp.trf>0 and fp.drf>0:
       rf=Part.makeCylinder(fp.drf/2,fp.trf,vO,vZ*-1).cut(Part.makeCylinder(fp.d/2,fp.trf,vO,vZ*-1))
       flange=flange.fuse(rf)
     if fp.dwn>0 and fp.twn>0 and fp.ODp>0:
       wn=Part.makeCone(fp.dwn/2,fp.ODp/2,fp.twn,vZ*float(fp.t)).cut(Part.makeCylinder(fp.d/2,fp.twn,vZ*float(fp.t)))
       flange=flange.fuse(wn)
   except:
     pass
   fp.Shape = flange
   fp.Ports=[FreeCAD.Vector(),FreeCAD.Vector(0,0,float(fp.t))]
   super(Flange,self).execute(fp) # perform common operations
Example #30
0
def edge_fillet(edges,radius):
	"""
	when given a list of two lines connected lines, returns a list of three
	curves (line, arc, line) corresponding to a filleted edge
	"""
	l1 = edges[0]
	l2 = edges[1]
	assert(l1.Curve.EndPoint == l2.Curve.StartPoint)
	dir1 =l1.Curve.EndPoint - l1.Curve.StartPoint
	dir2 =l2.Curve.EndPoint - l2.Curve.StartPoint

	normal = dir1.cross(dir2)

	raw_angle = math.asin(normal[2]/dir1.Length/dir2.Length)
	#This is the smaller angle enclosed by the two lines in radians
	angle = math.pi - abs(raw_angle)

	#to find the transition points of the fillet, we consider a rectangular
	#triangle with one kathete equal to the radius and the other one lying on
	#one of the input lines with length a
	a = radius/math.tan(0.5*angle)
	#parameter per length
	ppl1 = (l1.Curve.LastParameter-l1.Curve.FirstParameter)/l1.Curve.length()
	ppl2 = (l2.Curve.LastParameter-l2.Curve.FirstParameter)/l2.Curve.length()

	t1 = l1.Curve.value(l1.Curve.LastParameter - a*ppl1)
	t2 = l2.Curve.value(l1.Curve.FirstParameter + a*ppl2)

	#to fine the center of the fillet radius, we construct the angle bisector
	#between the two input lines, and get the distance of the center from the
	#common point by a trigonometric consideration
	bis = Part.makeLine(l1.Curve.EndPoint,(t1+t2).scale(0.5,0.5,0.5))
	pplb = (bis.Curve.LastParameter-bis.Curve.FirstParameter)/bis.Curve.length()
	d = radius/math.sin(0.5*angle)
	center = bis.Curve.value(bis.Curve.FirstParameter + d*pplb)

	#to construct the circle we need start and end angles
	r1 = t1 - center
	r2 = t2 - center
	if raw_angle > 0:
		alpha1 = math.atan2(r1[1],r1[0])*180/math.pi
		alpha2 = math.atan2(r2[1],r2[0])*180/math.pi
	else:
		alpha2 = math.atan2(r1[1],r1[0])*180/math.pi
		alpha1 = math.atan2(r2[1],r2[0])*180/math.pi
		normal *= -1

	return [Part.makeLine(l1.Curve.StartPoint,t1),
		Part.makeCircle(radius,center,normal,alpha1,alpha2),
		Part.makeLine(t2,l2.Curve.EndPoint)]
Example #31
0
def vslot(symmetry, vertices, fillets, corner_offset, circle_offsets):
    outline = assemble(symmetry, vertices)
    outline = fillet(outline, fillets, 1.5)
    outline = Part.Wire(outline)

    holes = []

    # corners
    # x offset, y offset, reverse, switch, mir_x, mir_y
    corner_symmetry = [
        (0, 0, False, False, False, False),
        (corner_offset, 0, False, False, True, False),
        (corner_offset, 0, False, False, True, True),
        (0, 0, False, False, False, True),
    ]

    for sym in corner_symmetry:
        holes.append(Part.Wire(assemble([sym], [vslot_cornerhole])))
        if sym[4] == sym[5]:
            holes[-1].reverse()

    # circular holes
    for offset in circle_offsets:
        holes.append(Part.Wire(Part.makeCircle(2.1, Vector(offset, 0, 0))))
        holes[-1].reverse()

    # big spaces
    print("Space")
    for offset in circle_offsets[:-1]:
        print(space_symmetry, vslot_space)
        holes.append(
            Part.Wire(assemble(space_symmetry, 4 * [vslot_space],
                               (offset, 0))))
        holes[-1].reverse()
    print("Space")

    # put everything together
    return Part.Face([outline] + holes)
Example #32
0
    def execute(self, obj):
        """This method is run when the object is created or recomputed."""
        import Part

        plm = obj.Placement

        shape = Part.makeCircle(obj.Radius.Value, App.Vector(0, 0, 0),
                                App.Vector(0, 0, 1), obj.FirstAngle.Value,
                                obj.LastAngle.Value)

        if obj.FirstAngle.Value == obj.LastAngle.Value:
            shape = Part.Wire(shape)
            if getattr(obj, "MakeFace", True):
                shape = Part.Face(shape)

        obj.Shape = shape

        if hasattr(obj, "Area") and hasattr(shape, "Area"):
            obj.Area = shape.Area

        obj.Placement = plm

        obj.positionBySupport()
Example #33
0
    def execute(self, fp):
        xtotal = fp.xsize.Value * fp.xoccurrences
        ytotal = fp.ysize.Value * fp.yoccurrences

        #App.Console.PrintMessage("xtotal,ytotal:" + str(xtotal) + "," + str(ytotal) + "\n")

        e1 = LineSegment(App.Vector(0, 0, 0), App.Vector(xtotal, 0,
                                                         0)).toShape().Edges[0]
        e2 = LineSegment(App.Vector(xtotal, 0, 0),
                         App.Vector(xtotal, ytotal, 0)).toShape().Edges[0]
        e3 = LineSegment(App.Vector(xtotal, ytotal, 0),
                         App.Vector(0, ytotal, 0)).toShape().Edges[0]
        e4 = LineSegment(App.Vector(0, ytotal, 0),
                         App.Vector(0, 0, 0)).toShape().Edges[0]
        w = Wire([e1, e2, e3, e4])

        #hole
        holes = []
        for i in range(fp.xoccurrences):
            for j in range(fp.yoccurrences):
                holes.append(
                    Part.Wire(
                        Part.makeCircle(
                            fp.holesize.Value / 2,
                            App.Vector(fp.xsize.Value / 2 + i * fp.xsize.Value,
                                       fp.ysize.Value / 2 + j * fp.ysize.Value,
                                       0), App.Vector(0, 0, -1))))

        face = Part.Face([w] + holes)
        baseshape = face.extrude(App.Vector(0, 0, fp.height.Value))
        if fp.fillet.Value > 0:
            borders = []
            for i in range(12):
                borders.append(baseshape.Edges[i])
            fp.Shape = baseshape.makeFillet(fp.fillet.Value, borders)
        else:
            fp.Shape = face.extrude(App.Vector(0, 0, fp.height.Value))
Example #34
0
    def testFuse(self):
        """
        Tests fusing one face to another.
        """
        # Face 1
        edge1 = Part.makeLine((0, 0, 0), (0, 10, 0))
        edge2 = Part.makeLine((0, 10, 0), (10, 10, 0))
        edge3 = Part.makeLine((10, 10, 0), (10, 0, 0))
        edge4 = Part.makeLine((10, 0, 0), (0, 0, 0))
        wire1 = Part.Wire([edge1, edge2, edge3, edge4])
        face1 = Part.Face(wire1)
        cqFace1 = Face(face1)

        # Face 2 (face to cut out of face 1)
        edge1 = Part.makeCircle(4.0)
        wire1 = Part.Wire([edge1])
        face2 = Part.Face(wire1)
        cqFace2 = Face(face2)

        # Face resulting from fuse
        cqFace3 = cqFace1.fuse(cqFace2)

        self.assertEquals(len(cqFace3.Faces()), 3)
        self.assertEquals(len(cqFace3.Edges()), 8)
Example #35
0
    def testIntersect(self):
        """
        Tests finding the intersection of two faces.
        """
        # Face 1
        edge1 = Part.makeLine((0, 0, 0), (0, 10, 0))
        edge2 = Part.makeLine((0, 10, 0), (10, 10, 0))
        edge3 = Part.makeLine((10, 10, 0), (10, 0, 0))
        edge4 = Part.makeLine((10, 0, 0), (0, 0, 0))
        wire1 = Part.Wire([edge1, edge2, edge3, edge4])
        face1 = Part.Face(wire1)
        cqFace1 = Face(face1)

        # Face 2 (face to cut out of face 1)
        edge1 = Part.makeCircle(4.0)
        wire1 = Part.Wire([edge1])
        face2 = Part.Face(wire1)
        cqFace2 = Face(face2)

        # Face resulting from the intersection
        cqFace3 = cqFace1.intersect(cqFace2)

        self.assertEquals(len(cqFace3.Faces()), 1)
        self.assertEquals(len(cqFace3.Edges()), 3)
 def MountingHole(self,yBase,yHeight):
     mhorig = Base.Vector(self.holeorig.x,yBase,self.holeorig.z)
     vthick = Base.Vector(0,yHeight,0)
     YNorm  = Base.Vector(0,1,0)
     hole   = Part.Face(Part.Wire(Part.makeCircle(self.bracketholedia()/2,mhorig,YNorm))).extrude(vthick)
     return hole
def setup(doc=None, solvertype="ccxtools"):
    # setup model

    if doc is None:
        doc = init_doc()

    # parts
    # TODO turn circle of upper tube to have the line on the other side
    # make a boolean fragment of them to be sure there is a mesh point on remesh
    # but as long as we do not remesh it works without the boolean fragment too
    # tubes
    tube_radius = 25
    tube_length = 500
    sh_lower_circle = Part.Wire(Part.makeCircle(tube_radius))
    sh_lower_tube = sh_lower_circle.extrude(FreeCAD.Vector(0, 0, tube_length))
    sh_lower_tube.reverse()
    lower_tube = doc.addObject("Part::Feature", "Lower_tube")
    lower_tube.Shape = sh_lower_tube

    sh_upper_circle = Part.Wire(Part.makeCircle(tube_radius))
    sh_upper_tube = sh_upper_circle.extrude(FreeCAD.Vector(0, 0, tube_length))
    sh_upper_tube.reverse()
    upper_tube = doc.addObject("Part::Feature", "Upper_tube")
    upper_tube.Shape = sh_upper_tube
    upper_tube.Placement = FreeCAD.Placement(
        FreeCAD.Vector(-25, 51, 475),
        FreeCAD.Rotation(90, 0, 90),
        FreeCAD.Vector(0, 0, 0),
    )

    # point for load
    v_force_pt = FreeCAD.Vector(0, 76, 475)
    sh_force_point = Part.Vertex(v_force_pt)
    force_point = doc.addObject("Part::Feature", "Load_place_point")
    force_point.Shape = sh_force_point
    if FreeCAD.GuiUp:
        force_point.ViewObject.PointSize = 10.0
        force_point.ViewObject.PointColor = (1.0, 0.0, 0.0)

    BooleanFrag = BOPTools.SplitFeatures.makeBooleanFragments(
        name='BooleanFragments')
    BooleanFrag.Objects = [upper_tube, force_point]
    if FreeCAD.GuiUp:
        upper_tube.ViewObject.hide()

    compound = doc.addObject("Part::Compound", "Compound")
    compound.Links = [BooleanFrag, lower_tube]

    # line for load direction
    sh_load_line = Part.makeLine(v_force_pt, FreeCAD.Vector(0, 150, 475))
    load_line = doc.addObject("Part::Feature", "Load_direction_line")
    load_line.Shape = sh_load_line
    if FreeCAD.GuiUp:
        load_line.ViewObject.LineWidth = 5.0
        load_line.ViewObject.LineColor = (1.0, 0.0, 0.0)

    doc.recompute()

    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.ActiveDocument.activeView().viewAxonometric()
        FreeCADGui.SendMsgToActiveView("ViewFit")

    # analysis
    analysis = ObjectsFem.makeAnalysis(doc, "Analysis")

    # solver
    if solvertype == "calculix":
        solver_object = analysis.addObject(
            ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0]
    elif solvertype == "ccxtools":
        solver_object = analysis.addObject(
            ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0]
        solver_object.WorkingDir = u""
    if solvertype == "calculix" or solvertype == "ccxtools":
        solver_object.AnalysisType = "static"
        solver_object.BeamShellResultOutput3D = True
        solver_object.GeometricalNonlinearity = "linear"  # really?
        # TODO iterations parameter !!!
        solver_object.ThermoMechSteadyState = False
        solver_object.MatrixSolverType = "default"
        solver_object.IterationsControlParameterTimeUse = False
        solver_object.SplitInputWriter = False

    # shell thickness
    analysis.addObject(
        ObjectsFem.makeElementGeometry2D(doc, 0.5, 'ShellThickness'))

    # material
    material_obj = analysis.addObject(
        ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial"))[0]
    mat = material_obj.Material
    mat["Name"] = "AlCuMgPb"
    mat["YoungsModulus"] = "72000 MPa"
    mat["PoissonRatio"] = "0.30"
    material_obj.Material = mat
    analysis.addObject(material_obj)

    # fixed_constraint
    fixed_constraint = analysis.addObject(
        ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed"))[0]
    fixed_constraint.References = [
        (lower_tube, "Edge2"),
        (upper_tube, "Edge3"),
    ]

    # force_constraint
    force_constraint = doc.Analysis.addObject(
        ObjectsFem.makeConstraintForce(doc, name="ConstraintForce"))[0]
    # TODO use point of tube boolean fragment
    force_constraint.References = [(force_point, "Vertex1")]
    force_constraint.Force = 5000.0
    force_constraint.Direction = (load_line, ["Edge1"])
    force_constraint.Reversed = True

    # contact constraint
    contact_constraint = doc.Analysis.addObject(
        ObjectsFem.makeConstraintContact(doc, name="ConstraintContact"))[0]
    contact_constraint.References = [
        (lower_tube, "Face1"),
        (upper_tube, "Face1"),
    ]
    contact_constraint.Friction = 0.0
    # contact_constrsh_aint.Slope = "1000000.0 kg/(mm*s^2)"  # contact stiffness
    contact_constraint.Slope = 1000000.0  # should be 1000000.0 kg/(mm*s^2)

    # mesh
    from .meshes.mesh_contact_tube_tube_tria3 import create_nodes, create_elements
    fem_mesh = Fem.FemMesh()
    control = create_nodes(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating nodes.\n")
    control = create_elements(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating elements.\n")
    femmesh_obj = analysis.addObject(
        doc.addObject("Fem::FemMeshObject", mesh_name))[0]
    femmesh_obj.FemMesh = fem_mesh

    doc.recompute()
    return doc
Example #38
0
 def getDeviation(self):
     "returns a deviation vector that represents the base of the circle"
     import Part
     c = Part.makeCircle(1,Vector(0,0,0),self.normal)
     return c.Vertexes[0].Point
 def __init__(self, name, origin):
     self.name = name
     if not isinstance(origin, Base.Vector):
         raise RuntimeError("origin is not a Vector")
     self.origin = origin
     ox = origin.x
     oy = origin.y
     oz = origin.z
     boardsurf = Part.makePlane(PCBwithStrips._psPCBwidth,
                                PCBwithStrips._psPCBlength, origin)
     xh = (ox + PCBwithStrips._stripIncr)
     while xh <= ox + PCBwithStrips._psPCBwidth:
         yh = oy + PCBwithStrips._stripIncr
         while yh <= oy + PCBwithStrips._psPCBlength:
             boardsurf = self._drill_leadhole(boardsurf, xh, yh, oz)
             yh += PCBwithStrips._stripIncr
         xh += PCBwithStrips._stripIncr
     self.mhvector = {
         1:
         Base.Vector(ox + PCBwithStrips._stripIncr,
                     oy + (PCBwithStrips._stripIncr + 5 * 2.54), oz),
         2:
         Base.Vector(
             ox + (PCBwithStrips._psPCBwidth - PCBwithStrips._stripIncr),
             oy + (PCBwithStrips._stripIncr + 5 * 2.54), oz),
         3:
         Base.Vector(
             ox + PCBwithStrips._stripIncr,
             oy + (PCBwithStrips._psPCBlength -
                   (PCBwithStrips._stripIncr + 5 * 2.54)), oz),
         4:
         Base.Vector(
             ox + (PCBwithStrips._psPCBwidth - PCBwithStrips._stripIncr),
             oy + (PCBwithStrips._psPCBlength -
                   (PCBwithStrips._stripIncr + 5 * 2.54)), oz)
     }
     mh1circ = Part.makeCircle(PCBwithStrips._mhdia / 2.0, self.mhvector[1])
     mh1wire = Part.Wire(mh1circ)
     mh1 = Part.Face(mh1wire)
     boardsurf = boardsurf.cut(mh1)
     mh2circ = Part.makeCircle(PCBwithStrips._mhdia / 2.0, self.mhvector[2])
     mh2wire = Part.Wire(mh2circ)
     mh2 = Part.Face(mh2wire)
     boardsurf = boardsurf.cut(mh2)
     mh3circ = Part.makeCircle(PCBwithStrips._mhdia / 2.0, self.mhvector[3])
     mh3wire = Part.Wire(mh3circ)
     mh3 = Part.Face(mh3wire)
     boardsurf = boardsurf.cut(mh3)
     mh4circ = Part.makeCircle(PCBwithStrips._mhdia / 2.0, self.mhvector[4])
     mh4wire = Part.Wire(mh4circ)
     mh4 = Part.Face(mh4wire)
     boardsurf = boardsurf.cut(mh4)
     self.board = boardsurf.extrude(
         Base.Vector(0, 0, PCBwithStrips._psPCBThickness))
     mh = {
         1:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     PCBwithStrips._mhdia / 2.0,
                     Base.Vector(self.mhvector[1].x, self.mhvector[1].y,
                                 oz - PCBwithStrips._stripThickness)))),
         2:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     PCBwithStrips._mhdia / 2.0,
                     Base.Vector(self.mhvector[2].x, self.mhvector[2].y,
                                 oz - PCBwithStrips._stripThickness)))),
         3:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     PCBwithStrips._mhdia / 2.0,
                     Base.Vector(self.mhvector[3].x, self.mhvector[3].y,
                                 oz - PCBwithStrips._stripThickness)))),
         4:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     PCBwithStrips._mhdia / 2.0,
                     Base.Vector(self.mhvector[4].x, self.mhvector[4].y,
                                 oz - PCBwithStrips._stripThickness))))
     }
     yoff = (PCBwithStrips._psPCBlength - PSK_S15C._pslength) / 2.0
     xoff = (PCBwithStrips._psPCBwidth - PSK_S15C._pswidth) / 2.0
     pin1X = PSK_S15C._pspin1Yoff + xoff
     pin2X = PSK_S15C._pspin2Yoff + xoff
     sx = PCBwithStrips._stripIncr
     self.strips = list()
     while (sx + PCBwithStrips._stripIncr) <= PCBwithStrips._psPCBwidth:
         if sx <= pin1X and sx >= pin2X:
             stripCP1 = Base.Vector(
                 ox + (sx - (PCBwithStrips._stripWidth / 2.0)),
                 oy + PCBwithStrips._stripOffset,
                 oz - PCBwithStrips._stripThickness)
             stripCP2 = Base.Vector(
                 ox + (sx - (PCBwithStrips._stripWidth / 2.0)), oy +
                 (PCBwithStrips._stripOffset + yoff + PSK_S15C._pspin1Xoff -
                  PCBwithStrips._stripExtra - 2.54),
                 oz - PCBwithStrips._stripThickness)
             striplen = yoff + PSK_S15C._pspin4Xoff + PCBwithStrips._stripExtra
             stripsurf = Part.makePlane(PCBwithStrips._stripWidth, striplen,
                                        stripCP1)
             xh = stripCP1.x + (PCBwithStrips._stripWidth / 2.0)
             yh = stripCP1.y + PCBwithStrips._stripOffset
             while yh < stripCP1.y + striplen:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP1.z)
                 yh += PCBwithStrips._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, PCBwithStrips._stripThickness))
             self.strips.append(strip)
             stripsurf = Part.makePlane(PCBwithStrips._stripWidth, striplen,
                                        stripCP2)
             xh = stripCP2.x + (PCBwithStrips._stripWidth / 2.0)
             yh = stripCP2.y + PCBwithStrips._stripOffset
             while yh < stripCP2.y + striplen:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP2.z)
                 yh += PCBwithStrips._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, PCBwithStrips._stripThickness))
             self.strips.append(strip)
         else:
             stripCP = Base.Vector(
                 ox + (sx - (PCBwithStrips._stripWidth / 2.0)),
                 oy + PCBwithStrips._stripOffset,
                 oz - PCBwithStrips._stripThickness)
             stripsurf = Part.makePlane(
                 PCBwithStrips._stripWidth, PCBwithStrips._psPCBlength -
                 (PCBwithStrips._stripOffset * 2), stripCP)
             xh = stripCP.x + (PCBwithStrips._stripWidth / 2.0)
             yh = stripCP.y + PCBwithStrips._stripOffset
             while yh < stripCP.y + PCBwithStrips._psPCBlength - (
                     PCBwithStrips._stripOffset * 2):
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP.z)
                 yh += PCBwithStrips._stripIncr
             i = 1
             while i <= 4:
                 h = self.mhvector[i]
                 stripsurf = stripsurf.cut(mh[i])
                 i += 1
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, PCBwithStrips._stripThickness))
             self.strips.append(strip)
         sx += PCBwithStrips._stripIncr
 def MountingHole(self, i, zBase):
     mhv = self.mhvector[i]
     mhz = Base.Vector(mhv.x, mhv.y, zBase)
     mhcirc = Part.makeCircle(self._mhdia / 2.0, mhz)
     mhwire = Part.Wire(mhcirc)
     return Part.Face(mhwire)
 def _drill_leadhole(self, surf, x, y, z):
     return (surf.cut(
         Part.Face(
             Part.Wire(
                 Part.makeCircle(self._leadhole_r, Base.Vector(x, y, z))))))
Example #42
0
	def runmode2(self, fp, prop):

		f=fp.source.Shape.Faces[fp.faceNumber-1]
		nf=f.toNurbs()

		ff=nf.Face1
		ff.ParameterRange

		sf=ff.Surface

		u=0.01*fp.u
		v=0.01*fp.v

		p=sf.value(u,v)
		[t1,t2]=sf.tangent(u,v)
		sf.parameter(t1)
		sf.parameter(t2)

		c1,c2=sf.curvatureDirections(u,v)

		cmax=sf.curvature(u,v,"Max")
		cmin=sf.curvature(u,v,"Min")

		if cmax <>0:
			rmax=1.0/cmax
		else:
			rmax=0 

		if cmin <>0:
			rmin=1.0/cmin
		else:
			rmin=0

		n=sf.normal(u,v)

		if rmax>fp.maxRadius:
			rmax=fp.maxRadius
			cmax=0
		if rmax<-fp.maxRadius:
			rmax=-fp.maxRadius
			cmax=0
		if rmin>fp.maxRadius:
			rmin=fp.maxRadius
			cmin=0
		if rmin<-fp.maxRadius:
			rmin=-fp.maxRadius
			cmin=0

		m2=p+n*rmin 
		m1=p+n*rmax 

		pts=[p,m2,p,m1]
		print (rmin,rmax)
		comp=[]

		try:
			comp +=[Part.makePolygon([p,m2])]
		except:
			pass

		try:
			comp += [Part.makePolygon([p,m1])]
		except:
			pass

		k=fp.maxRadius


		if cmax==0:
			c=Part.makePolygon([p-c1*k,p+c1*k])
		else:	
			c=Part.makeCircle(abs(rmax),m1,c2)

		comp += [c]

		if cmin==0:
			c=Part.makePolygon([p-c2*k,p+c2*k])
		else:	
			c=Part.makeCircle(abs(rmin),m2,c1)

		comp += [c]

		print "done"
		fp.Shape=Part.Compound(comp)
 def __init__(self, name, origin):
     PCBwithStrips.__init__(self, name, origin)
     ox = origin.x
     oy = origin.y
     oz = origin.z
     yoff = (PCBwithStrips._psPCBlength - PSK_S15C._pslength) / 2.0
     xoff = (PCBwithStrips._psPCBwidth - PSK_S15C._pswidth) / 2.0
     psorigin = Base.Vector(ox + xoff, oy + yoff,
                            oz + PCBwithStrips._psPCBThickness)
     self.powersupply = PSK_S15C(name + "_powersupply", psorigin)
     actermorigin = Base.Vector(
         ox + (PCBwithStrips._psPCBwidth - PCBwithStrips._psactermyoff -
               TB007_508_03BE.Length()),
         oy + (PCBwithStrips._psPCBlength - PCBwithStrips._pstermxoff -
               TB007_508_xxBE._termwidth),
         oz + PCBwithStrips._psPCBThickness)
     self.acterm = TB007_508_03BE(name + "_acterm", actermorigin)
     dctermorigin = Base.Vector(
         ox + (PCBwithStrips._psPCBwidth - PCBwithStrips._psdctermyoff -
               TB007_508_02BE.Length()), oy + (PCBwithStrips._pstermxoff),
         oz + PCBwithStrips._psPCBThickness)
     self.dcterm = TB007_508_02BE(name + "_dcterm", dctermorigin)
     self.bypasscap = C333(
         name + "_bypasscap",
         Base.Vector(ox + PSOnPCB._bypassY, oy + PSOnPCB._bypassX, oz))
     self.filtercap = AL_CAP_Radial_5mm10x12_5(
         name + "_filtercap",
         Base.Vector(ox + PSOnPCB._filterY, oy + PSOnPCB._filterX,
                     oz + PCBwithStrips._psPCBThickness))
     self.esd = DO_15_bendedLeads_400_under(
         name + "_esd",
         Base.Vector(ox + PSOnPCB._esdY, oy + PSOnPCB._esdX, oz))
     self.fuseholder = Littlefuse_FuseHolder_02810007H_02810010H(
         name + "_fuseholder",
         Base.Vector(ox + PSOnPCB._fuseholderY, oy + PSOnPCB._fuseholderX,
                     oz + PCBwithStrips._psPCBThickness))
     self.mov = B72220S2301K101(
         name + "_mov",
         Base.Vector(
             ox + (PCBwithStrips._psPCBwidth / 2.0),
             oy + ((PCBwithStrips._psPCBlength -
                    (yoff + PSK_S15C._pspin3Xoff + 3) + 3.81)), oz))
     groundj1X = oy + ((PCBwithStrips._psPCBlength / 2.0))
     groundj1Y = ox + ((PSK_S15C._pspin1Yoff) + yoff)
     groundj1L = 20.32 + 5.08
     wireradius = PSOnPCB._wiredia / 2.0
     XNorm = Base.Vector(1, 0, 0)
     YNorm = Base.Vector(0, 1, 0)
     self.groundwires = list()
     g1 = Part.Face(
         Part.Wire(
             Part.makeCircle(
                 wireradius,
                 Base.Vector(groundj1Y, groundj1X, oz - wireradius),
                 XNorm))).extrude(Base.Vector(-groundj1L, 0, 0))
     self.groundwires.append(g1)
     for i in [1, 2, 3]:
         yy = i * 2.54
         xx = (i & 1) * 2.54
         y1 = groundj1Y + yy
         y2 = groundj1Y - groundj1L - yy
         x = groundj1X - xx
         gA = Part.Face(
             Part.Wire(
                 Part.makeCircle(wireradius,
                                 Base.Vector(y1, x, oz - wireradius),
                                 XNorm))).extrude(Base.Vector(-2.54, 0, 0))
         gB = Part.Face(
             Part.Wire(
                 Part.makeCircle(wireradius,
                                 Base.Vector(y2, x, oz - wireradius),
                                 XNorm))).extrude(Base.Vector(2.54, 0, 0))
         self.groundwires.append(gA)
         self.groundwires.append(gB)
     self.linewires = list()
     l1Y = ox + PCBwithStrips._psactermyoff + (7 * 2.54)
     l1X = oy + PCBwithStrips._psPCBlength - (5.08 + 2.54)
     l1L = 5.08
     l1 = Part.Face(
         Part.Wire(
             Part.makeCircle(wireradius,
                             Base.Vector(l1Y, l1X, oz - wireradius),
                             XNorm))).extrude(Base.Vector(l1L, 0, 0))
     self.linewires.append(l1)
     l2Y = l1Y - 5.08 - 5.08
     l2X = oy + PCBwithStrips._psPCBlength - 5.08
     l2L = 5.08
     l2 = Part.Face(
         Part.Wire(
             Part.makeCircle(wireradius,
                             Base.Vector(l2Y, l2X, oz - wireradius),
                             XNorm))).extrude(Base.Vector(l2L, 0, 0))
     self.linewires.append(l2)
     self.minuswires = list()
     M1Y = ox + PCBwithStrips._psdctermyoff + (5 * 2.54)
     M1X = oy + PCBwithStrips._pstermxoff + (TB007_508_xxBE._termwidth /
                                             2.0) + 2.54
     M1L = 5.08
     m1 = Part.Face(
         Part.Wire(
             Part.makeCircle(wireradius,
                             Base.Vector(M1Y, M1X, oz - wireradius),
                             XNorm))).extrude(Base.Vector(M1L, 0, 0))
     self.minuswires.append(m1)
     M2Y = M1Y - M1L - 2.54
     M2X = M1X + 2.54
     M2L = 7.62
     m2 = Part.Face(
         Part.Wire(
             Part.makeCircle(wireradius,
                             Base.Vector(M2Y, M2X, oz - wireradius),
                             XNorm))).extrude(Base.Vector(M2L, 0, 0))
     self.minuswires.append(m2)
     self.pluswires = list()
     P1Y = ox + PCBwithStrips._psdctermyoff + 5.08 + 5.08
     P1X = M2X + 2.54
     P1L = 2.54 * 5
     p1 = Part.Face(
         Part.Wire(
             Part.makeCircle(wireradius,
                             Base.Vector(P1Y, P1X, oz - wireradius),
                             XNorm))).extrude(Base.Vector(P1L, 0, 0))
     self.pluswires.append(p1)
Example #44
0
 def onChanged(self, vobj, prop):
     if prop == "LineColor":
         l = vobj.LineColor
         self.mat.diffuseColor.setValue([l[0], l[1], l[2]])
     elif prop == "DrawStyle":
         if vobj.DrawStyle == "Solid":
             self.linestyle.linePattern = 0xffff
         elif vobj.DrawStyle == "Dashed":
             self.linestyle.linePattern = 0xf00f
         elif vobj.DrawStyle == "Dotted":
             self.linestyle.linePattern = 0x0f0f
         else:
             self.linestyle.linePattern = 0xff88
     elif prop == "LineWidth":
         self.linestyle.lineWidth = vobj.LineWidth
     elif prop in ["BubbleSize", "BubblePosition", "FontName", "FontSize"]:
         if hasattr(self, "bubbleset"):
             if self.bubbles:
                 self.bubbleset.removeChild(self.bubbles)
                 self.bubbles = None
             if vobj.Object.Shape:
                 if vobj.Object.Shape.Edges:
                     self.bubbles = coin.SoSeparator()
                     self.bubblestyle = coin.SoDrawStyle()
                     self.bubblestyle.linePattern = 0xffff
                     self.bubbles.addChild(self.bubblestyle)
                     import Part, Draft
                     self.bubbletexts = []
                     pos = ["Start"]
                     if hasattr(vobj, "BubblePosition"):
                         if vobj.BubblePosition == "Both":
                             pos = ["Start", "End"]
                         elif vobj.BubblePosition == "None":
                             pos = []
                         else:
                             pos = [vobj.BubblePosition]
                     for i in range(len(vobj.Object.Shape.Edges)):
                         for p in pos:
                             verts = vobj.Object.Shape.Edges[i].Vertexes
                             if p == "Start":
                                 p1 = verts[0].Point
                                 p2 = verts[1].Point
                             else:
                                 p1 = verts[1].Point
                                 p2 = verts[0].Point
                             dv = p2.sub(p1)
                             dv.normalize()
                             if hasattr(vobj.BubbleSize, "Value"):
                                 rad = vobj.BubbleSize.Value / 2
                             else:
                                 rad = vobj.BubbleSize / 2
                             center = p2.add(dv.scale(rad, rad, rad))
                             buf = Part.makeCircle(rad,
                                                   center).writeInventor()
                             try:
                                 cin = coin.SoInput()
                                 cin.setBuffer(buf)
                                 cob = coin.SoDB.readAll(cin)
                             except:
                                 import re
                                 # workaround for pivy SoInput.setBuffer() bug
                                 buf = buf.replace("\n", "")
                                 pts = re.findall("point \[(.*?)\]", buf)[0]
                                 pts = pts.split(",")
                                 pc = []
                                 for p in pts:
                                     v = p.strip().split()
                                     pc.append([
                                         float(v[0]),
                                         float(v[1]),
                                         float(v[2])
                                     ])
                                 coords = coin.SoCoordinate3()
                                 coords.point.setValues(0, len(pc), pc)
                                 line = coin.SoLineSet()
                                 line.numVertices.setValue(-1)
                             else:
                                 coords = cob.getChild(1).getChild(
                                     0).getChild(2)
                                 line = cob.getChild(1).getChild(
                                     0).getChild(3)
                             self.bubbles.addChild(coords)
                             self.bubbles.addChild(line)
                             st = coin.SoSeparator()
                             tr = coin.SoTransform()
                             fs = rad * 1.5
                             if hasattr(vobj, "FontSize"):
                                 fs = vobj.FontSize.Value
                             tr.translation.setValue(
                                 (center.x, center.y - fs / 2.5, center.z))
                             fo = coin.SoFont()
                             fn = Draft.getParam("textfont", "Arial,Sans")
                             if hasattr(vobj, "FontName"):
                                 if vobj.FontName:
                                     try:
                                         fn = str(vobj.FontName)
                                     except:
                                         pass
                             fo.name = fn
                             fo.size = fs
                             tx = coin.SoAsciiText()
                             tx.justification = coin.SoText2.CENTER
                             self.bubbletexts.append(tx)
                             st.addChild(tr)
                             st.addChild(fo)
                             st.addChild(tx)
                             self.bubbles.addChild(st)
                     self.bubbleset.addChild(self.bubbles)
                     self.onChanged(vobj, "NumberingStyle")
         if prop in ["FontName", "FontSize"]:
             self.onChanged(vobj, "ShowLabel")
     elif prop in ["NumberingStyle", "StartNumber"]:
         if hasattr(self, "bubbletexts"):
             chars = "abcdefghijklmnopqrstuvwxyz"
             roman = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400),
                      ('C', 100), ('XC', 90), ('L', 50), ('XL', 40),
                      ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1))
             num = 0
             if hasattr(vobj, "StartNumber"):
                 if vobj.StartNumber > 1:
                     num = vobj.StartNumber - 1
             alt = False
             for t in self.bubbletexts:
                 if hasattr(vobj, "NumberingStyle"):
                     if vobj.NumberingStyle == "1,2,3":
                         t.string = str(num + 1)
                     elif vobj.NumberingStyle == "01,02,03":
                         t.string = str(num + 1).zfill(2)
                     elif vobj.NumberingStyle == "001,002,003":
                         t.string = str(num + 1).zfill(3)
                     elif vobj.NumberingStyle == "A,B,C":
                         result = ""
                         base = num / 26
                         if base:
                             result += chars[base].upper()
                         remainder = num % 26
                         result += chars[remainder].upper()
                         t.string = result
                     elif vobj.NumberingStyle == "a,b,c":
                         result = ""
                         base = num / 26
                         if base:
                             result += chars[base]
                         remainder = num % 26
                         result += chars[remainder]
                         t.string = result
                     elif vobj.NumberingStyle == "I,II,III":
                         result = ""
                         n = num
                         n += 1
                         for numeral, integer in roman:
                             while n >= integer:
                                 result += numeral
                                 n -= integer
                         t.string = result
                     elif vobj.NumberingStyle == "L0,L1,L2":
                         t.string = "L" + str(num)
                 else:
                     t.string = str(num + 1)
                 num += 1
                 if hasattr(vobj, "BubblePosition"):
                     if vobj.BubblePosition == "Both":
                         if not alt:
                             num -= 1
                 alt = not alt
     elif prop in ["ShowLabel", "LabelOffset"]:
         if hasattr(self, "labels"):
             if self.labels:
                 self.labelset.removeChild(self.labels)
         self.labels = None
         if hasattr(vobj, "ShowLabel") and hasattr(vobj.Object, "Labels"):
             if vobj.ShowLabel:
                 self.labels = coin.SoSeparator()
                 for i in range(len(vobj.Object.Shape.Edges)):
                     if len(vobj.Object.Labels) > i:
                         if vobj.Object.Labels[i]:
                             import Draft
                             vert = vobj.Object.Shape.Edges[i].Vertexes[
                                 0].Point
                             if hasattr(vobj, "LabelOffset"):
                                 pl = FreeCAD.Placement(vobj.LabelOffset)
                                 pl.Base = vert.add(pl.Base)
                             st = coin.SoSeparator()
                             tr = coin.SoTransform()
                             fo = coin.SoFont()
                             tx = coin.SoAsciiText()
                             tx.justification = coin.SoText2.LEFT
                             t = vobj.Object.Labels[i]
                             if isinstance(t, unicode):
                                 t = t.encode("utf8")
                             tx.string.setValue(t)
                             if hasattr(vobj, "FontSize"):
                                 fs = vobj.FontSize.Value
                             elif hasattr(vobj.BubbleSize, "Value"):
                                 fs = vobj.BubbleSize.Value * 0.75
                             else:
                                 fs = vobj.BubbleSize * 0.75
                             tr.translation.setValue(tuple(pl.Base))
                             tr.rotation.setValue(pl.Rotation.Q)
                             fn = Draft.getParam("textfont", "Arial,Sans")
                             if hasattr(vobj, "FontName"):
                                 if vobj.FontName:
                                     try:
                                         fn = str(vobj.FontName)
                                     except:
                                         pass
                             fo.name = fn
                             fo.size = fs
                             st.addChild(tr)
                             st.addChild(fo)
                             st.addChild(tx)
                             self.labels.addChild(st)
                 self.labelset.addChild(self.labels)
Example #45
0
    def updateData(self, obj, prop):
        if hasattr(self, "arc"):
            from pivy import coin
            import Part, DraftGeomUtils
            import DraftGui
            arcsegs = 24

            # calculate the arc data
            if DraftVecUtils.isNull(obj.Normal):
                norm = App.Vector(0, 0, 1)
            else:
                norm = obj.Normal
            radius = (obj.Dimline.sub(obj.Center)).Length
            self.circle = Part.makeCircle(radius, obj.Center, norm,
                                          obj.FirstAngle.Value,
                                          obj.LastAngle.Value)
            self.p2 = self.circle.Vertexes[0].Point
            self.p3 = self.circle.Vertexes[-1].Point
            mp = DraftGeomUtils.findMidpoint(self.circle.Edges[0])
            ray = mp.sub(obj.Center)

            # set text value
            if obj.LastAngle.Value > obj.FirstAngle.Value:
                a = obj.LastAngle.Value - obj.FirstAngle.Value
            else:
                a = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value
            su = True
            if hasattr(obj.ViewObject, "ShowUnit"):
                su = obj.ViewObject.ShowUnit
            if hasattr(obj.ViewObject, "Decimals"):
                self.string = DraftGui.displayExternal(a,
                                                       obj.ViewObject.Decimals,
                                                       'Angle', su)
            else:
                self.string = DraftGui.displayExternal(a, None, 'Angle', su)
            if obj.ViewObject.Override:
                self.string = obj.ViewObject.Override.replace("$dim",\
                    self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(
                self.string)

            # check display mode
            try:
                m = obj.ViewObject.DisplayMode
            except:  # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D", "3D"][utils.get_param("dimstyle", 0)]

            # set the arc
            if m == "3D":
                # calculate the spacing of the text
                spacing = (len(self.string) *
                           obj.ViewObject.FontSize.Value) / 8.0
                pts1 = []
                cut = None
                pts2 = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    if (p.sub(mp)).Length <= spacing:
                        if cut is None:
                            cut = i
                    else:
                        if cut is None:
                            pts1.append([p.x, p.y, p.z])
                        else:
                            pts2.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts1 + pts2)
                i1 = len(pts1)
                i2 = i1 + len(pts2)
                self.arc.coordIndex.setValues(
                    0,
                    len(pts1) + len(pts2) + 1,
                    list(range(len(pts1))) + [-1] + list(range(i1, i2)))
                if (len(pts1) >= 3) and (len(pts2) >= 3):
                    self.circle1 = Part.Arc(
                        App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]),
                        App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]),
                        App.Vector(pts1[-1][0], pts1[-1][1],
                                   pts1[-1][2])).toShape()
                    self.circle2 = Part.Arc(
                        App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]),
                        App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]),
                        App.Vector(pts2[-1][0], pts2[-1][1],
                                   pts2[-1][2])).toShape()
            else:
                pts = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    pts.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts)
                self.arc.coordIndex.setValues(0, arcsegs + 1,
                                              list(range(arcsegs + 1)))

            # set the arrow coords and rotation
            self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z))
            self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z))
            # calculate small chords to make arrows look better
            arrowlength = 4 * obj.ViewObject.ArrowSize.Value
            u1 = (self.circle.valueAt(self.circle.FirstParameter + arrowlength)
                  ).sub(self.circle.valueAt(
                      self.circle.FirstParameter)).normalize()
            u2 = (self.circle.valueAt(self.circle.LastParameter)).sub(
                self.circle.valueAt(self.circle.LastParameter -
                                    arrowlength)).normalize()
            if hasattr(obj.ViewObject, "FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u1 = u1.negative()
                    u2 = u2.negative()
            w2 = self.circle.Curve.Axis
            w1 = w2.negative()
            v1 = w1.cross(u1)
            v2 = w2.cross(u2)
            q1 = App.Placement(DraftVecUtils.getPlaneRotation(u1, v1,
                                                              w1)).Rotation.Q
            q2 = App.Placement(DraftVecUtils.getPlaneRotation(u2, v2,
                                                              w2)).Rotation.Q
            self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
            self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))

            # setting text pos & rot
            self.tbase = mp
            if hasattr(obj.ViewObject, "TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition

            u3 = ray.cross(norm).normalize()
            v3 = norm.cross(u3)
            r = App.Placement(DraftVecUtils.getPlaneRotation(u3, v3,
                                                             norm)).Rotation
            offset = r.multVec(App.Vector(0, 1, 0))

            if hasattr(obj.ViewObject, "TextSpacing"):
                offset = DraftVecUtils.scaleTo(
                    offset, obj.ViewObject.TextSpacing.Value)
            else:
                offset = DraftVecUtils.scaleTo(offset, 0.05)
            if m == "3D":
                offset = offset.negative()
            self.tbase = self.tbase.add(offset)
            q = r.Q
            self.textpos.translation.setValue(
                [self.tbase.x, self.tbase.y, self.tbase.z])
            self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3])

            # set the angle property
            if round(obj.Angle, utils.precision()) != round(
                    a, utils.precision()):
                obj.Angle = a
 def USBJackCutoutHole(self,xPanel):
     cutoutOrig = self.origin.add(Base.Vector(-40,\
                       self._FeatherYUSB_Offset+self._FeatherYBoardOffset,\
                       62.5 + 196.5 + 100 + 62.5))
     cutoutOrig = Base.Vector(xPanel,cutoutOrig.y+110,cutoutOrig.z+55)
     return Part.Face(Part.Wire(Part.makeCircle(175,cutoutOrig,Base.Vector(1,0,0))))
Example #47
0
    def execute(self, obj):

        if self.clone(obj):
            return

        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].Shape:
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.InList[0]
        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print obj.Rounding
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        size = (ArchCommands.projectToVector(father.Shape.copy(), axis)).Length
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)  #.normalize()
                # don't normalize so the vector can also be used to determine the distance
                size = axis.Length
        #print axis
        #print size
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return

        # all tests ok!
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
        except Part.OCCError:
            print "Arch: error sweeping rebar profile along the base sketch"
            return
        # building final shape
        shapes = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis, size / 2)
            bar.translate(offset)
            shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis, interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        bar.translate(baseoffset)
                    shapes.append(bar)
                else:
                    bar = bar.copy()
                    bar.translate(vinterval)
                    shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
Example #48
0
    def execute(self, obj):

        if self.clone(obj):
            return
        if not obj.Base and ((not obj.Shape) or (not obj.Shape.isNull())):
            # let pass without error if we already have a shape
            return
        if not obj.Base:
            FreeCAD.Console.PrintError(
                "No Base, return without a rebar shape for {}.\n".format(
                    obj.Name))
            return
        if not hasattr(obj.Base, "Shape") or (
                not obj.Base.Shape) or obj.Base.Shape.isNull():
            FreeCAD.Console.PrintError(
                "No Shape in Base, return without a rebar shape for {}.\n".
                format(obj.Name))
            return
        if obj.Base.Shape.Faces:
            FreeCAD.Console.PrintError(
                "Faces in Shape of Base, return without a rebar shape for {}.\n"
                .format(obj.Name))
            return
        if not obj.Base.Shape.Edges:
            FreeCAD.Console.PrintError(
                "No Edges in Shape of Base, return without a rebar shape for {}.\n"
                .format(obj.Name))
            return
        if not obj.Diameter.Value:
            FreeCAD.Console.PrintError(
                "No Diameter Value, return without a rebar shape for {}.\n".
                format(obj.Name))
            return
        if not obj.Amount:
            FreeCAD.Console.PrintError(
                "No Amount, return without a rebar shape for {}.\n".format(
                    obj.Name))
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0], "Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if hasattr(father, 'Shape'):
                fathershape = father.Shape

        import Part
        # corner cases:
        #    compound from more Wires
        #    compound without Wires but with multiple Edges
        # Does they make sense? If yes handle them.
        # Does it makes sense to handle Shapes with Faces or even Solids?
        if not obj.Base.Shape.Wires and len(obj.Base.Shape.Edges) == 1:
            wire = Part.Wire(obj.Base.Shape.Edges[0])
        else:
            wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print(obj.Rounding)
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                from DraftGeomUtils import filletWire
                wire = filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        if fathershape:
            size = (ArchCommands.projectToVector(fathershape.copy(),
                                                 axis)).Length
        else:
            size = 1
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
                if fathershape:
                    size = (ArchCommands.projectToVector(
                        fathershape.copy(), axis)).Length
                else:
                    size = 1
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        spacinglist = None
        if hasattr(obj, "CustomSpacing"):
            if obj.CustomSpacing:
                spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing)
                influenceArea = sum(
                    spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2
        # Drop this check to solve issue as discussed here: https://github.com/FreeCAD/FreeCAD/pull/2550
        # if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
        #        return
        # all tests ok!
        if hasattr(obj, "Length"):
            length = getLengthOfRebar(obj)
            if length:
                obj.Length = length
        pl = obj.Placement
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
            basewire = wire.copy()
        except Part.OCCError:
            print("Arch: error sweeping rebar profile along the base sketch")
            return
        # building final shape
        shapes = []
        placementlist = []
        self.wires = []
        rot = FreeCAD.Rotation()
        if obj.Amount == 1:
            if hasattr(obj, "RebarShape"):
                barplacement = CalculatePlacement(
                    obj.Amount, 1, obj.Diameter.Value, size, axis, rot,
                    obj.OffsetStart.Value, obj.OffsetEnd.Value, obj.RebarShape)
            else:
                barplacement = CalculatePlacement(obj.Amount, 1,
                                                  obj.Diameter.Value, size,
                                                  axis, rot,
                                                  obj.OffsetStart.Value,
                                                  obj.OffsetEnd.Value)
            placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            if hasattr(obj, "RebarShape") and obj.RebarShape == "Stirrup":
                interval = size - (obj.OffsetStart.Value +
                                   obj.OffsetEnd.Value + obj.Diameter.Value)
            else:
                interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            for i in range(obj.Amount):
                if hasattr(obj, "RebarShape"):
                    barplacement = CalculatePlacement(obj.Amount, i + 1,
                                                      obj.Diameter.Value, size,
                                                      axis, rot,
                                                      obj.OffsetStart.Value,
                                                      obj.OffsetEnd.Value,
                                                      obj.RebarShape)
                else:
                    barplacement = CalculatePlacement(obj.Amount, i + 1,
                                                      obj.Diameter.Value, size,
                                                      axis, rot,
                                                      obj.OffsetStart.Value,
                                                      obj.OffsetEnd.Value)
                placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        # Calculate placement of bars from custom spacing.
        if spacinglist:
            placementlist[:] = []
            if hasattr(obj, "RebarShape") and obj.RebarShape == "Stirrup":
                reqInfluenceArea = size - (obj.OffsetStart.Value +
                                           obj.OffsetEnd.Value +
                                           obj.Diameter.Value)
            else:
                reqInfluenceArea = size - (obj.OffsetStart.Value +
                                           obj.OffsetEnd.Value)
            # Avoid unnecessary checks to pass like. For eg.: when we have values
            # like influenceArea is 100.00001 and reqInflueneArea is 100
            if round(influenceArea) > round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Influence area of rebars is greater than " +
                    str(reqInfluenceArea) + ".\n")
            elif round(influenceArea) < round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Last span is greater that end offset.\n")
            for i in range(len(spacinglist)):
                if i == 0:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
                else:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, i + 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
            obj.Amount = len(spacinglist)
            obj.Spacing = 0
        obj.PlacementList = placementlist
        for i in range(len(obj.PlacementList)):
            if i == 0:
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                basewire.Placement = obj.PlacementList[i]
                self.wires.append(basewire)
            else:
                bar = bar.copy()
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                w = basewire.copy()
                w.Placement = obj.PlacementList[i]
                self.wires.append(w)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
        obj.TotalLength = obj.Length * len(obj.PlacementList)
 def MountingHole(self,i,zBase,panelThick):
     mh = self.mh[i]
     mh = Base.Vector(mh.x,mh.y,zBase)
     thick = Base.Vector(0,0,panelThick)
     mrad = self.hvpowerboardMHDia()/2.0
     return Part.Face(Part.Wire(Part.makeCircle(mrad,mh))).extrude(thick)
 def __init__(self, name, origin):
     self.name = name
     if not isinstance(origin, Base.Vector):
         raise RuntimeError("origin is not a Vector")
     self.origin = origin
     ox = origin.x
     oy = origin.y
     oz = origin.z
     boardsurf = Part.makePlane(self._psPCBwidth, self._psPCBlength, origin)
     xh = (ox + self._stripIncr)
     while xh <= ox + self._psPCBwidth:
         yh = oy + self._stripIncr
         while yh <= oy + self._psPCBlength:
             boardsurf = self._drill_leadhole(boardsurf, xh, yh, oz)
             yh += self._stripIncr
         xh += self._stripIncr
     self.mhvector = {
         1:
         Base.Vector(ox + self._psPCBMhOff + self._stripIncr,
                     oy + (self._stripIncr + 5 * 2.54), oz),
         2:
         Base.Vector(
             ox + self._psPCBMhOff + self._psPCBpsw + self._stripIncr,
             oy + (self._stripIncr + 5 * 2.54), oz),
         3:
         Base.Vector(
             ox + self._psPCBMhOff + self._stripIncr,
             oy + (self._psPCBlength - (self._stripIncr + 5 * 2.54)), oz),
         4:
         Base.Vector(
             ox + (self._psPCBMhOff + self._psPCBpsw + self._stripIncr),
             oy + (self._psPCBlength - (self._stripIncr + 5 * 2.54)), oz)
     }
     mh1circ = Part.makeCircle(self._mhdia / 2.0, self.mhvector[1])
     mh1wire = Part.Wire(mh1circ)
     mh1 = Part.Face(mh1wire)
     boardsurf = boardsurf.cut(mh1)
     mh2circ = Part.makeCircle(self._mhdia / 2.0, self.mhvector[2])
     mh2wire = Part.Wire(mh2circ)
     mh2 = Part.Face(mh2wire)
     boardsurf = boardsurf.cut(mh2)
     mh3circ = Part.makeCircle(self._mhdia / 2.0, self.mhvector[3])
     mh3wire = Part.Wire(mh3circ)
     mh3 = Part.Face(mh3wire)
     boardsurf = boardsurf.cut(mh3)
     mh4circ = Part.makeCircle(self._mhdia / 2.0, self.mhvector[4])
     mh4wire = Part.Wire(mh4circ)
     mh4 = Part.Face(mh4wire)
     boardsurf = boardsurf.cut(mh4)
     self.board = boardsurf.extrude(Base.Vector(0, 0, self._psPCBThickness))
     mh = {
         1:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     self._mhdia / 2.0,
                     Base.Vector(self.mhvector[1].x, self.mhvector[1].y,
                                 oz - self._stripThickness)))),
         2:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     self._mhdia / 2.0,
                     Base.Vector(self.mhvector[2].x, self.mhvector[2].y,
                                 oz - self._stripThickness)))),
         3:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     self._mhdia / 2.0,
                     Base.Vector(self.mhvector[3].x, self.mhvector[3].y,
                                 oz - self._stripThickness)))),
         4:
         Part.Face(
             Part.Wire(
                 Part.makeCircle(
                     self._mhdia / 2.0,
                     Base.Vector(self.mhvector[4].x, self.mhvector[4].y,
                                 oz - self._stripThickness))))
     }
     yoff = (self._psPCBlength - PSK_S15C._pslength) / 2.0
     xoff = self._psPCBMhOff + (
         (self._psPCBpsw - PSK_S15C._pswidth) / 2.0) + self._stripIncr
     pin1X = (PSK_S15C._pspin1Yoff + xoff)
     pin2X = (PSK_S15C._pspin2Yoff + xoff)
     sx = self._stripIncr
     vinX = sx + self._stripIncr
     gndX1 = vinX + self._stripIncr
     gndX2 = gndX1 + (3 * self._stripIncr)
     voutX = gndX2 + self._stripIncr
     self.strips = list()
     while (sx + self._stripIncr) <= self._psPCBwidth:
         #sys.__stderr__.write("*** sx = %f, pin1X is %f, pin2X is %f\n"%(sx,pin1X,pin2X))
         #sys.__stderr__.write("*** sx = %f, vinX is %f, voutX is %f\n"%(sx,vinX,voutX))
         if closeto(sx, vinX) or closeto(sx, voutX):
             #sys.__stderr__.write("*** sx hit\n")
             stripCP1 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + self._stripOffset,
                                    oz - self._stripThickness)
             striplen1 = 6 * self._stripIncr
             stripsurf = Part.makePlane(self._stripWidth, striplen1,
                                        stripCP1)
             xh = stripCP1.x + (self._stripWidth / 2.0)
             yh = stripCP1.y + self._stripOffset
             while yh < stripCP1.y + striplen1:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP1.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
             stripCP2 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + (11.5 * self._stripIncr),
                                    oz - self._stripThickness)
             striplen2 = self._psPCBlength - (12 * self._stripIncr)
             stripsurf = Part.makePlane(self._stripWidth, striplen2,
                                        stripCP2)
             xh = stripCP2.x + (self._stripWidth / 2.0)
             yh = stripCP2.y + self._stripOffset
             while yh < stripCP2.y + striplen2:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP2.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
         elif closeto(sx, gndX1) or closeto(sx, gndX2):
             #sys.__stderr__.write("*** sx hit\n")
             stripCP1 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + self._stripOffset,
                                    oz - self._stripThickness)
             striplen1 = 6 * self._stripIncr
             stripsurf = Part.makePlane(self._stripWidth, striplen1,
                                        stripCP1)
             xh = stripCP1.x + (self._stripWidth / 2.0)
             yh = stripCP1.y + self._stripOffset
             while yh < stripCP1.y + striplen1:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP1.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
             stripCP2 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + (11.5 * self._stripIncr),
                                    oz - self._stripThickness)
             striplen2 = 5 * self._stripIncr
             stripsurf = Part.makePlane(self._stripWidth, striplen2,
                                        stripCP2)
             xh = stripCP2.x + (self._stripWidth / 2.0)
             yh = stripCP2.y + self._stripOffset
             while yh < stripCP2.y + striplen2:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP2.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
             stripCP3 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + (25.5 * self._stripIncr),
                                    oz - self._stripThickness)
             striplen3 = 4 * self._stripIncr
             stripsurf = Part.makePlane(self._stripWidth, striplen3,
                                        stripCP3)
             xh = stripCP3.x + (self._stripWidth / 2.0)
             yh = stripCP3.y + self._stripOffset
             while yh < stripCP3.y + striplen3:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP3.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
         elif (sx < pin1X or closeto(sx,pin1X)) and \
              (sx > pin2X or closeto(sx,pin2X)):
             #sys.__stderr__.write("*** sx hit\n")
             stripCP1 = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                    oy + self._stripOffset,
                                    oz - self._stripThickness)
             stripCP2 = Base.Vector(
                 ox + (sx - (self._stripWidth / 2.0)),
                 oy + (self._stripOffset + yoff + PSK_S15C._pspin1Xoff -
                       self._stripExtra - 2.54), oz - self._stripThickness)
             striplen = yoff + PSK_S15C._pspin4Xoff + self._stripExtra
             stripsurf = Part.makePlane(self._stripWidth, striplen,
                                        stripCP1)
             xh = stripCP1.x + (self._stripWidth / 2.0)
             yh = stripCP1.y + self._stripOffset
             while yh < stripCP1.y + striplen:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP1.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
             stripsurf = Part.makePlane(self._stripWidth, striplen,
                                        stripCP2)
             xh = stripCP2.x + (self._stripWidth / 2.0)
             yh = stripCP2.y + self._stripOffset
             while yh < stripCP2.y + striplen:
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP2.z)
                 yh += self._stripIncr
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
         else:
             stripCP = Base.Vector(ox + (sx - (self._stripWidth / 2.0)),
                                   oy + self._stripOffset,
                                   oz - self._stripThickness)
             stripsurf = Part.makePlane(
                 self._stripWidth,
                 self._psPCBlength - (self._stripOffset * 2), stripCP)
             xh = stripCP.x + (self._stripWidth / 2.0)
             yh = stripCP.y + self._stripOffset
             while yh < stripCP.y + self._psPCBlength - (self._stripOffset *
                                                         2):
                 stripsurf = self._drill_leadhole(stripsurf, xh, yh,
                                                  stripCP.z)
                 yh += self._stripIncr
             i = 1
             while i <= 4:
                 h = self.mhvector[i]
                 stripsurf = stripsurf.cut(mh[i])
                 i += 1
             strip = stripsurf.extrude(
                 Base.Vector(0, 0, self._stripThickness))
             self.strips.append(strip)
         sx += self._stripIncr
 def Standoff(self,i,zBase,height,diameter):
     soff = self.mh[i] 
     soff = Base.Vector(soff.x,soff.y,zBase)
     stall = Base.Vector(0,0,height)
     srad = diameter/2.0
     return Part.Face(Part.Wire(Part.makeCircle(srad,soff))).extrude(stall)
Example #52
0
 def create_circle(self):
     position = Base.Vector(self.position)
     direction = Base.Vector(self.direction)
     self.shape = Part.makeCircle(self.radius, position, direction, 0, 360)
Example #53
0
def makeSolarDiagram(longitude, latitude, scale=1, complete=False):
    """makeSolarDiagram(longitude,latitude,[scale,complete]):
    returns a solar diagram as a pivy node. If complete is
    True, the 12 months are drawn"""

    from subprocess import call
    py3_failed = call(["python3", "-c", "import Pysolar"])

    if py3_failed:
        try:
            import Pysolar
        except:
            print(
                "Pysolar is not installed. Unable to generate solar diagrams")
            return None
    else:
        from subprocess import check_output

    from pivy import coin

    if not scale:
        return None

    def toNode(shape):
        "builds a pivy node from a simple linear shape"
        from pivy import coin
        buf = shape.writeInventor(2, 0.01)
        buf = buf.replace("\n", "")
        pts = re.findall("point \[(.*?)\]", buf)[0]
        pts = pts.split(",")
        pc = []
        for p in pts:
            v = p.strip().split()
            pc.append([float(v[0]), float(v[1]), float(v[2])])
        coords = coin.SoCoordinate3()
        coords.point.setValues(0, len(pc), pc)
        line = coin.SoLineSet()
        line.numVertices.setValue(-1)
        item = coin.SoSeparator()
        item.addChild(coords)
        item.addChild(line)
        return item

    circles = []
    sunpaths = []
    hourpaths = []
    circlepos = []
    hourpos = []

    # build the base circle + number positions
    import Part
    for i in range(1, 9):
        circles.append(Part.makeCircle(scale * (i / 8.0)))
    for ad in range(0, 360, 15):
        a = math.radians(ad)
        p1 = FreeCAD.Vector(math.cos(a) * scale, math.sin(a) * scale, 0)
        p2 = FreeCAD.Vector(
            math.cos(a) * scale * 0.125,
            math.sin(a) * scale * 0.125, 0)
        p3 = FreeCAD.Vector(
            math.cos(a) * scale * 1.08,
            math.sin(a) * scale * 1.08, 0)
        circles.append(Part.LineSegment(p1, p2).toShape())
        circlepos.append((ad, p3))

    # build the sun curves at solstices and equinoxe
    year = datetime.datetime.now().year
    hpts = [[] for i in range(24)]
    m = [(6, 21), (7, 21), (8, 21), (9, 21), (10, 21), (11, 21), (12, 21)]
    if complete:
        m.extend([(1, 21), (2, 21), (3, 21), (4, 21), (5, 21)])
    for i, d in enumerate(m):
        pts = []
        for h in range(24):
            if not py3_failed:
                dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1],
                                                            h)
                alt_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_altitude_fast(%s, %s, %s))'" % (
                    latitude, longitude, dt)
                alt = math.radians(
                    float(check_output(alt_call, shell=True).strip()))
                az_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_azimuth(%s, %s, %s))'" % (
                    latitude, longitude, dt)
                az = float(
                    re.search('.+$', check_output(az_call,
                                                  shell=True)).group(0))
            else:
                dt = datetime.datetime(year, d[0], d[1], h)
                alt = math.radians(
                    Pysolar.solar.GetAltitudeFast(latitude, longitude, dt))
                az = Pysolar.solar.GetAzimuth(latitude, longitude, dt)
            az = -90 + az  # pysolar's zero is south
            if az < 0:
                az = 360 + az
            az = math.radians(az)
            zc = math.sin(alt) * scale
            ic = math.cos(alt) * scale
            xc = math.cos(az) * ic
            yc = math.sin(az) * ic
            p = FreeCAD.Vector(xc, yc, zc)
            pts.append(p)
            hpts[h].append(p)
            if i in [0, 6]:
                ep = FreeCAD.Vector(p)
                ep.multiply(1.08)
                if ep.z >= 0:
                    if h == 12:
                        if i == 0:
                            h = "SUMMER"
                        else:
                            h = "WINTER"
                        if latitude < 0:
                            if h == "SUMMER":
                                h = "WINTER"
                            else:
                                h = "SUMMER"
                    hourpos.append((h, ep))
        if i < 7:
            sunpaths.append(Part.makePolygon(pts))
    for h in hpts:
        if complete:
            h.append(h[0])
        hourpaths.append(Part.makePolygon(h))

    # cut underground lines
    sz = 2.1 * scale
    cube = Part.makeBox(sz, sz, sz)
    cube.translate(FreeCAD.Vector(-sz / 2, -sz / 2, -sz))
    sunpaths = [sp.cut(cube) for sp in sunpaths]
    hourpaths = [hp.cut(cube) for hp in hourpaths]

    # build nodes
    ts = 0.005 * scale  # text scale
    mastersep = coin.SoSeparator()
    circlesep = coin.SoSeparator()
    numsep = coin.SoSeparator()
    pathsep = coin.SoSeparator()
    hoursep = coin.SoSeparator()
    hournumsep = coin.SoSeparator()
    mastersep.addChild(circlesep)
    mastersep.addChild(numsep)
    mastersep.addChild(pathsep)
    mastersep.addChild(hoursep)
    for item in circles:
        circlesep.addChild(toNode(item))
    for item in sunpaths:
        for w in item.Edges:
            pathsep.addChild(toNode(w))
    for item in hourpaths:
        for w in item.Edges:
            hoursep.addChild(toNode(w))
    for p in circlepos:
        text = coin.SoText2()
        s = p[0] - 90
        s = -s
        if s > 360:
            s = s - 360
        if s < 0:
            s = 360 + s
        if s == 0:
            s = "N"
        elif s == 90:
            s = "E"
        elif s == 180:
            s = "S"
        elif s == 270:
            s = "W"
        else:
            s = str(s)
        text.string = s
        text.justification = coin.SoText2.CENTER
        coords = coin.SoTransform()
        coords.translation.setValue([p[1].x, p[1].y, p[1].z])
        coords.scaleFactor.setValue([ts, ts, ts])
        item = coin.SoSeparator()
        item.addChild(coords)
        item.addChild(text)
        numsep.addChild(item)
    for p in hourpos:
        text = coin.SoText2()
        s = str(p[0])
        text.string = s
        text.justification = coin.SoText2.CENTER
        coords = coin.SoTransform()
        coords.translation.setValue([p[1].x, p[1].y, p[1].z])
        coords.scaleFactor.setValue([ts, ts, ts])
        item = coin.SoSeparator()
        item.addChild(coords)
        item.addChild(text)
        numsep.addChild(item)
    return mastersep
Example #54
0
    def execute(self,fp):
        b = fp.pin_circle_radius
        d = fp.roller_diameter
        e = fp.eccentricity
        n = fp.teeth_number
        p = b/n
        s = fp.segment_count
        ang = fp.pressure_angle_lim
        c = fp.pressure_angle_offset

        q = 2*math.pi/float(s)

        # Find the pressure angle limit circles
        minAngle = -1.0
        maxAngle = -1.0
        for i in range(0, 180):
            x = self.calc_pressure_angle(p, d, n, i * math.pi / 180.)
            if ( x < ang) and (minAngle < 0):
                minAngle = float(i)
            if (x < -ang) and (maxAngle < 0):
                maxAngle = float(i-1)

        minRadius = self.calc_pressure_limit(p, d, e, n, minAngle * math.pi / 180.)
        maxRadius = self.calc_pressure_limit(p, d, e, n, maxAngle * math.pi / 180.)
        # unused
        # Wire(Part.makeCircle(minRadius,App.Vector(-e, 0, 0)))
        # Wire(Part.makeCircle(maxRadius,App.Vector(-e, 0, 0)))

        App.Console.PrintMessage("Generating cam disk\r\n")
        #generate the cam profile - note: shifted in -x by eccentricicy amount
        i=0
        x = self.calc_x(p, d, e, n, q*i / float(n))
        y = self.calc_y(p, d, e, n, q*i / n)
        x, y = self.check_limit(x,y,maxRadius,minRadius,c)
        points = [App.Vector(x-e, y, 0)]
        for i in range(0,s):
            x = self.calc_x(p, d, e, n, q*(i+1) / n)
            y = self.calc_y(p, d, e, n, q*(i+1) / n)
            x, y = self.check_limit(x, y, maxRadius, minRadius, c)
            points.append([x-e, y, 0])

        wi = make_bspline_wire([points])
        wires = []
        mat= App.Matrix()
        mat.move(App.Vector(e, 0., 0.))
        mat.rotateZ(2 * np.pi / n)
        mat.move(App.Vector(-e, 0., 0.))
        for _ in range(n):
            wi = wi.transformGeometry(mat)
            wires.append(wi)

        cam = Face(Wire(wires))
        #add a circle in the center of the cam
        if fp.hole_radius.Value:
            centerCircle = Face(Wire(Part.makeCircle(fp.hole_radius.Value, App.Vector(-e, 0, 0))))
            cam = cam.cut(centerCircle)

        to_be_fused = []
        if fp.show_disk0==True:
            if fp.disk_height.Value==0:
                to_be_fused.append(cam)
            else:
                to_be_fused.append(cam.extrude(App.Vector(0, 0, fp.disk_height.Value)))

        #secondary cam disk
        if fp.show_disk1==True:
            App.Console.PrintMessage("Generating secondary cam disk\r\n")
            second_cam = cam.copy()
            mat= App.Matrix()
            mat.rotateZ(np.pi)
            mat.move(App.Vector(-e, 0, 0))
            if n%2 == 0:
                mat.rotateZ(np.pi/n)
            mat.move(App.Vector(e, 0, 0))
            second_cam = second_cam.transformGeometry(mat)
            if fp.disk_height.Value==0:
                to_be_fused.append(second_cam)
            else:
                to_be_fused.append(second_cam.extrude(App.Vector(0, 0, -fp.disk_height.Value)))

        #pins
        if fp.show_pins==True:
            App.Console.PrintMessage("Generating pins\r\n")
            pins = []
            for i in range(0, n + 1):
                x = p * n * math.cos(2 * math.pi / (n + 1) * i)
                y = p * n * math.sin(2 * math.pi / (n + 1) * i)
                pins.append(Wire(Part.makeCircle(d / 2, App.Vector(x, y, 0))))

            pins = Face(pins)

            z_offset = -fp.pin_height.Value / 2;

            if fp.center_pins==True:
                if fp.show_disk0==True and fp.show_disk1==False:
                    z_offset += fp.disk_height.Value / 2;
                elif fp.show_disk0==False and fp.show_disk1==True:
                    z_offset += -fp.disk_height.Value / 2;
            #extrude
            if z_offset!=0:
                pins.translate(App.Vector(0, 0, z_offset))
            if fp.pin_height!=0:
                pins = pins.extrude(App.Vector(0, 0, fp.pin_height.Value))

            to_be_fused.append(pins);

        if to_be_fused:
            fp.Shape = Part.makeCompound(to_be_fused)
Example #55
0
    def execute(self, obj):

        if self.clone(obj):
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0], "Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if father.isDerivedFrom("Part::Feature"):
                fathershape = father.Shape

        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print(obj.Rounding)
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        if fathershape:
            size = (ArchCommands.projectToVector(fathershape.copy(),
                                                 axis)).Length
        else:
            size = 1
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
                if fathershape:
                    size = (ArchCommands.projectToVector(
                        fathershape.copy(), axis)).Length
                else:
                    size = 1
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        #print(axis)
        #print(size)
        spacinglist = None
        if hasattr(obj, "CustomSpacing"):
            if obj.CustomSpacing:
                spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing)
                influenceArea = sum(
                    spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return
        # all tests ok!
        if hasattr(obj, "Length"):
            length = getLengthOfRebar(obj)
            if length:
                obj.Length = length
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
            basewire = wire.copy()
        except Part.OCCError:
            print("Arch: error sweeping rebar profile along the base sketch")
            return
        # building final shape
        shapes = []
        placementlist = []
        self.wires = []
        if father:
            rot = father.Placement.Rotation
        else:
            rot = FreeCAD.Rotation()
        if obj.Amount == 1:
            barplacement = CalculatePlacement(obj.Amount, 1, size, axis, rot,
                                              obj.OffsetStart.Value,
                                              obj.OffsetEnd.Value)
            placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            for i in range(obj.Amount):
                barplacement = CalculatePlacement(obj.Amount, i + 1, size,
                                                  axis, rot,
                                                  obj.OffsetStart.Value,
                                                  obj.OffsetEnd.Value)
                placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        # Calculate placement of bars from custom spacing.
        if spacinglist:
            placementlist[:] = []
            reqInfluenceArea = size - (obj.OffsetStart.Value +
                                       obj.OffsetEnd.Value)
            # Avoid unnecessary checks to pass like. For eg.: when we have values
            # like influenceArea is 100.00001 and reqInflueneArea is 100
            if round(influenceArea) > round(reqInfluenceArea):
                return FreeCAD.Console.PrintError(
                    "Influence area of rebars is greater than " +
                    str(reqInfluenceArea) + ".\n")
            elif round(influenceArea) < round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Last span is greater that end offset.\n")
            for i in range(len(spacinglist)):
                if i == 0:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
                else:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, i + 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
            obj.Amount = len(spacinglist)
            obj.Spacing = 0
        obj.PlacementList = placementlist
        for i in range(len(obj.PlacementList)):
            if i == 0:
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                basewire.Placement = obj.PlacementList[i]
                self.wires.append(basewire)
            else:
                bar = bar.copy()
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                w = basewire.copy()
                w.Placement = obj.PlacementList[i]
                self.wires.append(w)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
        obj.TotalLength = obj.Length * len(obj.PlacementList)
Example #56
0
    def execute(self, fp):
        m = fp.module.Value
        d = fp.diameter.Value
        t = fp.teeth
        h = fp.height

        clearance = fp.clearance
        head = fp.head
        alpha = fp.pressure_angle.Value
        beta = np.arctan(m * t / d)
        fp.beta = np.rad2deg(beta)
        beta = -(fp.reverse_pitch * 2 - 1) * (np.pi / 2 - beta)

        r_1 = (d - (2 + 2 * clearance) * m) / 2
        r_2 = (d + (2 + 2 * head) * m) / 2
        z_a = (2 + head + clearance) * m * np.tan(np.deg2rad(alpha))
        z_b = (m * np.pi - 4 * m * np.tan(np.deg2rad(alpha))) / 2
        z_0 = clearance * m * np.tan(np.deg2rad(alpha))
        z_1 = z_b - z_0
        z_2 = z_1 + z_a
        z_3 = z_2 + z_b - 2 * head * m * np.tan(np.deg2rad(alpha))
        z_4 = z_3 + z_a

        def helical_projection(r, z):
            phi = 2 * z / m / t
            x = r * np.cos(phi)
            y = r * np.sin(phi)
            z = 0 * y
            return np.array([x, y, z]). T

        # create a circle from phi=0 to phi_1 with r_1
        phi_0 = 2 * z_0 / m / t
        phi_1 = 2 * z_1 / m / t
        c1 = Part.makeCircle(r_1, App.Vector(0, 0, 0),
                             App.Vector(0, 0, 1), np.rad2deg(phi_0), np.rad2deg(phi_1))

        # create first bspline
        z_values = np.linspace(z_1, z_2, 10)
        r_values = np.linspace(r_1, r_2, 10)
        points = helical_projection(r_values, z_values)
        bsp1 = Part.BSplineCurve()
        bsp1.interpolate(list(map(fcvec, points)))
        bsp1 = bsp1.toShape()

        # create circle from phi_2 to phi_3
        phi_2 = 2 * z_2 / m / t
        phi_3 = 2 * z_3 / m / t
        c2 = Part.makeCircle(r_2, App.Vector(0, 0, 0), App.Vector(
            0, 0, 1), np.rad2deg(phi_2), np.rad2deg(phi_3))

        # create second bspline
        z_values = np.linspace(z_3, z_4, 10)
        r_values = np.linspace(r_2, r_1, 10)
        points = helical_projection(r_values, z_values)
        bsp2 = Part.BSplineCurve()
        bsp2.interpolate(list(map(fcvec, points)))
        bsp2 = bsp2.toShape()

        wire = Part.Wire([c1, bsp1, c2, bsp2])
        w_all = [wire]

        rot = App.Matrix()
        rot.rotateZ(2 * np.pi / t)
        for i in range(1, t):
            w_all.append(w_all[-1].transformGeometry(rot))

        full_wire = Part.Wire(Part.Wire(w_all))
        if h == 0:
            fp.Shape = full_wire
        else:
            shape = helicalextrusion(full_wire,
                                     h,
                                     h * np.tan(beta) * 2 / d)
            fp.Shape = shape
Example #57
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        if obj.Base:
            PathLog.debug("base items exist.  Processing...")
            self.removalshapes = []
            self.horiz = []
            vertical = []
            for o in obj.Base:
                PathLog.debug("Base item: {}".format(o))
                base = o[0]
                for sub in o[1]:
                    if "Face" in sub:
                        face = base.Shape.getElement(sub)
                        if type(face.Surface) == Part.Plane and PathGeom.isVertical(face.Surface.Axis):
                            # it's a flat horizontal face
                            self.horiz.append(face)
                        elif type(face.Surface) == Part.Cylinder and PathGeom.isVertical(face.Surface.Axis):
                            # vertical cylinder wall
                            if any(e.isClosed() for e in face.Edges):
                                # complete cylinder
                                circle = Part.makeCircle(face.Surface.Radius, face.Surface.Center)
                                disk = Part.Face(Part.Wire(circle))
                                self.horiz.append(disk)
                            else:
                                # partial cylinder wall
                                vertical.append(face)
                        elif type(face.Surface) == Part.Plane and PathGeom.isHorizontal(face.Surface.Axis):
                            vertical.append(face)
                        else:
                            PathLog.error(translate('PathPocket', "Pocket does not support shape %s.%s") % (base.Label, sub))

            self.vertical = PathGeom.combineConnectedShapes(vertical)
            self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical]
            for wire in self.vWires:
                w = PathGeom.removeDuplicateEdges(wire)
                face = Part.Face(w)
                face.tessellate(0.1)
                if PathGeom.isRoughly(face.Area, 0):
                    PathLog.error(translate('PathPocket', 'Vertical faces do not form a loop - ignoring'))
                else:
                    self.horiz.append(face)


            # move all horizontal faces to FinalDepth
            for f in self.horiz:
                f.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - f.BoundBox.ZMin))

            # check all faces and see if they are touching/overlapping and combine those into a compound
            self.horizontal = []
            for shape in PathGeom.combineConnectedShapes(self.horiz):
                shape.sewShape()
                shape.tessellate(0.1)
                if obj.UseOutline:
                    wire = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1))
                    wire.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - wire.BoundBox.ZMin))
                    self.horizontal.append(Part.Face(wire))
                else:
                    self.horizontal.append(shape)

            # extrude all faces up to StartDepth and those are the removal shapes
            extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value)
            self.removalshapes = [(face.extrude(extent), False) for face in self.horizontal]

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            self.outline = Part.Face(TechDraw.findShapeOutline(self.baseobject.Shape, 1, FreeCAD.Vector(0, 0, 1)))
            stockBB = self.stock.Shape.BoundBox

            self.outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
            self.body  = self.outline.extrude(FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
            self.removalshapes = [(self.stock.Shape.cut(self.body), False)]

        for (shape,hole) in self.removalshapes:
            shape.tessellate(0.1)

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]
        return self.removalshapes
Example #58
0
    def makeTruss(self, obj, v0, v1):

        import Part

        # get normal direction
        normal = obj.Normal
        if not normal.Length:
            normal = FreeCAD.Vector(0, 0, 1)

        # create base profile
        maindir = v1.sub(v0)
        sidedir = normal.cross(maindir)
        if not sidedir.Length:
            FreeCAD.Console.PrintLog(obj.Label +
                                     ": normal and base are parallel\n")
            return
        sidedir.normalize()
        p0 = v0.add(
            FreeCAD.Vector(sidedir).negative().multiply(obj.StrutWidth.Value /
                                                        2))
        p1 = p0.add(
            FreeCAD.Vector(sidedir).multiply(obj.StrutWidth.Value /
                                             2).multiply(2))
        p2 = p1.add(FreeCAD.Vector(normal).multiply(obj.StrutHeight))
        p3 = p0.add(FreeCAD.Vector(normal).multiply(obj.StrutHeight))
        trussprofile = Part.Face(Part.makePolygon([p0, p1, p2, p3, p0]))

        # create bottom strut
        bottomstrut = trussprofile.extrude(maindir)

        # create top strut
        v2 = v0.add(FreeCAD.Vector(normal).multiply(obj.HeightStart.Value))
        v3 = v1.add(FreeCAD.Vector(normal).multiply(obj.HeightEnd.Value))
        topdir = v3.sub(v2)
        if obj.StrutStartOffset.Value:
            v2f = v2.add(
                (v2.sub(v3)).normalize().multiply(obj.StrutStartOffset.Value))
        else:
            v2f = v2
        if obj.StrutEndOffset.Value:
            v3f = v3.add(
                (v3.sub(v2)).normalize().multiply(obj.StrutEndOffset.Value))
        else:
            v3f = v3
        offtopdir = v3f.sub(v2f)
        topstrut = trussprofile.extrude(offtopdir)
        topstrut.translate(v2f.sub(v0))
        topstrut.translate(
            FreeCAD.Vector(normal).multiply(-obj.StrutHeight.Value))
        angle = math.degrees(topdir.getAngle(maindir))

        # create rod profile on the XY plane
        if obj.RodType == "Round":
            rodprofile = Part.Face(
                Part.Wire([Part.makeCircle(obj.RodSize / 2)]))
        else:
            rodprofile = Part.Face(
                Part.makePlane(
                    obj.RodSize, obj.RodSize,
                    FreeCAD.Vector(-obj.RodSize / 2, -obj.RodSize / 2, 0)))

        # create rods
        rods = []
        bottomrodstart = v0.add(
            FreeCAD.Vector(normal).multiply(obj.StrutHeight.Value / 2))
        toprodstart = v2.add(
            FreeCAD.Vector(normal).multiply(obj.StrutHeight.Value /
                                            2).negative())
        bottomrodvec = FreeCAD.Vector(maindir).multiply(1 / obj.RodSections)
        toprodvec = FreeCAD.Vector(topdir).multiply(1 / obj.RodSections)
        bottomrodpos = [bottomrodstart]
        toprodpos = [toprodstart]

        if obj.RodMode == rodmodes[0]:
            # /|/|/|
            for i in range(1, obj.RodSections + 1):
                if (i > 1) or (obj.StrutStartOffset.Value >= 0):
                    # do not add first vert rod if negative offset
                    rods.append(
                        self.makeRod(rodprofile, bottomrodpos[-1],
                                     toprodpos[-1]))
                bottomrodpos.append(bottomrodpos[-1].add(bottomrodvec))
                toprodpos.append(toprodpos[-1].add(toprodvec))
                if obj.RodDirection == "Forward":
                    rods.append(
                        self.makeRod(rodprofile, bottomrodpos[-2],
                                     toprodpos[-1]))
                else:
                    rods.append(
                        self.makeRod(rodprofile, bottomrodpos[-1],
                                     toprodpos[-2]))

        elif obj.RodMode == rodmodes[1]:
            # /\/\/\
            fw = True
            for i in range(1, obj.RodSections + 1):
                bottomrodpos.append(bottomrodpos[-1].add(bottomrodvec))
                toprodpos.append(toprodpos[-1].add(toprodvec))
                if obj.RodDirection == "Forward":
                    if fw:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-2],
                                         toprodpos[-1]))
                    else:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-1],
                                         toprodpos[-2]))
                else:
                    if fw:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-1],
                                         toprodpos[-2]))
                    else:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-2],
                                         toprodpos[-1]))
                fw = not fw

        elif obj.RodMode == rodmodes[2]:
            # /|\|/|\
            fw = True
            for i in range(1, obj.RodSections + 1):
                if (i > 1) or (obj.StrutStartOffset.Value >= 0):
                    # do not add first vert rod if negative offset
                    rods.append(
                        self.makeRod(rodprofile, bottomrodpos[-1],
                                     toprodpos[-1]))
                bottomrodpos.append(bottomrodpos[-1].add(bottomrodvec))
                toprodpos.append(toprodpos[-1].add(toprodvec))
                if obj.RodDirection == "Forward":
                    if fw:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-2],
                                         toprodpos[-1]))
                    else:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-1],
                                         toprodpos[-2]))
                else:
                    if fw:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-1],
                                         toprodpos[-2]))
                    else:
                        rods.append(
                            self.makeRod(rodprofile, bottomrodpos[-2],
                                         toprodpos[-1]))
                fw = not fw

        # add end rod
        if obj.RodEnd:
            rods.append(
                self.makeRod(rodprofile, bottomrodpos[-1], toprodpos[-1]))

        # trim rods
        rods = [rod.cut(topstrut).cut(bottomstrut) for rod in rods]

        return topstrut, bottomstrut, rods, angle
Example #59
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()
        PathLog.debug("areaOpShapes() in PathPocketShape.py")

        def judgeFinalDepth(obj, fD):
            if obj.FinalDepth.Value >= fD:
                return obj.FinalDepth.Value
            else:
                return fD

        def judgeStartDepth(obj, sD):
            if obj.StartDepth.Value >= sD:
                return obj.StartDepth.Value
            else:
                return sD

        def analyzeVerticalFaces(self, obj, vertTuples):
            hT = []
            # base = FreeCAD.ActiveDocument.getObject(self.modelName)

            # Separate elements, regroup by orientation (axis_angle combination)
            vTags = ['X34.2']
            vGrps = [[(2.3, 3.4, 'X')]]
            for tup in vertTuples:
                (face, sub, angle, axis, tag, strDep, finDep, trans) = tup
                if tag in vTags:
                    # Determine index of found string
                    i = 0
                    for orn in vTags:
                        if orn == tag:
                            break
                        i += 1
                    vGrps[i].append(tup)
                else:
                    vTags.append(tag)  # add orientation entry
                    vGrps.append([tup])  # add orientation entry
            # Remove temp elements
            vTags.pop(0)
            vGrps.pop(0)

            # check all faces in each axis_angle group
            shpList = []
            zmaxH = 0.0
            for o in range(0, len(vTags)):
                shpList = []
                zmaxH = vGrps[o][0].BoundBox.ZMax
                for (face, sub, angle, axis, tag, strDep, finDep,
                     trans) in vGrps[o]:
                    shpList.append(face)
                    # Identify tallest face to use as zMax
                    if face.BoundBox.ZMax > zmaxH:
                        zmaxH = face.BoundBox.ZMax
                # check all faces and see if they are touching/overlapping and combine those into a compound
                # Original Code in For loop
                self.vertical = PathGeom.combineConnectedShapes(shpList)
                self.vWires = [
                    TechDraw.findShapeOutline(shape, 1,
                                              FreeCAD.Vector(0, 0, 1))
                    for shape in self.vertical
                ]
                for wire in self.vWires:
                    w = PathGeom.removeDuplicateEdges(wire)
                    face = Part.Face(w)
                    face.tessellate(0.05)
                    if PathGeom.isRoughly(face.Area, 0):
                        PathLog.error(
                            translate(
                                'PathPocket',
                                'Vertical faces do not form a loop - ignoring')
                        )
                    else:
                        strDep = zmaxH + self.leadIn  # base.Shape.BoundBox.ZMax
                        finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                        tup = face, sub, angle, axis, tag, strDep, finDep, trans
                        hT.append(tup)
            # Eol
            return hT

        if obj.Base:
            PathLog.debug('base items exist.  Processing...')
            self.removalshapes = []
            self.horiz = []
            vertical = []
            horizTuples = []
            vertTuples = []
            axis = 'X'
            angle = 0.0
            reset = False
            resetPlacement = None
            trans = FreeCAD.Vector(0.0, 0.0, 0.0)

            for o in obj.Base:
                PathLog.debug('Base item: {}'.format(o))
                base = o[0]

                # Limit sub faces to children of single Model object.
                if self.modelName is None:
                    self.modelName = base.Name
                else:
                    if base.Name != self.modelName:
                        for sub in o[1]:
                            PathLog.error(sub +
                                          " is not a part of Model object: " +
                                          self.modelName)
                        o[1] = []
                        PathLog.error(
                            "Only processing faces on a single Model object per operation."
                        )
                        PathLog.error(
                            "You will need to separate faces per Model object within the Job."
                        )

                startBase = FreeCAD.Vector(base.Placement.Base.x,
                                           base.Placement.Base.y,
                                           base.Placement.Base.z)
                startAngle = base.Placement.Rotation.Angle
                startAxis = base.Placement.Rotation.Axis
                startRotation = FreeCAD.Rotation(startAxis, startAngle)
                resetPlacement = FreeCAD.Placement(startBase, startRotation)
                for sub in o[1]:
                    if 'Face' in sub:
                        PathLog.debug('sub: {}'.format(sub))
                        # Determine angle of rotation needed to make normal vector = (0,0,1)
                        strDep = obj.StartDepth.Value
                        finDep = obj.FinalDepth.Value
                        trans = FreeCAD.Vector(0.0, 0.0, 0.0)
                        rtn = False

                        if obj.UseRotation != 'Off':
                            (rtn, angle,
                             axis) = self.pocketRotationAnalysis(obj,
                                                                 base,
                                                                 sub,
                                                                 prnt=True)

                        if rtn is True:
                            reset = True
                            PathLog.debug(
                                str(sub) +
                                ": rotating model to make face normal at (0,0,1) ..."
                            )
                            if axis == 'X':
                                bX = 0.0
                                bY = 0.0
                                bZ = math.sin(math.radians(
                                    angle)) * base.Placement.Base.y
                                vect = FreeCAD.Vector(1, 0, 0)
                            elif axis == 'Y':
                                bX = 0.0
                                bY = 0.0
                                bZ = math.sin(math.radians(
                                    angle)) * base.Placement.Base.x
                                if obj.B_AxisErrorOverride is True:
                                    bZ = -1 * bZ
                                vect = FreeCAD.Vector(0, 1, 0)
                            # Rotate base to such that Surface.Axis of pocket bottom is Z=1
                            base.Placement.Rotation = FreeCAD.Rotation(
                                vect, angle)
                            base.recompute()
                            trans = FreeCAD.Vector(bX, bY, bZ)
                        else:
                            axis = 'X'
                            angle = 0.0
                        tag = axis + str(round(angle, 7))
                        face = base.Shape.getElement(sub)

                        if type(face.Surface
                                ) == Part.Plane and PathGeom.isVertical(
                                    face.Surface.Axis):
                            # it's a flat horizontal face
                            PathLog.debug(" == Part.Plane: isVertical")
                            # Adjust start and finish depths for pocket
                            strDep = base.Shape.BoundBox.ZMax + self.leadIn
                            finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                            # Over-write default final depth value, leaves manual override by user
                            obj.StartDepth.Value = trans.z + strDep
                            obj.FinalDepth.Value = trans.z + finDep

                            tup = face, sub, angle, axis, tag, strDep, finDep, trans
                            horizTuples.append(tup)
                        elif type(face.Surface
                                  ) == Part.Cylinder and PathGeom.isVertical(
                                      face.Surface.Axis):
                            PathLog.debug("== Part.Cylinder")
                            # vertical cylinder wall
                            if any(e.isClosed() for e in face.Edges):
                                PathLog.debug("e.isClosed()")
                                # complete cylinder
                                circle = Part.makeCircle(
                                    face.Surface.Radius, face.Surface.Center)
                                disk = Part.Face(Part.Wire(circle))

                                # Adjust start and finish depths for pocket
                                strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                                finDep = judgeFinalDepth(
                                    obj, face.BoundBox.ZMin)
                                # Over-write default final depth value, leaves manual override by user
                                obj.StartDepth.Value = trans.z + strDep
                                obj.FinalDepth.Value = trans.z + finDep

                                tup = disk, sub, angle, axis, tag, strDep, finDep, trans
                                horizTuples.append(tup)
                            else:
                                # partial cylinder wall
                                vertical.append(face)

                                # Adjust start and finish depths for pocket
                                strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                                finDep = judgeFinalDepth(
                                    obj, face.BoundBox.ZMin)
                                # Over-write default final depth value, leaves manual override by user
                                obj.StartDepth.Value = trans.z + strDep
                                obj.FinalDepth.Value = trans.z + finDep
                                tup = face, sub, angle, axis, tag, strDep, finDep, trans
                                vertTuples.append(tup)

                                PathLog.debug(sub +
                                              "is vertical after rotation.")
                        elif type(face.Surface
                                  ) == Part.Plane and PathGeom.isHorizontal(
                                      face.Surface.Axis):
                            vertical.append(face)

                            # Adjust start and finish depths for pocket
                            strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                            finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                            # Over-write default final depth value, leaves manual override by user
                            obj.StartDepth.Value = trans.z + strDep
                            obj.FinalDepth.Value = trans.z + finDep
                            tup = face, sub, angle, axis, tag, strDep, finDep, trans
                            vertTuples.append(tup)
                            PathLog.debug(sub + "is vertical after rotation.")
                        else:
                            PathLog.error(
                                translate(
                                    'PathPocket',
                                    'Pocket does not support shape %s.%s') %
                                (base.Label, sub))

                        if reset is True:
                            base.Placement.Rotation = startRotation
                            base.recompute()
                            reset = False
                    # End IF
                # End FOR
                base.Placement = resetPlacement
                base.recompute()
            # End FOR

            # Analyze vertical faces via PathGeom.combineConnectedShapes()
            # hT = analyzeVerticalFaces(self, obj, vertTuples)
            # horizTuples.extend(hT)

            # This section will be replaced analyzeVerticalFaces(self, obj, vertTuples) above
            self.vertical = PathGeom.combineConnectedShapes(vertical)
            self.vWires = [
                TechDraw.findShapeOutline(shape, 1,
                                          FreeCAD.Vector(0.0, 0.0, 1.0))
                for shape in self.vertical
            ]
            for wire in self.vWires:
                w = PathGeom.removeDuplicateEdges(wire)
                face = Part.Face(w)
                face.tessellate(0.05)
                if PathGeom.isRoughly(face.Area, 0):
                    PathLog.error(
                        translate(
                            'PathPocket',
                            'Vertical faces do not form a loop - ignoring'))
                else:
                    # self.horiz.append(face)
                    strDep = base.Shape.BoundBox.ZMax + self.leadIn
                    finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                    tup = face, 'vertFace', 0.0, 'X', 'X0.0', strDep, finDep, FreeCAD.Vector(
                        0.0, 0.0, 0.0)
                    horizTuples.append(tup)

            # add faces for extensions
            self.exts = []
            for ext in self.getExtensions(obj):
                wire = Part.Face(ext.getWire())
                if wire:
                    face = Part.Face(wire)
                    # self.horiz.append(face)
                    strDep = base.Shape.BoundBox.ZMax + self.leadIn
                    finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                    tup = face, 'vertFace', 0.0, 'X', 'X0.0', strDep, finDep, FreeCAD.Vector(
                        0.0, 0.0, 0.0)
                    horizTuples.append(tup)
                    self.exts.append(face)

            # move all horizontal faces to FinalDepth
            for (face, sub, angle, axis, tag, strDep, finDep,
                 trans) in horizTuples:
                # face.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - face.BoundBox.ZMin))
                if angle <= 0.0:
                    if axis == 'X':
                        face.translate(
                            FreeCAD.Vector(
                                0, trans.z,
                                trans.z + finDep - face.BoundBox.ZMin))
                    elif axis == 'Y':
                        face.translate(
                            FreeCAD.Vector(
                                -1 * trans.z, 0,
                                trans.z + finDep - face.BoundBox.ZMin))
                else:
                    if axis == 'X':
                        face.translate(
                            FreeCAD.Vector(
                                0, -1 * trans.z,
                                trans.z + finDep - face.BoundBox.ZMin))
                    elif axis == 'Y':
                        face.translate(
                            FreeCAD.Vector(
                                trans.z, 0,
                                trans.z + finDep - face.BoundBox.ZMin))

            # Separate elements, regroup by orientation (axis_angle combination)
            hTags = ['X34.2']
            hGrps = [[(2.3, 3.4, 'X')]]
            for tup in horizTuples:
                (face, sub, angle, axis, tag, strDep, finDep, trans) = tup
                if tag in hTags:
                    # Determine index of found string
                    i = 0
                    for orn in hTags:
                        if orn == tag:
                            break
                        i += 1
                    hGrps[i].append(tup)
                else:
                    hTags.append(tag)  # add orientation entry
                    hGrps.append([tup])  # add orientation entry
            # Remove temp elements
            hTags.pop(0)
            hGrps.pop(0)

            # check all faces in each axis_angle group
            self.horizontal = []
            shpList = []
            for o in range(0, len(hTags)):
                PathLog.debug('hTag: {}'.format(hTags[o]))
                shpList = []
                for (face, sub, angle, axis, tag, strDep, finDep,
                     trans) in hGrps[o]:
                    shpList.append(face)
                # check all faces and see if they are touching/overlapping and combine those into a compound
                # Original Code in For loop
                for shape in PathGeom.combineConnectedShapes(shpList):
                    shape.sewShape()
                    # shape.tessellate(0.05) # Russ4262 0.1 original
                    if obj.UseOutline:
                        wire = TechDraw.findShapeOutline(
                            shape, 1, FreeCAD.Vector(0, 0, 1))
                        wire.translate(
                            FreeCAD.Vector(
                                0, 0,
                                obj.FinalDepth.Value - wire.BoundBox.ZMin))
                        PathLog.debug(
                            " -obj.UseOutline: obj.FinalDepth.Value" +
                            str(obj.FinalDepth.Value))
                        PathLog.debug(" -obj.UseOutline: wire.BoundBox.ZMin" +
                                      str(wire.BoundBox.ZMin))
                        # shape.tessellate(0.05) # Russ4262 0.1 original
                        face = Part.Face(wire)
                        tup = face, sub, angle, axis, tag, strDep, finDep, trans
                        self.horizontal.append(tup)
                    else:
                        # Re-pair shape to tuple set
                        for (face, sub, angle, axis, tag, strDep, finDep,
                             trans) in hGrps[o]:
                            if shape is face:
                                tup = face, sub, angle, axis, tag, strDep, finDep, trans
                                self.horizontal.append(tup)
                                break
            # Eol

            # extrude all faces up to StartDepth and those are the removal shapes
            for (face, sub, angle, axis, tag, strDep, finDep,
                 trans) in self.horizontal:
                # extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value)
                extent = FreeCAD.Vector(0, 0, strDep - finDep)
                shp = face.removeSplitter().extrude(extent)
                # tup = shp, False, sub, angle, axis, tag, strDep, finDep, trans
                tup = shp, False, sub, angle, axis  # shape, isHole, sub, angle, axis
                self.removalshapes.append(tup)

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            self.outlines = [
                Part.Face(
                    TechDraw.findShapeOutline(base.Shape, 1,
                                              FreeCAD.Vector(0, 0, 1)))
                for base in self.model
            ]
            stockBB = self.stock.Shape.BoundBox
            PathLog.debug(" -Using outlines; no obj.Base")

            self.removalshapes = []
            self.bodies = []
            for outline in self.outlines:
                outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
                body = outline.extrude(
                    FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
                self.bodies.append(body)
                self.removalshapes.append(
                    (self.stock.Shape.cut(body), False, 'outline', 0.0, 'X'))

        for (shape, isHole, sub, angle, axis) in self.removalshapes:
            shape.tessellate(0.05)

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]
        return self.removalshapes
Example #60
0
def getSVG(obj,
           scale=1,
           linewidth=0.35,
           fontsize=12,
           fillstyle="shape color",
           direction=None,
           linestyle=None,
           color=None,
           linespacing=None,
           techdraw=False,
           rotation=0,
           fillSpaces=False,
           override=True):
    '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color],[linespacing]):
    returns a string containing a SVG representation of the given object,
    with the given linewidth and fontsize (used if the given object contains
    any text). You can also supply an arbitrary projection vector. the
    scale parameter allows to scale linewidths down, so they are resolution-independant.'''

    import Part, DraftGeomUtils

    # if this is a group, gather all the svg views of its children
    if hasattr(obj, "isDerivedFrom"):
        if obj.isDerivedFrom("App::DocumentObjectGroup") or getType(
                obj) == "Layer":
            svg = ""
            for child in obj.Group:
                svg += getSVG(child, scale, linewidth, fontsize, fillstyle,
                              direction, linestyle, color, linespacing,
                              techdraw, rotation, fillSpaces, override)
            return svg

    pathdata = []
    svg = ""
    linewidth = float(linewidth) / scale
    if not override:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "LineWidth"):
                if hasattr(obj.ViewObject.LineWidth, "Value"):
                    lw = obj.ViewObject.LineWidth.Value
                else:
                    lw = obj.ViewObject.LineWidth
                linewidth = lw * linewidth
    fontsize = (float(fontsize) / scale) / 2
    if linespacing:
        linespacing = float(linespacing) / scale
    else:
        linespacing = 0.5
    #print obj.Label," line spacing ",linespacing,"scale ",scale
    pointratio = .75  # the number of times the dots are smaller than the arrow size
    plane = None
    if direction:
        if isinstance(direction, FreeCAD.Vector):
            if direction != Vector(0, 0, 0):
                plane = WorkingPlane.plane()
                plane.alignToPointAndAxis_SVG(Vector(0, 0, 0),
                                              direction.negative().negative(),
                                              0)
        elif isinstance(direction, WorkingPlane.plane):
            plane = direction
    stroke = "#000000"
    if color and override:
        if "#" in color:
            stroke = color
        else:
            stroke = getrgb(color)
    elif gui:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "LineColor"):
                stroke = getrgb(obj.ViewObject.LineColor)
            elif hasattr(obj.ViewObject, "TextColor"):
                stroke = getrgb(obj.ViewObject.TextColor)
    lstyle = "none"
    if override:
        lstyle = getLineStyle(linestyle, scale)
    else:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "DrawStyle"):
                lstyle = getLineStyle(obj.ViewObject.DrawStyle, scale)

    def getPath(edges=[], wires=[], pathname=None):

        svg = "<path "
        if pathname is None:
            svg += 'id="%s" ' % obj.Name
        elif pathname != "":
            svg += 'id="%s" ' % pathname
        svg += ' d="'
        if not wires:
            egroups = Part.sortEdges(edges)
        else:
            egroups = []
            first = True
            for w in wires:
                w1 = w.copy()
                if first:
                    first = False
                else:
                    # invert further wires to create holes
                    w1 = DraftGeomUtils.invert(w1)
                w1.fixWire()
                egroups.append(Part.__sortEdges__(w1.Edges))
        for egroupindex, edges in enumerate(egroups):
            edata = ""
            vs = ()  #skipped for the first edge
            for edgeindex, e in enumerate(edges):
                previousvs = vs
                # vertexes of an edge (reversed if needed)
                vs = e.Vertexes
                if previousvs:
                    if (vs[0].Point - previousvs[-1].Point).Length > 1e-6:
                        vs.reverse()
                if edgeindex == 0:
                    v = getProj(vs[0].Point, plane)
                    edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' '
                else:
                    if (vs[0].Point - previousvs[-1].Point).Length > 1e-6:
                        raise ValueError('edges not ordered')
                iscircle = DraftGeomUtils.geomType(e) == "Circle"
                isellipse = DraftGeomUtils.geomType(e) == "Ellipse"
                if iscircle or isellipse:
                    import math
                    if hasattr(FreeCAD, "DraftWorkingPlane"):
                        drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
                    else:
                        drawing_plane_normal = FreeCAD.Vector(0, 0, 1)
                    if plane: drawing_plane_normal = plane.axis
                    c = e.Curve
                    if round(c.Axis.getAngle(drawing_plane_normal),
                             2) in [0, 3.14]:
                        occversion = Part.OCC_VERSION.split(".")
                        done = False
                        if (int(occversion[0]) >= 7) and (int(occversion[1]) >=
                                                          1):
                            # if using occ >= 7.1, use HLR algorithm
                            import Drawing
                            snip = Drawing.projectToSVG(
                                e, drawing_plane_normal)
                            if snip:
                                try:
                                    a = "A " + snip.split("path d=\"")[
                                        1].split("\"")[0].split("A")[1]
                                except:
                                    pass
                                else:
                                    edata += a
                                    done = True
                        if not done:
                            if len(e.Vertexes
                                   ) == 1 and iscircle:  #complete curve
                                svg = getCircle(e)
                                return svg
                            elif len(e.Vertexes) == 1 and isellipse:
                                #svg = getEllipse(e)
                                #return svg
                                endpoints = [
                                    getProj(
                                        c.value((c.LastParameter -
                                                 c.FirstParameter) / 2.0),
                                        plane),
                                    getProj(vs[-1].Point, plane)
                                ]
                            else:
                                endpoints = [getProj(vs[-1].Point, plane)]
                            # arc
                            if iscircle:
                                rx = ry = c.Radius
                                rot = 0
                            else:  #ellipse
                                rx = c.MajorRadius
                                ry = c.MinorRadius
                                rot = math.degrees(c.AngleXU * (c.Axis * \
                                    FreeCAD.Vector(0,0,1)))
                                if rot > 90:
                                    rot -= 180
                                if rot < -90:
                                    rot += 180
                                #be careful with the sweep flag
                            flag_large_arc = (((e.ParameterRange[1] - \
                                    e.ParameterRange[0]) / math.pi) % 2) > 1
                            #flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
                            #         == (e.LastParameter > e.FirstParameter)
                            #        == (e.Orientation == "Forward")
                            # other method: check the direction of the angle between tangents
                            t1 = e.tangentAt(e.FirstParameter)
                            t2 = e.tangentAt(
                                e.FirstParameter +
                                (e.LastParameter - e.FirstParameter) / 10)
                            flag_sweep = (DraftVecUtils.angle(
                                t1, t2, drawing_plane_normal) < 0)
                            for v in endpoints:
                                edata += 'A %s %s %s %s %s %s %s ' % \
                                        (str(rx),str(ry),str(rot),\
                                        str(int(flag_large_arc)),\
                                        str(int(flag_sweep)),str(v.x),str(v.y))
                    else:
                        edata += getDiscretized(e, plane)
                elif DraftGeomUtils.geomType(e) == "Line":
                    v = getProj(vs[-1].Point, plane)
                    edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
                else:
                    bspline = e.Curve.toBSpline(e.FirstParameter,
                                                e.LastParameter)
                    if bspline.Degree > 3 or bspline.isRational():
                        try:
                            bspline = bspline.approximateBSpline(
                                0.05, 50, 3, 'C0')
                        except RuntimeError:
                            print("Debug: unable to approximate bspline")
                    if bspline.Degree <= 3 and not bspline.isRational():
                        for bezierseg in bspline.toBezier():
                            if bezierseg.Degree > 3:  #should not happen
                                raise AssertionError
                            elif bezierseg.Degree == 1:
                                edata += 'L '
                            elif bezierseg.Degree == 2:
                                edata += 'Q '
                            elif bezierseg.Degree == 3:
                                edata += 'C '
                            for pole in bezierseg.getPoles()[1:]:
                                v = getProj(pole, plane)
                                edata += str(v.x) + ' ' + str(v.y) + ' '
                    else:
                        print("Debug: one edge (hash ",e.hashCode(),\
                                ") has been discretized with parameter 0.1")
                        for linepoint in bspline.discretize(0.1)[1:]:
                            v = getProj(linepoint, plane)
                            edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
            if fill != 'none':
                edata += 'Z '
            if edata in pathdata:
                # do not draw a path on another identical path
                return ""
            else:
                svg += edata
                pathdata.append(edata)
        svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill
        try:
            svg += ';fill-opacity:' + str(fill_opacity)
        except NameError:
            pass
        svg += ';fill-rule: evenodd "'
        svg += '/>\n'
        return svg

    def getCircle(edge):
        cen = getProj(edge.Curve.Center, plane)
        rad = edge.Curve.Radius
        if hasattr(FreeCAD, "DraftWorkingPlane"):
            drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
        else:
            drawing_plane_normal = FreeCAD.Vector(0, 0, 1)
        if plane: drawing_plane_normal = plane.axis
        if round(edge.Curve.Axis.getAngle(drawing_plane_normal),
                 2) in [0, 3.14]:
            # perpendicular projection: circle
            svg = '<circle cx="' + str(cen.x)
            svg += '" cy="' + str(cen.y)
            svg += '" r="' + str(rad) + '" '
        else:
            # any other projection: ellipse
            svg = '<path d="'
            svg += getDiscretized(edge, plane)
            svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getEllipse(edge):
        cen = getProj(edge.Curve.Center, plane)
        mir = edge.Curve.MinorRadius
        mar = edge.Curve.MajorRadius
        svg = '<ellipse cx="' + str(cen.x)
        svg += '" cy="' + str(cen.y)
        svg += '" rx="' + str(mar)
        svg += '" ry="' + str(mir) + '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getArrow(arrowtype, point, arrowsize, color, linewidth, angle=0):
        svg = ""
        if gui:
            if not obj.ViewObject:
                return svg
            if obj.ViewObject.ArrowType == "Circle":
                svg += '<circle cx="' + str(point.x) + '" cy="' + str(point.y)
                svg += '" r="' + str(arrowsize) + '" '
                svg += 'fill="none" stroke="' + color + '" '
                svg += 'style="stroke-width:' + str(
                    linewidth) + ';stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Dot":
                svg += '<circle cx="' + str(point.x) + '" cy="' + str(point.y)
                svg += '" r="' + str(arrowsize) + '" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Arrow":
                svg += '<path transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale(' + str(arrowsize) + ',' + str(
                    arrowsize) + ')" freecad:skip="1" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M 0 0 L 4 1 L 4 -1 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick":
                svg += '<path transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale(' + str(arrowsize) + ',' + str(
                    arrowsize) + ')" freecad:skip="1" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M -1 -2 L 0 2 L 1 2 L 0 -2 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick-2":
                svg += '<line transform="rotate(' + str(
                    math.degrees(angle) + 45)
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += '" freecad:skip="1" '
                svg += 'fill="none" stroke="' + color + '" '
                svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
                svg += 'stroke-width:' + str(linewidth) + '" '
                svg += 'x1="-' + str(arrowsize * 2) + '" y1="0" '
                svg += 'x2="' + str(arrowsize * 2) + '" y2="0" />\n'
            else:
                print("getSVG: arrow type not implemented")
        return svg

    def getOvershoot(point, shootsize, color, linewidth, angle=0):
        svg = '<line transform="rotate(' + str(math.degrees(angle))
        svg += ',' + str(point.x) + ',' + str(point.y) + ') '
        svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
        svg += '" freecad:skip="1" '
        svg += 'fill="none" stroke="' + color + '" '
        svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
        svg += 'stroke-width:' + str(linewidth) + '" '
        svg += 'x1="0" y1="0" '
        svg += 'x2="' + str(shootsize * -1) + '" y2="0" />\n'
        return svg

    def getText(tcolor,
                fontsize,
                fontname,
                angle,
                base,
                text,
                linespacing=0.5,
                align="center",
                flip=True):
        if isinstance(angle, FreeCAD.Rotation):
            if not plane:
                angle = angle.Angle
            else:
                if plane.axis.getAngle(angle.Axis) < 0.001:
                    angle = angle.Angle
                elif abs(plane.axis.getAngle(angle.Axis) - math.pi) < 0.001:
                    if abs(angle.Angle) > 0.1:
                        angle = -angle.Angle
                    else:
                        angle = angle.Angle
                elif abs(plane.axis.getAngle(angle.Axis) -
                         math.pi / 2) < 0.001:
                    return ""  # text is perpendicular to view, so it shouldn't appear
                else:
                    angle = 0  #TODO maybe there is something better to do here?
        if not isinstance(text, list):
            text = text.split("\n")
        if align.lower() == "center":
            anchor = "middle"
        elif align.lower() == "left":
            anchor = "start"
        else:
            anchor = "end"
        if techdraw:
            svg = ""
            for i in range(len(text)):
                t = text[i].replace("&", "&amp;").replace("<", "&lt;").replace(
                    ">", "&gt;")
                if six.PY2 and not isinstance(t, six.text_type):
                    t = t.decode("utf8")
                # possible workaround if UTF8 is unsupported
                #    import unicodedata
                #    t = u"".join([c for c in unicodedata.normalize("NFKD",t) if not unicodedata.combining(c)]).encode("utf8")
                svg += '<text stroke-width="0" stroke="' + tcolor + '" fill="' + tcolor + '" font-size="' + str(
                    fontsize) + '" '
                svg += 'style="text-anchor:' + anchor + ';text-align:' + align.lower(
                ) + ';'
                svg += 'font-family:' + fontname + '" '
                svg += 'transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(
                    base.x) + ',' + str(base.y - linespacing * i) + ') '
                svg += 'translate(' + str(
                    base.x) + ',' + str(base.y - linespacing * i) + ') '
                svg += 'scale(1,-1)" '
                #svg += '" freecad:skip="1"'
                svg += '>\n' + t + '</text>\n'
        else:
            svg = '<text stroke-width="0" stroke="' + tcolor + '" fill="'
            svg += tcolor + '" font-size="'
            svg += str(fontsize) + '" '
            svg += 'style="text-anchor:' + anchor + ';text-align:' + align.lower(
            ) + ';'
            svg += 'font-family:' + fontname + '" '
            svg += 'transform="rotate(' + str(math.degrees(angle))
            svg += ',' + str(base.x) + ',' + str(base.y) + ') '
            if flip:
                svg += 'translate(' + str(base.x) + ',' + str(base.y) + ')'
            else:
                svg += 'translate(' + str(base.x) + ',' + str(-base.y) + ')'
            #svg += 'scale('+str(tmod/2000)+',-'+str(tmod/2000)+') '
            if flip:
                svg += ' scale(1,-1) '
            else:
                svg += ' scale(1,1) '
            svg += '" freecad:skip="1"'
            svg += '>\n'
            if len(text) == 1:
                try:
                    svg += text[0].replace("&", "&amp;").replace(
                        "<", "&lt;").replace(">", "&gt;")
                except:
                    svg += text[0].decode("utf8").replace(
                        "&", "&amp;").replace("<",
                                              "&lt;").replace(">", "&gt;")
            else:
                for i in range(len(text)):
                    if i == 0:
                        svg += '<tspan>'
                    else:
                        svg += '<tspan x="0" dy="' + str(linespacing) + '">'
                    try:
                        svg += text[i].replace("&", "&amp;").replace(
                            "<", "&lt;").replace(">", "&gt;")
                    except:
                        svg += text[i].decode("utf8").replace(
                            "&", "&amp;").replace("<",
                                                  "&lt;").replace(">", "&gt;")
                    svg += '</tspan>\n'
            svg += '</text>\n'
        return svg

    if not obj:
        pass

    elif isinstance(obj, Part.Shape):
        if "#" in fillstyle:
            fill = fillstyle
        elif fillstyle == "shape color":
            fill = "#888888"
        else:
            fill = 'url(#' + fillstyle + ')'
        svg += getPath(obj.Edges, pathname="")

    elif getType(obj) in ["Dimension", "LinearDimension"]:
        if gui:
            if not obj.ViewObject:
                print(
                    "export of dimensions to SVG is only available in GUI mode"
                )
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy, "p1"):
                    prx = obj.ViewObject.Proxy
                    ts = (len(prx.string) *
                          obj.ViewObject.FontSize.Value) / 4.0
                    rm = ((prx.p3.sub(prx.p2)).Length / 2.0) - ts
                    p2a = getProj(
                        prx.p2.add(
                            DraftVecUtils.scaleTo(prx.p3.sub(prx.p2), rm)),
                        plane)
                    p2b = getProj(
                        prx.p3.add(
                            DraftVecUtils.scaleTo(prx.p2.sub(prx.p3), rm)),
                        plane)
                    p1 = getProj(prx.p1, plane)
                    p2 = getProj(prx.p2, plane)
                    p3 = getProj(prx.p3, plane)
                    p4 = getProj(prx.p4, plane)
                    tbase = getProj(prx.tbase, plane)
                    r = prx.textpos.rotation.getValue().getValue()
                    rv = FreeCAD.Rotation(r[0], r[1], r[2], r[3]).multVec(
                        FreeCAD.Vector(1, 0, 0))
                    angle = -DraftVecUtils.angle(getProj(rv, plane))
                    #angle = -DraftVecUtils.angle(p3.sub(p2))

                    svg = ''
                    nolines = False
                    if hasattr(obj.ViewObject, "ShowLine"):
                        if not obj.ViewObject.ShowLine:
                            nolines = True

                    # drawing lines
                    if not nolines:
                        svg += '<path '
                    if obj.ViewObject.DisplayMode == "2D":
                        tangle = angle
                        if tangle > math.pi / 2:
                            tangle = tangle - math.pi
                        #elif (tangle <= -math.pi/2) or (tangle > math.pi/2):
                        #    tangle = tangle+math.pi
                        #tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2/scale,0),tangle))
                        if rotation != 0:
                            #print "dim: tangle:",tangle," rot: ",rotation," text: ",prx.string
                            if abs(tangle + math.radians(rotation)) < 0.0001:
                                tangle += math.pi
                                tbase = tbase.add(
                                    DraftVecUtils.rotate(
                                        Vector(0, 2 / scale, 0), tangle))
                        if not nolines:
                            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
                            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
                            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
                            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '
                    else:
                        tangle = 0
                        if rotation != 0:
                            tangle = -math.radians(rotation)
                        tbase = tbase.add(Vector(0, -2.0 / scale, 0))
                        if not nolines:
                            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
                            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
                            svg += 'L ' + str(p2a.x) + ' ' + str(p2a.y) + ' '
                            svg += 'M ' + str(p2b.x) + ' ' + str(p2b.y) + ' '
                            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
                            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '

                    if not nolines:
                        svg += 'fill="none" stroke="'
                        svg += stroke + '" '
                        svg += 'stroke-width="' + str(linewidth) + ' px" '
                        svg += 'style="stroke-width:' + str(linewidth)
                        svg += ';stroke-miterlimit:4;stroke-dasharray:none" '
                        svg += 'freecad:basepoint1="' + str(p1.x) + ' ' + str(
                            p1.y) + '" '
                        svg += 'freecad:basepoint2="' + str(p4.x) + ' ' + str(
                            p4.y) + '" '
                        svg += 'freecad:dimpoint="' + str(p2.x) + ' ' + str(
                            p2.y) + '"'
                        svg += '/>\n'

                        # drawing dimension and extension lines overshoots
                        if hasattr(obj.ViewObject, "DimOvershoot"
                                   ) and obj.ViewObject.DimOvershoot.Value:
                            shootsize = obj.ViewObject.DimOvershoot.Value / pointratio
                            svg += getOvershoot(p2, shootsize, stroke,
                                                linewidth, angle)
                            svg += getOvershoot(p3, shootsize, stroke,
                                                linewidth, angle + math.pi)
                        if hasattr(obj.ViewObject, "ExtOvershoot"
                                   ) and obj.ViewObject.ExtOvershoot.Value:
                            shootsize = obj.ViewObject.ExtOvershoot.Value / pointratio
                            shootangle = -DraftVecUtils.angle(p1.sub(p2))
                            svg += getOvershoot(p2, shootsize, stroke,
                                                linewidth, shootangle)
                            svg += getOvershoot(p3, shootsize, stroke,
                                                linewidth, shootangle)

                        # drawing arrows
                        if hasattr(obj.ViewObject, "ArrowType"):
                            arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                            if hasattr(obj.ViewObject, "FlipArrows"):
                                if obj.ViewObject.FlipArrows:
                                    angle = angle + math.pi
                            svg += getArrow(obj.ViewObject.ArrowType, p2,
                                            arrowsize, stroke, linewidth,
                                            angle)
                            svg += getArrow(obj.ViewObject.ArrowType, p3,
                                            arrowsize, stroke, linewidth,
                                            angle + math.pi)

                    # drawing text
                    svg += getText(stroke, fontsize, obj.ViewObject.FontName,
                                   tangle, tbase, prx.string)

    elif getType(obj) == "AngularDimension":
        if gui:
            if not obj.ViewObject:
                print(
                    "export of dimensions to SVG is only available in GUI mode"
                )
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy, "circle"):
                    prx = obj.ViewObject.Proxy

                    # drawing arc
                    fill = "none"
                    if obj.ViewObject.DisplayMode == "2D":
                        svg += getPath([prx.circle])
                    else:
                        if hasattr(prx, "circle1"):
                            svg += getPath([prx.circle1])
                            svg += getPath([prx.circle2])
                        else:
                            svg += getPath([prx.circle])

                    # drawing arrows
                    if hasattr(obj.ViewObject, "ArrowType"):
                        p2 = getProj(prx.p2, plane)
                        p3 = getProj(prx.p3, plane)
                        arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                        arrowlength = 4 * obj.ViewObject.ArrowSize.Value
                        u1 = getProj(
                            (prx.circle.valueAt(prx.circle.FirstParameter +
                                                arrowlength)
                             ).sub(
                                 prx.circle.valueAt(
                                     prx.circle.FirstParameter)), plane)
                        u2 = getProj(
                            (prx.circle.valueAt(prx.circle.LastParameter -
                                                arrowlength)
                             ).sub(prx.circle.valueAt(
                                 prx.circle.LastParameter)), plane)
                        angle1 = -DraftVecUtils.angle(u1)
                        angle2 = -DraftVecUtils.angle(u2)
                        if hasattr(obj.ViewObject, "FlipArrows"):
                            if obj.ViewObject.FlipArrows:
                                angle1 = angle1 + math.pi
                                angle2 = angle2 + math.pi
                        svg += getArrow(obj.ViewObject.ArrowType, p2,
                                        arrowsize, stroke, linewidth, angle1)
                        svg += getArrow(obj.ViewObject.ArrowType, p3,
                                        arrowsize, stroke, linewidth, angle2)

                    # drawing text
                    if obj.ViewObject.DisplayMode == "2D":
                        t = prx.circle.tangentAt(prx.circle.FirstParameter +
                                                 (prx.circle.LastParameter -
                                                  prx.circle.FirstParameter) /
                                                 2.0)
                        t = getProj(t, plane)
                        tangle = DraftVecUtils.angle(t)
                        if (tangle <= -math.pi / 2) or (tangle > math.pi / 2):
                            tangle = tangle + math.pi
                        tbase = getProj(
                            prx.circle.valueAt(prx.circle.FirstParameter +
                                               (prx.circle.LastParameter -
                                                prx.circle.FirstParameter) /
                                               2.0), plane)
                        tbase = tbase.add(
                            DraftVecUtils.rotate(Vector(0, 2.0 / scale, 0),
                                                 tangle))
                        #print(tbase)
                    else:
                        tangle = 0
                        tbase = getProj(prx.tbase, plane)
                    svg += getText(stroke, fontsize, obj.ViewObject.FontName,
                                   tangle, tbase, prx.string)

    elif getType(obj) == "Label":
        if getattr(obj.ViewObject, "Line",
                   True):  # some Labels may have no Line property

            def format_point(coords, action='L'):
                return "{action}{x},{y}".format(x=coords.x,
                                                y=coords.y,
                                                action=action)

            # Draw multisegment line
            proj_points = list(map(lambda x: getProj(x, plane), obj.Points))
            path_dir_list = [format_point(proj_points[0], action='M')]
            path_dir_list += map(format_point, proj_points[1:])
            path_dir_str = " ".join(path_dir_list)
            svg_path = '<path fill="none" stroke="{stroke}" stroke-width="{linewidth}" d="{directions}"/>'.format(
                stroke=stroke, linewidth=linewidth, directions=path_dir_str)
            svg += svg_path

            # Draw arrow.
            # We are different here from 3D view
            # if Line is set to 'off', no arrow is drawn
            if hasattr(obj.ViewObject, "ArrowType") and len(obj.Points) >= 2:
                last_segment = FreeCAD.Vector(obj.Points[-1] - obj.Points[-2])
                angle = -DraftVecUtils.angle(getProj(last_segment,
                                                     plane)) + math.pi
                svg += getArrow(arrowtype=obj.ViewObject.ArrowType,
                                point=proj_points[-1],
                                arrowsize=obj.ViewObject.ArrowSize.Value /
                                pointratio,
                                color=stroke,
                                linewidth=linewidth,
                                angle=angle)

        # print text
        if gui:
            if not obj.ViewObject:
                print("export of texts to SVG is only available in GUI mode")
            else:
                fontname = obj.ViewObject.TextFont
                position = getProj(obj.Placement.Base, plane)
                rotation = obj.Placement.Rotation
                justification = obj.ViewObject.TextAlignment
                text = obj.Text
                svg += getText(stroke, fontsize, fontname, rotation, position,
                               text, linespacing, justification)

    elif getType(obj) in ["Annotation", "DraftText"]:
        "returns an svg representation of a document annotation"
        if gui:
            if not obj.ViewObject:
                print("export of texts to SVG is only available in GUI mode")
            else:
                n = obj.ViewObject.FontName
                if getType(obj) == "Annotation":
                    p = getProj(obj.Position, plane)
                    r = obj.ViewObject.Rotation.getValueAs("rad")
                    t = obj.LabelText
                else:  # DraftText
                    p = getProj(obj.Placement.Base, plane)
                    r = obj.Placement.Rotation
                    t = obj.Text
                j = obj.ViewObject.Justification
                svg += getText(stroke, fontsize, n, r, p, t, linespacing, j)

    elif getType(obj) == "Axis":
        "returns the SVG representation of an Arch Axis system"
        if gui:
            if not obj.ViewObject:
                print("export of axes to SVG is only available in GUI mode")
            else:
                vobj = obj.ViewObject
                lorig = lstyle
                fill = 'none'
                rad = vobj.BubbleSize.Value / 2
                n = 0
                for e in obj.Shape.Edges:
                    lstyle = lorig
                    svg += getPath([e])
                    lstyle = "none"
                    pos = ["Start"]
                    if hasattr(vobj, "BubblePosition"):
                        if vobj.BubblePosition == "Both":
                            pos = ["Start", "End"]
                        else:
                            pos = [vobj.BubblePosition]
                    for p in pos:
                        if p == "Start":
                            p1 = e.Vertexes[0].Point
                            p2 = e.Vertexes[1].Point
                        else:
                            p1 = e.Vertexes[1].Point
                            p2 = e.Vertexes[0].Point
                        dv = p2.sub(p1)
                        dv.normalize()
                        center = p2.add(dv.scale(rad, rad, rad))
                        svg += getCircle(Part.makeCircle(rad, center))
                        if hasattr(vobj.Proxy, "bubbletexts"):
                            if len(vobj.Proxy.bubbletexts) >= n:
                                svg += '<text fill="' + stroke + '" '
                                svg += 'font-size="' + str(rad) + '" '
                                svg += 'style="text-anchor:middle;'
                                svg += 'text-align:center;'
                                svg += 'font-family: sans;" '
                                svg += 'transform="translate(' + str(
                                    center.x +
                                    rad / 4.0) + ',' + str(center.y -
                                                           rad / 3.0) + ') '
                                svg += 'scale(1,-1)"> '
                                svg += '<tspan>' + obj.ViewObject.Proxy.bubbletexts[
                                    n].string.getValues()[0] + '</tspan>\n'
                                svg += '</text>\n'
                                n += 1
                lstyle = lorig

    elif getType(obj) == "Pipe":
        fill = stroke
        if obj.Base and obj.Diameter:
            svg += getPath(obj.Base.Shape.Edges)
        for f in obj.Shape.Faces:
            if len(f.Edges) == 1:
                if isinstance(f.Edges[0].Curve, Part.Circle):
                    svg += getCircle(f.Edges[0])

    elif getType(obj) == "Rebar":
        fill = "none"
        if obj.Proxy:
            if not hasattr(obj.Proxy, "wires"):
                obj.Proxy.execute(obj)
            if hasattr(obj.Proxy, "wires"):
                svg += getPath(wires=obj.Proxy.wires)

    elif getType(obj) == "PipeConnector":
        pass

    elif getType(obj) == "Space":
        "returns an SVG fragment for the text of a space"
        if gui:
            if not obj.ViewObject:
                print("export of spaces to SVG is only available in GUI mode")
            else:
                if fillSpaces:
                    if hasattr(obj, "Proxy"):
                        if not hasattr(obj.Proxy, "face"):
                            obj.Proxy.getArea(obj, notouch=True)
                        if hasattr(obj.Proxy, "face"):
                            # setting fill
                            if gui:
                                fill = getrgb(obj.ViewObject.ShapeColor,
                                              testbw=False)
                                fill_opacity = 1 - (
                                    obj.ViewObject.Transparency / 100.0)
                            else:
                                fill = "#888888"
                            svg += getPath(wires=[obj.Proxy.face.OuterWire])
                c = getrgb(obj.ViewObject.TextColor)
                n = obj.ViewObject.FontName
                a = 0
                if rotation != 0:
                    a = math.radians(rotation)
                t1 = obj.ViewObject.Proxy.text1.string.getValues()
                t2 = obj.ViewObject.Proxy.text2.string.getValues()
                scale = obj.ViewObject.FirstLine.Value / obj.ViewObject.FontSize.Value
                f1 = fontsize * scale
                p2 = obj.Placement.multVec(
                    FreeCAD.Vector(obj.ViewObject.Proxy.coords.translation.
                                   getValue().getValue()))
                lspc = FreeCAD.Vector(obj.ViewObject.Proxy.header.translation.
                                      getValue().getValue())
                p1 = p2.add(lspc)
                j = obj.ViewObject.TextAlign
                t3 = getText(c,
                             f1,
                             n,
                             a,
                             getProj(p1, plane),
                             t1,
                             linespacing,
                             j,
                             flip=True)
                svg += t3
                if t2:
                    ofs = FreeCAD.Vector(0, -lspc.Length, 0)
                    if a:
                        ofs = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1),
                                               -rotation).multVec(ofs)
                    t4 = getText(c,
                                 fontsize,
                                 n,
                                 a,
                                 getProj(p1, plane).add(ofs),
                                 t2,
                                 linespacing,
                                 j,
                                 flip=True)
                    svg += t4

    elif obj.isDerivedFrom('Part::Feature'):
        if obj.Shape.isNull():
            return ''
        # setting fill
        if obj.Shape.Faces:
            if gui:
                try:
                    m = obj.ViewObject.DisplayMode
                except AttributeError:
                    m = None
                if (m != "Wireframe"):
                    if fillstyle == "shape color":
                        fill = getrgb(obj.ViewObject.ShapeColor, testbw=False)
                        fill_opacity = 1 - (obj.ViewObject.Transparency /
                                            100.0)
                    else:
                        fill = 'url(#' + fillstyle + ')'
                        svg += getPattern(fillstyle)
                else:
                    fill = "none"
            else:
                fill = "#888888"
        else:
            fill = 'none'

        if len(obj.Shape.Vertexes) > 1:
            wiredEdges = []
            if obj.Shape.Faces:
                for i, f in enumerate(obj.Shape.Faces):
                    # place outer wire first
                    wires = [f.OuterWire]
                    wires.extend([
                        w for w in f.Wires
                        if w.hashCode() != f.OuterWire.hashCode()
                    ])
                    svg += getPath(wires=f.Wires,pathname='%s_f%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(f.Edges)
            else:
                for i, w in enumerate(obj.Shape.Wires):
                    svg += getPath(w.Edges,pathname='%s_w%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(w.Edges)
            if len(wiredEdges) != len(obj.Shape.Edges):
                for i, e in enumerate(obj.Shape.Edges):
                    if (DraftGeomUtils.findEdge(e, wiredEdges) is None):
                        svg += getPath([e],pathname='%s_nwe%04d' % \
                                (obj.Name,i))
        else:
            # closed circle or spline
            if obj.Shape.Edges:
                if isinstance(obj.Shape.Edges[0].Curve, Part.Circle):
                    svg = getCircle(obj.Shape.Edges[0])
                else:
                    svg = getPath(obj.Shape.Edges)
        if FreeCAD.GuiUp:
            if hasattr(obj.ViewObject, "EndArrow") and hasattr(
                    obj.ViewObject,
                    "ArrowType") and (len(obj.Shape.Vertexes) > 1):
                if obj.ViewObject.EndArrow:
                    p1 = getProj(obj.Shape.Vertexes[-1].Point, plane)
                    p2 = getProj(obj.Shape.Vertexes[-2].Point, plane)
                    angle = -DraftVecUtils.angle(p2.sub(p1))
                    arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                    svg += getArrow(obj.ViewObject.ArrowType, p1, arrowsize,
                                    stroke, linewidth, angle)

    # techdraw expects bottom-to-top coordinates
    if techdraw:
        svg = '<g transform ="scale(1,-1)">\n    ' + svg + '</g>\n'
    return svg