def retrieve_thickness_from_biggest_face(freecad_object):
    area_faces = biggest_area_faces(freecad_object)
    list_edges_face1 = Part.__sortEdges__(area_faces[2][0].Edges)
    list_edges_face2 = Part.__sortEdges__(area_faces[2][1].Edges)

    list_pts_face1 = sort_quad_vertex(list_edges_face1, False)
    if list_pts_face1 is None:
        list_pts_face1 = sort_quad_vertex(list_edges_face1, True)
    if list_pts_face1 is None:
        raise ValueError("Error sorting vertex")

    list_pts_face2 = sort_quad_vertex(list_edges_face2, False)
    if list_pts_face2 is None:
        list_pts_face2 = sort_quad_vertex(list_edges_face2, True)
    if list_pts_face2 is None:
        raise ValueError("Error sorting vertex")

    min_array = []
    for vec1 in list_pts_face1:
        tab_diff = []
        for vec2 in list_pts_face2:
            tab_diff.append(vec1.sub(vec2).Length)
        min_array.append(min(tab_diff))

    counter_list = collections.Counter(min_array)
    thickness_occ = counter_list.most_common(1)

    return thickness_occ[0][0]
Example #2
0
 def getArea(self,obj):
     "returns the horizontal area at the center of the space"
     import Part,DraftGeomUtils
     if not hasattr(obj.Shape,"CenterOfMass"):
         return 0
     try:
         pl = Part.makePlane(1,1)
         pl.translate(obj.Shape.CenterOfMass)
         sh = obj.Shape.copy()
         cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
         e = sh.section(cutplane)
         e = Part.__sortEdges__(e.Edges)
         w = Part.Wire(e)
         f = Part.Face(w)
     except Part.OCCError:
         return 0
     else:
         if hasattr(obj,"PerimeterLength"):
             if w.Length != obj.PerimeterLength.Value:
                 obj.PerimeterLength = w.Length
         if hasattr(obj,"VerticalArea"):
             a = 0
             for f in sh.Faces:
                 ang = f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1))
                 if (ang > 1.57) and (ang < 1.571):
                     a += f.Area
                 if a != obj.VerticalArea.Value:
                     obj.VerticalArea = a
         #print "area of ",obj.Label," : ",f.Area
         return f.Area
Example #3
0
    def execute(self, obj):
        edge = _utils.getShape(obj, "Edge", "Edge")
        curve = curveExtend.getTrimmedCurve(edge)

        cont_start = 1
        if hasattr(obj, "TypeStart"):
            if obj.TypeStart == "G2 curve":
                cont_start = 2
        cont_end = 1
        if hasattr(obj, "TypeEnd"):
            if obj.TypeEnd == "G2 curve":
                cont_end = 2

        ext = []
        if obj.LengthStart > 0:
            ext.append(curveExtend.extendCurve( curve, 0, obj.LengthStart, cont_start))
        if obj.LengthEnd > 0:
            ext.append(curveExtend.extendCurve( curve, 1, obj.LengthEnd, cont_end))
        if not ext == []:
            if hasattr(obj, "Output"):
                if obj.Output == "SingleEdge":
                    for c in ext:
                        curve.join(c.toBSpline())
                    obj.Shape = curve.toShape()
                else:
                    ext.append(curve)
                    edges = []
                    for c in ext:
                        edges.append(Part.Edge(c))
                    w = Part.Wire(Part.__sortEdges__(edges))
                    w.fixWire()
                    obj.Shape = w
Example #4
0
 def projectFace(self,face):
     "projects a single face on the WP"
     #print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges"
     wires = []
     if not face[0].Wires:
         if DEBUG: print "Error: Unable to project face on the WP"
         return None
     norm = face[0].normalAt(0,0)
     for w in face[0].Wires:
         verts = []
         edges = Part.__sortEdges__(w.Edges)
         #print len(edges)," edges after sorting"
         for e in edges:
             v = e.Vertexes[0].Point
             #print v
             v = self.wp.getLocalCoords(v)
             verts.append(v)
         verts.append(verts[0])
         if len(verts) > 2:
             #print "new wire with ",len(verts)
             wires.append(Part.makePolygon(verts))
     try:
         sh = ArchCommands.makeFace(wires)
     except:
         if DEBUG: print "Error: Unable to project face on the WP"
         return None
     else:
         # restoring flipped normals
         vnorm = self.wp.getLocalCoords(norm)
         if vnorm.getAngle(sh.normalAt(0,0)) > 1:
             sh.reverse()
         #print "VRM: projectFace end: ",len(sh.Vertexes)," verts"
         return [sh]+face[1:]
Example #5
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if not tool or tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        self.setLabel(obj)

        output += "(" + obj.Label + ")"
        if not obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            return
        contourwire = TechDraw.findShapeOutline(baseobject.Shape,1, Vector(0,0,1))

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)
        try:
            output += self._buildPathLibarea(obj, edgelist)
        except:
            FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            if obj.ViewObject:
                obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #6
0
def getIndices(shape,offset):
    "returns a list with 2 lists: vertices and face indexes, offsetted with the given amount"
    vlist = []
    elist = []
    flist = []
    curves = None
    for e in shape.Edges:
        try:
            if not isinstance(e.Curve,Part.LineSegment):
                if not curves:
                    curves = shape.tessellate(1)
                    FreeCAD.Console.PrintWarning(translate("Arch","Found a shape containing curves, triangulating\n").decode('utf8'))
                    break
        except: # unimplemented curve type
            curves = shape.tessellate(1)
            FreeCAD.Console.PrintWarning(translate("Arch","Found a shape containing curves, triangulating\n").decode('utf8'))
            break
    if curves:
        for v in curves[0]:
            vlist.append(" "+str(round(v.x,p))+" "+str(round(v.y,p))+" "+str(round(v.z,p)))
        for f in curves[1]:
            fi = ""
            for vi in f:
                fi += " " + str(vi + offset)
            flist.append(fi)
    else:
        for v in shape.Vertexes:
            vlist.append(" "+str(round(v.X,p))+" "+str(round(v.Y,p))+" "+str(round(v.Z,p)))
        if not shape.Faces:
            for e in shape.Edges:
                if DraftGeomUtils.geomType(e) == "Line":
                    ei = " " + str(findVert(e.Vertexes[0],shape.Vertexes) + offset)
                    ei += " " + str(findVert(e.Vertexes[-1],shape.Vertexes) + offset)
                    elist.append(ei)
        for f in shape.Faces:
            if len(f.Wires) > 1:
                # if we have holes, we triangulate
                tris = f.tessellate(1)
                for fdata in tris[1]:
                    fi = ""
                    for vi in fdata:
                        vdata = Part.Vertex(tris[0][vi])
                        fi += " " + str(findVert(vdata,shape.Vertexes) + offset)
                    flist.append(fi)
            else:
                fi = ""
                # OCC vertices are unsorted. We need to sort in the right order...
                edges = Part.__sortEdges__(f.OuterWire.Edges)
                #print edges
                for e in edges:
                    #print e.Vertexes[0].Point,e.Vertexes[1].Point
                    v = e.Vertexes[0]
                    ind = findVert(v,shape.Vertexes)
                    if ind == None:
                        return None,None,None
                    fi += " " + str(ind + offset)
                flist.append(fi)
    return vlist,elist,flist
	def recompute(self,fp):

		w=fp.wire
		eds=Part.__sortEdges__(w.Shape.Edges)
		pts=[]
		for e in eds:
			ees=e.discretize(2)
			pts += ees[0:-1]

		pts.append(ees[-1])

		sp=Part.BSplineCurve()
		#sp.increaseDegree(3)
		if fp.mode=="poles":
			sp.buildFromPoles(pts)
		elif fp.mode=="interpolate":
			if fp.InitialTangent.Length<>0 and fp.FinalTangent.Length<>0: 
				sp.interpolate(pts,InitialTangent=fp.InitialTangent,FinalTangent=fp.FinalTangent)
			elif 1:
				# tangenten an einzelne Punkte
				Tangents=[]
				Tangentflags=[]
				tt=fp.Tangents
				print tt
				for i,p in enumerate(pts):
					try:
				#		print  str(tt[i])
						j=','.join(str(tt[i]).split())
				#		print j
				#		print str(fp.TangentFlags[i])
						v=eval("FreeCAD.Vector(" +  j +")")
						v.normalize()
						Tangents.append(v)
						Tangentflags.append(str(fp.TangentFlags[i]) == '1')
					except:
						print "Fehler Tangenten Vektor ", i+1
						Tangents.append(FreeCAD.Vector(1,0,0))
						Tangentflags.append(0)
				try:
					sp.interpolate(pts,Tangents=Tangents,TangentFlags=Tangentflags)
				except:
					sp.interpolate(pts)
			else:
				sp.interpolate(pts)

		elif fp.mode=="approximate":
			paramtype=fp.paramtype
			if paramtype<>'Default':
				sp.approximate(Points=pts,ParamType=paramtype,DegMax=3)
			else:
				sp.approximate(pts)
		printinfo(sp)
		return sp
Example #8
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = obj.ToolController
        if toolLoad is None or toolLoad.ToolNumber == 0:
            FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.")
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = toolLoad.Proxy.getTool(toolLoad)
            if not tool or tool.Diameter == 0:
                FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.")
                return
            else:
                self.radius = tool.Diameter/2

        output += "(" + obj.Label + ")"
        if obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            wires = []

            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                wires.extend(findWires(edgelist))

            for wire in wires:
                edgelist = wire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #9
0
 def getArea(self,obj):
     "returns the horizontal area at the center of the space"
     import Part,DraftGeomUtils
     if not hasattr(obj.Shape,"CenterOfMass"):
         return 0
     try:
         pl = Part.makePlane(1,1)
         pl.translate(obj.Shape.CenterOfMass)
         sh = obj.Shape.copy()
         cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
         e = sh.section(cutplane)
         e = Part.__sortEdges__(e.Edges)
         w = Part.Wire(e)
         f = Part.Face(w)
         return f.Area
     except Part.OCCError:
         return 0
Example #10
0
 def flattenFace(self,face):
     "Returns a face where all vertices have Z = 0"
     wires = []
     for w in face[0].Wires:
         verts = []
         edges = Part.__sortEdges__(w.Edges)
         for e in edges:
             v = e.Vertexes[0].Point
             verts.append(FreeCAD.Vector(v.x,v.y,0))
         verts.append(verts[0])
         wires.append(Part.makePolygon(verts))
     try:
         sh = Part.Face(wires)
     except Part.OCCError:
         if DEBUG: print "Error: Unable to flatten face"
         return None
     else:
         return [sh]+face[1:]
Example #11
0
def getObjectData(obj):
    result = {'name': str(obj.Label.encode("utf8"))}
    if hasattr(obj, "Description"): result['description'] = str(obj.Description)

    if FreeCADGui:
        result['color'] = \
            Draft.getrgb(obj.ViewObject.ShapeColor, testbw = False)

    if obj.isDerivedFrom("Part::Feature"):
        mesh = Mesh.Mesh(obj.Shape.tessellate(0.1))

        # Add wires
        wires = []
        for f in obj.Shape.Faces:
            for w in f.Wires:
                wo = Part.Wire(Part.__sortEdges__(w.Edges))
                wires.append([[v.x, v.y, v.z]
                              for v in wo.discretize(QuasiDeflection = 0.1)])

        result['wires'] = wires

    elif obj.isDerivedFrom("Mesh::Feature"): mesh = obj.Mesh

    # Add vertices
    count = 0
    vertices = []
    vIndex = {}

    for p in mesh.Points:
        v = p.Vector
        vIndex[p.Index] = count
        count += 1
        vertices.append([v.x, v.y, v.z])

    result['vertices'] = vertices

    # Add facets & normals
    facets = [[vIndex[i] for i in f.PointIndices] for f in mesh.Facets]
    normals = [[f.Normal.x, f.Normal.y, f.Normal.z] for f in mesh.Facets]

    result['normals'] = normals
    result['facets'] = facets

    return result
Example #12
0
 def getPathData(self,w):
     "Returns a SVG path data string from a 2D wire"
     def tostr(val):
         return str(round(val,DraftVecUtils.precision()))
     edges = Part.__sortEdges__(w.Edges)
     v = edges[0].Vertexes[0].Point
     svg = 'M '+ tostr(v.x) +' '+ tostr(v.y) + ' '
     for e in edges:
         if (DraftGeomUtils.geomType(e) == "Line") or (DraftGeomUtils.geomType(e) == "BSplineCurve"):
             v = e.Vertexes[-1].Point
             svg += 'L '+ tostr(v.x) +' '+ tostr(v.y) + ' '
         elif DraftGeomUtils.geomType(e) == "Circle":
             r = e.Curve.Radius
             v = e.Vertexes[-1].Point
             svg += 'A '+ tostr(r) + ' '+ tostr(r) +' 0 0 1 '+ tostr(v.x) +' '
             svg += tostr(v.y) + ' '
     if len(edges) > 1:
         svg += 'Z '
     return svg
Example #13
0
def get_local_axis(face):
    list_edges = Part.__sortEdges__(face.Edges)
    list_points = sort_quad_vertex(list_edges, False)
    if list_points is None:
        list_points = sort_quad_vertex(list_edges, True)
    if list_points is None:
        raise ValueError("Error sorting vertex")

    normal_face = face.normalAt(0, 0)
    y_local = None
    z_local = None
    x_local = normal_face.negative()
    z_local_not_normalized = None
    y_local_not_normalized = None
    for x in range(0, 4):
        vector1 = list_points[(x + 1) % 4] - list_points[x]
        vector2 = list_points[(x - 1) % 4] - list_points[x]
        y_local = None
        z_local = None
        if vector1.Length >= vector2.Length:
            z_local_not_normalized = vector2 * 1
            y_local_not_normalized = vector1 * 1
            y_local = vector1.normalize()
            z_local = vector2.normalize()

        else:
            z_local_not_normalized = vector1 * 1
            y_local_not_normalized = vector2 * 1
            y_local = vector2.normalize()
            z_local = vector1.normalize()

        computed_x_local = y_local.cross(z_local)

        if compare_freecad_vector(computed_x_local, x_local):
            # FreeCAD.Console.PrintMessage("\nFound\n")
            # FreeCAD.Console.PrintMessage(x_local)
            # FreeCAD.Console.PrintMessage(y_local)
            # FreeCAD.Console.PrintMessage(z_local)
            # FreeCAD.Console.PrintMessage("\n\n")
            return x_local, y_local_not_normalized, z_local_not_normalized

    return None, None, None
Example #14
0
    def getFootprint(self,obj):

        "returns a face that represents the footprint of this space"

        import Part,DraftGeomUtils
        if not hasattr(obj.Shape,"CenterOfMass"):
            return None
        try:
            pl = Part.makePlane(1,1)
            pl.translate(obj.Shape.CenterOfMass)
            sh = obj.Shape.copy()
            cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
            e = sh.section(cutplane)
            e = Part.__sortEdges__(e.Edges)
            w = Part.Wire(e)
            dv = FreeCAD.Vector(obj.Shape.CenterOfMass.x,obj.Shape.CenterOfMass.y,obj.Shape.BoundBox.ZMin)
            dv = dv.sub(obj.Shape.CenterOfMass)
            w.translate(dv)
            return Part.Face(w)
        except Part.OCCError:
            return None
Example #15
0
def p_polyhedron_action(p) :
    '''polyhedron_action : polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA faces EQ OSQUARE path_set ESQUARE COMMA keywordargument_list RPAREN SEMICOL
                      | polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA triangles EQ OSQUARE points_list_3d ESQUARE COMMA keywordargument_list RPAREN SEMICOL'''
    if printverbose: print("Polyhedron Points")
    v = []
    for i in p[6] :
        if printverbose: print(i)
        v.append(FreeCAD.Vector(float(i[0]),float(i[1]),float(i[2])))
    if printverbose:
        print(v)
        print ("Polyhedron "+p[9])
        print (p[12])
    faces_list = []    
    mypolyhed = doc.addObject('Part::Feature',p[1])
    for i in p[12] :
        if printverbose: print(i)
        v2 = FreeCAD.Vector
        pp =[v2(v[k]) for k in i]
        # Add first point to end of list to close polygon
        pp.append(pp[0])
        print("pp")
        print(pp)
        w = Part.makePolygon(pp)
        print("w")
        print(w)
        try:
           f = Part.Face(w)
        except:
            secWireList = w.Edges[:]
            f = Part.makeFilledFace(Part.__sortEdges__(secWireList))
        #f = make_face(v[int(i[0])],v[int(i[1])],v[int(i[2])])
        faces_list.append(f)
    shell=Part.makeShell(faces_list)
    solid=Part.Solid(shell).removeSplitter()
    if solid.Volume < 0:
        solid.reverse()
    mypolyhed.Shape=solid
    p[0] = [mypolyhed]
Example #16
0
def makeRoof2(baseobj=None,
              facenr=0,
              angles=[
                  45.,
              ],
              run=[],
              idrel=[
                  0,
              ],
              thickness=[
                  50.,
              ],
              overhang=[
                  100.,
              ],
              name="Roof"):
    '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on
    a closed wire or an object. You can provide a list of angles, run,
    idrel, thickness, overhang for each edges in the wire to define the
    roof shape. The default for angle is 45 and the list is
    automatically complete to match with number of edges in the wire.
    If the base object is a solid the roof take the shape.'''

    if not FreeCAD.ActiveDocument:
        FreeCAD.Console.PrintError("No active document. Aborting\n")
        return
    import Part
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
    obj.Label = translate("Arch", name)
    w = None
    _Roof(obj)
    if FreeCAD.GuiUp:
        _ViewProviderRoof(obj.ViewObject)
    if baseobj:
        obj.Base = baseobj
        if hasattr(obj.Base, 'Shape'):
            if obj.Base.Shape.Solids:
                FreeCAD.Console.PrintMessage("meng: Shape.Solids\n")
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
            else:
                if (obj.Base.Shape.Faces and obj.Face):
                    w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
                    if FreeCAD.GuiUp:
                        obj.Base.ViewObject.hide()
                    FreeCAD.Console.PrintMessage("meng: Shape.else Faces\n")
                elif obj.Base.Shape.Wires:
                    w = obj.Base.Shape.Wires[0]
                    if FreeCAD.GuiUp:
                        FreeCAD.Console.PrintMessage(
                            "meng: Shape.else Wires\n")
                        obj.Base.ViewObject.hide()
        if w:
            FreeCAD.Console.PrintMessage("meng: Wires\n")
            if w.isClosed():
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
                edges = Part.__sortEdges__(w.Edges)
                l = len(edges)

                la = len(angles)
                alist = angles
                for i in range(l - la):
                    alist.append(angles[0])
                obj.Angles = alist

                rlist = []
                minWireEdge = findMinWireEdge(w.Edges)
                minWireLength = minWireEdge['length']
                minWireIndex = minWireEdge['index']
                FreeCAD.Console.PrintMessage(str(minWireEdge) + "22222222 ,\n")
                for i in range(l):
                    # rlist.append(250.)
                    rlist.append(minWireLength / 2.)
                    FreeCAD.Console.PrintMessage(
                        str(minWireLength / 2.) + " ,\n")

                obj.Runs = rlist

                lidrel = len(idrel)
                rellist = idrel
                for i in range(l - lidrel):
                    rellist.append(0)
                obj.IdRel = rellist

                lthick = len(thickness)
                tlist = thickness
                for i in range(l - lthick):
                    tlist.append(thickness[0])
                obj.Thickness = tlist

                lover = len(overhang)
                olist = overhang
                for i in range(l - lover):
                    olist.append(overhang[0])
                obj.Overhang = olist
    obj.Face = facenr
    return obj
Example #17
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        output += "(" + obj.Label + ")"
        if obj.Side != "On":
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            holes = []
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance (shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print ("found a base object which is not a face.  Can't continue.")
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1, Vector(0,0,1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #18
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

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj, "ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(
                        baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            edges = obj.Base.Shape.Edges
            if hasattr(obj, "Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 1, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges,
                                   key=lambda x: x.CenterOfMass.z,
                                   reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges, key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
            for e in edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj, "BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(
                            DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(
                            translate(
                                "Arch",
                                "Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else:
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 0, 1))
                    angle = bvec.getAngle(axis)
                    if round(angle, Draft.precision()) != 0:
                        if round(angle, Draft.precision()) != round(
                                math.pi, Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint),
                                           DraftVecUtils.tup(rotaxis),
                                           math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(
                        DraftVecUtils.tup(bpoint),
                        DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()),
                        obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                if hasattr(obj, "Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Example #19
0
    def makeRibs(self, obj, update):
        # obj.LeadingEdge, obj.traillingedge, obj.Path, obj.Hullcurves=[obj.leadingedge,obj.traillingedge]
        ribs = []
        if update == True:
            FreeCAD.Console.PrintMessage(
                "MakeRibs update ------------------------------------\n")
            #for i in range(0,len(obj.Ribs)) :
            #    direction=FreeCAD.Vector([0,0,0])
            #    chord=obj.Ribs[i].Chord
            ###    angle=obj.Ribs[i].Placement.Rotation.Angle
            #self.updateRib(obj, obj.Ribs[i].Chord, obj.Ribs[i].Placement.Base,direction ,obj.Ribs[i].Placement.Rotation.Angle,i)
            #self.updateRib(obj, chord, posvecrib,direction, rotaxis,angle,i)
            ribs = obj.Ribs
        else:
            FreeCAD.Console.PrintMessage(
                "MakeRibs create ------------------------------------\n")
            FreeCAD.Console.PrintMessage("  Number of Hullcurves  : " +
                                         str(len(obj.Hullcurves)) + "\n")

            #--------------CurvesPathArray code--------------------------
            curvebox = FreeCAD.BoundBox(float("-inf"), float("-inf"),
                                        float("-inf"), float("inf"),
                                        float("inf"), float("inf"))
            for n in range(0, len(obj.Hullcurves)):
                cbbx = obj.Hullcurves[n].Shape.BoundBox
                if self.doScaleXYZ[n][0]:
                    if cbbx.XMin > curvebox.XMin: curvebox.XMin = cbbx.XMin
                    if cbbx.XMax < curvebox.XMax: curvebox.XMax = cbbx.XMax
                if self.doScaleXYZ[n][1]:
                    if cbbx.YMin > curvebox.YMin: curvebox.YMin = cbbx.YMin
                    if cbbx.YMax < curvebox.YMax: curvebox.YMax = cbbx.YMax
                if self.doScaleXYZ[n][2]:
                    if cbbx.ZMin > curvebox.ZMin: curvebox.ZMin = cbbx.ZMin
                    if cbbx.ZMax < curvebox.ZMax: curvebox.ZMax = cbbx.ZMax

                if len(obj.Hullcurves) > 0:
                    if curvebox.XMin == float("-inf"):
                        curvebox.XMin = obj.Hullcurves[0].Shape.BoundBox.XMin
                if curvebox.XMax == float("inf"):
                    curvebox.XMax = obj.Hullcurves[0].Shape.BoundBox.XMax
                if curvebox.YMin == float("-inf"):
                    curvebox.YMin = obj.Hullcurves[0].Shape.BoundBox.YMin
                if curvebox.YMax == float("inf"):
                    curvebox.YMax = obj.Hullcurves[0].Shape.BoundBox.YMax
                if curvebox.ZMin == float("-inf"):
                    curvebox.ZMin = obj.Hullcurves[0].Shape.BoundBox.ZMin
                if curvebox.ZMax == float("inf"):
                    curvebox.ZMax = obj.Hullcurves[0].Shape.BoundBox.ZMax

            edges = Part.__sortEdges__(obj.Path.Shape.Edges)
            leadingedge_edges = Part.__sortEdges__(
                obj.LeadingEdge.Shape.Edges
            )  #leadingedge_edges=Part.sortEdges(obj.LeadingEdge.Shape.Edges)  # deprecated !

            FreeCAD.Console.PrintMessage("  Len of edges  : " +
                                         str(len(edges)) + "\n")
            FreeCAD.Console.PrintMessage("  Items         : " +
                                         str(int(obj.Items)) + "\n")

            maxlen = obj.LeadingEdge.Shape.Length

            for n in range(0, int(obj.Items)):
                FreeCAD.Console.PrintMessage(
                    "  Rib number                 : --- " + str(n) + " ---\n")
                plen = obj.OffsetStart
                if obj.Items > 1:
                    plen += (maxlen - obj.OffsetStart -
                             obj.OffsetEnd) * n / (float(obj.Items) - 1)

                for edge in edges:
                    if plen > edge.Length:
                        plen = edge.Length
                    if plen > edge.Length:
                        print("  plen > edge.Length:")
                        #plen -= edge.Length
                    else:
                        param = edge.getParameterByLength(plen)
                        direction = edge.tangentAt(param)  # path direction
                        posvec = edge.valueAt(param)  #on path
                        posvec_path = edge.valueAt(param)

                        directionleadingedge = leadingedge_edges[0].tangentAt(
                            param)  # leadinedge direction
                        param_leadingedge = leadingedge_edges[
                            0].getParameterByLength(plen)
                        posvec_leadingedge = leadingedge_edges[0].valueAt(
                            param_leadingedge)

                        normal = CurvedShapes.getNormal(
                            obj.Base)  # get the rib normal
                        rotaxis = normal.cross(direction)

                        angle = math.degrees(normal.getAngle(direction))

                        planEdge = Part.makePlane(edge.Length, edge.Length,
                                                  FreeCAD.Vector(0, 0, 0),
                                                  direction).Faces[0]
                        FreeCAD.Console.PrintMessage(
                            "      planEdge             : " + str(planEdge) +
                            "\n")
                        uv = planEdge.Surface.parameter(posvec_path)
                        normaledge = planEdge.normalAt(uv[0], uv[1])
                        FreeCAD.Console.PrintMessage(
                            "  normaledge                 : --- " +
                            str(normaledge) + " ---\n")

                        planLeadingedge = Part.makePlane(
                            leadingedge_edges[0].Length,
                            leadingedge_edges[0].Length,
                            FreeCAD.Vector(0, 0, 0), directionleadingedge)
                        FreeCAD.Console.PrintMessage(
                            "      planLeadingedge             : " +
                            str(planLeadingedge) + "\n")
                        uv = planLeadingedge.Surface.parameter(
                            posvec_leadingedge)
                        normaLeadingedge = planLeadingedge.normalAt(
                            uv[0], uv[1])
                        FreeCAD.Console.PrintMessage(
                            "  normaLeadingedge                 c: --- " +
                            str(normaLeadingedge) + " ---\n")

                        #l=Part.Line(FreeCAD.Vector(posvec_path),normaledge)
                        ##ll=Part.Line(FreeCAD.Vector(posvec_leadingedge),normaLeadingedge)

                        #point=l.intersect(normaLeadingedge)

                        #p=App.Vector(1,1,1)
                        #posvec_path.projectToPlane(App.Vector(0,0,0),App.Vector(1,0,1))
                        #point =normaLeadingedge.cross() #
                        point = FreeCAD.Vector(
                            posvec_leadingedge.x, posvec_leadingedge.y,
                            posvec_path.z
                        )  #math.sqrt(posvec.x*posvec.x+posvec.y*posvec.y))#posvec_path.projectToPlane(planLeadingedge)

                        #point=planLeadingedge.projectPoint.(FreeCAD.Vector(posvec_path))
                        FreeCAD.Console.PrintMessage(
                            "      Intercsection                 : --- " +
                            str(point) + " ---\n")
                        #normalleadingedge=leadingedge_edges[0].normalAt(param_leadingedge)
                        #A=DraftGeomUtils.findIntersection(normaledge,normalleadingedge)
                        #posvecrib=FreeCAD.Vector(posvec_leadingedge.x, posvec_leadingedge.y,posvec_path.z)
                        #posvecrib=FreeCAD.Vector(posvec_path.x, posvec_path.y,posvec_path.z)
                        posvecrib = FreeCAD.Vector(point.x, point.y, point.z)

                        if len(obj.Ribs) < obj.Items:

                            FreeCAD.Console.PrintMessage(
                                "      Rib normal             : " +
                                str(normal) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path Plen              : " + str(plen) +
                                "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path Param             : " +
                                str(param) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path Position          : " +
                                str(posvec) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path Direction         : " +
                                str(direction) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path doScaleXYZ        : " +
                                str(self.doScaleXYZ) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      LeadingEdge doScaleXYZ : " +
                                str(self.doScaleXYZ) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Leading position       : " +
                                str(posvec_leadingedge) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Path position          : " +
                                str(posvec_path) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Rib Angle              : " +
                                str(angle) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Rotaxis                : " +
                                str(rotaxis) + "\n")
                            FreeCAD.Console.PrintMessage(
                                "      Rotaxis.Length         : " +
                                str(rotaxis.Length) + "\n")
                            #plane = Part.Plane(posvecrib, direction)
                            #Part.show(plane)
                            #bbox = CurvedShapes.boundbox_from_intersect(obj.Hullcurves, posvecrib, direction, self.doScaleXYZ,False)

                            bbox = CurvedShapes.boundbox_from_intersect(
                                obj.Hullcurves, posvec_leadingedge, direction,
                                self.doScaleXYZ, False)
                            if bbox:
                                x, y, z, scalex, scaley, scalez = scaleByBoundbox2(
                                    obj.Base.Shape, bbox, self.doScaleXYZsum)
                                FreeCAD.Console.PrintMessage("      scalex" +
                                                             str(scalex) +
                                                             " \n")
                                FreeCAD.Console.PrintMessage("      scaley" +
                                                             str(scaley) +
                                                             " \n")
                                FreeCAD.Console.PrintMessage("      scalez" +
                                                             str(scalez) +
                                                             " \n")
                                chord = scalex
                                rib = self.createRib(
                                    obj, chord, posvecrib, direction, rotaxis,
                                    angle)  # posvec_leadingedge
                                FreeCAD.Console.PrintMessage(
                                    "      Rib.Label         : " +
                                    str(rib.Label) + "\n")
                                if rib:
                                    ribs.append(rib)
                            else:
                                FreeCAD.Console.PrintMessage(
                                    "      Error : not bbox ------------\n")

        if len(ribs) > 1:
            FreeCAD.Console.PrintMessage("     Number of rib created : " +
                                         str(len(ribs)) + "\n")
            self.wingpshape(obj)
            if update == False:
                obj.Ribs = ribs

        print("------------End of makeRibs function------------")
Example #20
0
def makeAreaCurve(edges, direction, startpt=None, endpt=None):
    curveobj = area.Curve()

    cleanededges = Part.__sortEdges__(cleanedges(edges, 0.01))

    # for e in cleanededges:
    # print str(e.valueAt(e.FirstParameter)) + "," +
    # str(e.valueAt(e.LastParameter))
    edgelist = []

    if len(cleanededges) == 1:  # user selected a single edge.
        edgelist = cleanededges
    else:
        # edgelist = [] #Multiple edges.  Need to sequence the vetexes.
        # First get the first segment oriented correctly.

        # We first compare the last parameter of the first segment to see if it
        # matches either end of the second segment. If not, it must need
        # flipping.
        p0L = cleanededges[0].valueAt(cleanededges[0].LastParameter)
        if PathGeom.pointsCoincide(
                p0L, cleanededges[1].valueAt(cleanededges[1].FirstParameter)
        ) or PathGeom.pointsCoincide(
                p0L, cleanededges[1].valueAt(cleanededges[1].LastParameter)):
            edge0 = cleanededges[0]
        else:
            edge0 = PathUtils.reverseEdge(cleanededges[0])

        edgelist.append(edge0)

        # Now iterate the rest of the edges matching the last parameter of the
        # previous segment.
        for edge in cleanededges[1:]:
            if PathGeom.pointsCoincide(
                    edge.valueAt(edge.FirstParameter),
                    edgelist[-1].valueAt(edgelist[-1].LastParameter)):
                nextedge = edge
            else:
                nextedge = PathUtils.reverseEdge(edge)
            edgelist.append(nextedge)
    # print "makeareacurve 87: " + "area.Point(" +
    # str(edgelist[0].Vertexes[0].X) + ", " +
    # str(edgelist[0].Vertexes[0].Y)+")"
    curveobj.append(
        area.Point(edgelist[0].Vertexes[0].X, edgelist[0].Vertexes[0].Y))
    #     seglist =[]
    #     if direction=='CW':
    #         edgelist.reverse()
    #         for e in edgelist:
    #             seglist.append(PathUtils.reverseEdge(e)) #swap end points on every segment
    #     else:
    #         for e in edgelist:
    #             seglist.append(e)

    for s in edgelist:
        curveobj.append(makeAreaVertex(s))

    if startpt:
        # future nearest point code yet to be worked out -fixme
        #         v1 = Vector(startpt.X,startpt.Y,startpt.Z)
        #         perppoint1 = DraftGeomUtils.findPerpendicular(v1,firstedge)
        #         perppoint1 = DraftGeomUtils.findDistance(v1,firstedge)
        #         if  perppoint1:
        #             curveobj.ChangeStart(area.Point(perppoint1[0].x,perppoint1[0].y))
        #         else:
        #             curveobj.ChangeStart(area.Point(startpt.X,startpt.Y))
        curveobj.ChangeStart(area.Point(startpt.x, startpt.y))
    if endpt:
        # future nearest point code yet to be worked out -fixme
        #         v2 = Vector(endpt.X,endpt.Y,endpt.Z)
        #         perppoint2 = DraftGeomUtils.findPerpendicular(v2,lastedge)
        #         if perppoint2:
        #             curveobj.ChangeEnd(area.Point(perppoint2[0].x,perppoint2[0].y))
        #         else:
        #             curveobj.ChangeEnd(area.Point(endpt.X,endpt.Y))
        curveobj.ChangeEnd(area.Point(endpt.x, endpt.y))

    if curveobj.IsClockwise() and direction == 'CCW':
        curveobj.Reverse()
    elif not curveobj.IsClockwise() and direction == 'CW':
        curveobj.Reverse()
    return curveobj
Example #21
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

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Example #22
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = obj.ToolController
        if toolLoad is None or toolLoad.ToolNumber == 0:
            FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.")
            #return
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = toolLoad.Proxy.getTool(toolLoad)
            if not tool or tool.Diameter == 0:
                FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.")
                return
            else:
                self.radius = tool.Diameter/2

        output += "(" + obj.Label + ")"
        if obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            holes = []
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print ("found a base object which is not a face.  Can't continue.")
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1, Vector(0, 0, 1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        else:  #Try to build targets frorm the job base
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return

            if hasattr(baseobject, "Proxy"):
                if isinstance(baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                    if obj.processPerimeter:
                        shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
                        for shape in shapes:
                            for wire in shape.Wires:
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                PathLog.debug("Processing panel perimeter.  edges found: {}".format(len(edgelist)))
                            try:
                                output += self._buildPathLibarea(obj, edgelist, isHole=False)
                            except:
                                FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

                    shapes = baseobject.Proxy.getHoles(baseobject, transform=True)
                    for shape in shapes:
                        for wire in shape.Wires:
                            drillable = PathUtils.isDrillable(baseobject.Proxy, wire)
                            if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                try:
                                    output += self._buildPathLibarea(obj, edgelist, isHole=True)
                                except:
                                    FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #23
0
 def getExtrusionData(self, obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part, DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self, obj)
     if data:
         if not isinstance(data[0], list):
             # multifuses not considered here
             return data
     length = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     if obj.Normal == Vector(0, 0, 0):
         normal = Vector(0, 0, 1)
     else:
         normal = Vector(obj.Normal)
     base = None
     placement = None
     basewires = None
     # build wall layers
     layers = []
     if hasattr(obj, "Material"):
         if obj.Material:
             if hasattr(obj.Material, "Materials"):
                 varwidth = 0
                 restwidth = width - sum(obj.Material.Thicknesses)
                 if restwidth > 0:
                     varwidth = [
                         t for t in obj.Material.Thicknesses if t == 0
                     ]
                     if varwidth:
                         varwidth = restwidth / len(varwidth)
                 for t in obj.Material.Thicknesses:
                     if t:
                         layers.append(t)
                     elif varwidth:
                         layers.append(varwidth)
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Face > 0:
                     if len(obj.Base.Shape.Faces) >= obj.Face:
                         face = obj.Base.Shape.Faces[obj.Face - 1]
                         # this wall is based on a specific face of its base object
                         normal = face.normalAt(0, 0)
                         if normal.getAngle(Vector(0, 0, 1)) > math.pi / 4:
                             normal.multiply(width)
                             base = face.extrude(normal)
                             if obj.Align == "Center":
                                 base.translate(
                                     normal.negative().multiply(0.5))
                             elif obj.Align == "Right":
                                 base.translate(normal.negative())
                         else:
                             normal.multiply(height)
                             base = face.extrude(normal)
                         base, placement = self.rebase(base)
                         return (base, normal, placement)
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base, placement = self.rebase(obj.Base.Shape)
                 elif obj.Base.Shape.Wires:
                     basewires = obj.Base.Shape.Wires
                 elif len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 if basewires and width:
                     if (len(basewires) == 1) and layers:
                         basewires = [basewires[0] for l in layers]
                     layeroffset = 0
                     baseface = None
                     for i, wire in enumerate(basewires):
                         e = wire.Edges[0]
                         if isinstance(e.Curve, Part.Circle):
                             dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                         else:
                             dvec = DraftGeomUtils.vec(
                                 wire.Edges[0]).cross(normal)
                         if not DraftVecUtils.isNull(dvec):
                             dvec.normalize()
                         sh = None
                         if obj.Align == "Left":
                             off = obj.Offset.Value
                             if layers:
                                 off = off + layeroffset
                                 dvec.multiply(layers[i])
                                 layeroffset += layers[i]
                             else:
                                 dvec.multiply(width)
                             if off:
                                 dvec2 = DraftVecUtils.scaleTo(dvec, off)
                                 wire = DraftGeomUtils.offsetWire(
                                     wire, dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire, dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1, w2)
                         elif obj.Align == "Right":
                             dvec = dvec.negative()
                             off = obj.Offset.Value
                             if layers:
                                 off = off + layeroffset
                                 dvec.multiply(layers[i])
                                 layeroffset += layers[i]
                             else:
                                 dvec.multiply(width)
                             if off:
                                 dvec2 = DraftVecUtils.scaleTo(dvec, off)
                                 wire = DraftGeomUtils.offsetWire(
                                     wire, dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire, dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1, w2)
                         elif obj.Align == "Center":
                             if layers:
                                 off = width / 2 - layeroffset
                                 d1 = Vector(dvec).multiply(off)
                                 w1 = DraftGeomUtils.offsetWire(wire, d1)
                                 layeroffset += layers[i]
                                 off = width / 2 - layeroffset
                                 d1 = Vector(dvec).multiply(off)
                                 w2 = DraftGeomUtils.offsetWire(wire, d1)
                             else:
                                 dvec.multiply(width / 2)
                                 w1 = DraftGeomUtils.offsetWire(wire, dvec)
                                 dvec = dvec.negative()
                                 w2 = DraftGeomUtils.offsetWire(wire, dvec)
                             sh = DraftGeomUtils.bind(w1, w2)
                         if sh:
                             sh.fix(0.1, 0,
                                    1)  # fixes self-intersecting wires
                             f = Part.Face(sh)
                             if baseface:
                                 if layers:
                                     baseface.append(f)
                                 else:
                                     baseface = baseface.fuse(f)
                             else:
                                 if layers:
                                     baseface = [f]
                                 else:
                                     baseface = f
                     if baseface:
                         base, placement = self.rebase(baseface)
     else:
         if layers:
             totalwidth = sum(layers)
             offset = 0
             base = []
             for l in layers:
                 l2 = length / 2 or 0.5
                 w1 = -totalwidth / 2 + offset
                 w2 = w1 + l
                 v1 = Vector(-l2, w1, 0)
                 v2 = Vector(l2, w1, 0)
                 v3 = Vector(l2, w2, 0)
                 v4 = Vector(-l2, w2, 0)
                 base.append(
                     Part.Face(Part.makePolygon([v1, v2, v3, v4, v1])))
                 offset += l
         else:
             l2 = length / 2 or 0.5
             w2 = width / 2 or 0.5
             v1 = Vector(-l2, -w2, 0)
             v2 = Vector(l2, -w2, 0)
             v3 = Vector(l2, w2, 0)
             v4 = Vector(-l2, w2, 0)
             base = Part.Face(Part.makePolygon([v1, v2, v3, v4, v1]))
         placement = FreeCAD.Placement()
     if base and placement:
         extrusion = normal.multiply(height)
         return (base, extrusion, placement)
     return None
Example #24
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = obj.ToolController
        if toolLoad is None or toolLoad.ToolNumber == 0:
            FreeCAD.Console.PrintError(
                "No Tool Controller is selected. We need a tool to build a Path."
            )
            #return
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = toolLoad.Proxy.getTool(toolLoad)
            if not tool or tool.Diameter == 0:
                FreeCAD.Console.PrintError(
                    "No Tool found or diameter is zero. We need a tool to build a Path."
                )
                return
            else:
                self.radius = tool.Diameter / 2

        output += "(" + obj.Label + ")"
        if obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(
                self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            holes = []
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z),
                                         1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print(
                            "found a base object which is not a face.  Can't continue."
                        )
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1,
                                                    Vector(0, 0, 1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        else:  #Try to build targets frorm the job base
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return

            if hasattr(baseobject, "Proxy"):
                if isinstance(baseobject.Proxy,
                              ArchPanel.PanelSheet):  # process the sheet
                    if obj.processPerimeter:
                        shapes = baseobject.Proxy.getOutlines(baseobject,
                                                              transform=True)
                        for shape in shapes:
                            for wire in shape.Wires:
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                PathLog.debug(
                                    "Processing panel perimeter.  edges found: {}"
                                    .format(len(edgelist)))
                            try:
                                output += self._buildPathLibarea(obj,
                                                                 edgelist,
                                                                 isHole=False)
                            except:
                                FreeCAD.Console.PrintError(
                                    "Something unexpected happened. Unable to generate a contour path. Check project and tool config."
                                )

                    shapes = baseobject.Proxy.getHoles(baseobject,
                                                       transform=True)
                    for shape in shapes:
                        for wire in shape.Wires:
                            drillable = PathUtils.isDrillable(
                                baseobject.Proxy, wire)
                            if (drillable and obj.processCircles) or (
                                    not drillable and obj.processHoles):
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                try:
                                    output += self._buildPathLibarea(
                                        obj, edgelist, isHole=True)
                                except:
                                    FreeCAD.Console.PrintError(
                                        "Something unexpected happened. Unable to generate a contour path. Check project and tool config."
                                    )

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #25
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)
        # obj.ToolController = PathUtils.getToolControllers(obj)
        # toolLoad = PathUtils.getToolLoad(obj, obj.ToolController)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter / 2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        output += "(" + obj.Label + ")"
        if obj.Side != "On":
            output += "(Compensated Tool Path. Diameter: " + str(
                self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            # hfaces = []
            # vfaces = []
            wires = []

            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                wires.extend(findWires(edgelist))

            for wire in wires:
                edgelist = wire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #26
0
def getObjectData(obj,wireframeMode=wireframeStyle):
    """returns the geometry data of an object as three.js snippet. wireframeMode
    can be multimaterial, faceloop or None"""
    
    result = ""
    wires = []

    if obj.isDerivedFrom("Part::Feature"):
        fcmesh = obj.Shape.tessellate(0.1)
        result = "var geom = new THREE.Geometry();\n"
        # adding vertices data
        for i in range(len(fcmesh[0])):
            v = fcmesh[0][i]
            result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n"
        result += tab+"console.log(geom.vertices)\n"
        for i in range(len(fcmesh[0])):
            result += tab+"geom.vertices.push(v"+str(i)+");\n"
        # adding facets data
        for f in fcmesh[1]:
            result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n"
        for f in obj.Shape.Faces:
            for w in f.Wires:
                wo = Part.Wire(Part.__sortEdges__(w.Edges))
                wires.append(wo.discretize(QuasiDeflection=0.1))

    elif obj.isDerivedFrom("Mesh::Feature"):
        mesh = obj.Mesh
        result = "var geom = new THREE.Geometry();\n"
        # adding vertices data 
        for p in mesh.Points:
            v = p.Vector
            i = p.Index
            result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n"
        result += tab+"console.log(geom.vertices)\n"
        for p in mesh.Points:
            result += tab+"geom.vertices.push(v"+str(p.Index)+");\n"
        # adding facets data
        for f in mesh.Facets:
            result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n"
            
    if result:
        # adding a base material
        if FreeCADGui:
            col = obj.ViewObject.ShapeColor
            rgb = Draft.getrgb(col,testbw=False)
        else:
            rgb = "#888888" # test color
        result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
        #result += tab+"var basematerial = new THREE.MeshLambertMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
        
        if wireframeMode == "faceloop":
            # adding the mesh to the scene with a wireframe copy
            result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
            result += tab+"scene.add( mesh );\n"
            result += tab+"var linematerial = new THREE.LineBasicMaterial({linewidth: %d, color: 0x000000,});\n" % linewidth
            for w in wires:
                result += tab+"var wire = new THREE.Geometry();\n"
                for p in w:
                    result += tab+"wire.vertices.push(new THREE.Vector3("
                    result += str(p.x)+", "+str(p.y)+", "+str(p.z)+"));\n"
                result += tab+"var line = new THREE.Line(wire, linematerial);\n"
                result += tab+"scene.add(line);\n"
            
        elif wireframeMode == "multimaterial":
            # adding a wireframe material
            result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: "
            result += "0x000000, wireframe: true, transparent: true } );\n"
            result += tab+"var material = [ basematerial, wireframe ];\n"
            result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n"
            result += tab+"scene.add( mesh );\n"+tab
            
        else:
            # adding the mesh to the scene with simple material
            result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
            result += tab+"scene.add( mesh );\n"+tab
        
    return result
def getRebarShapeSVG(
    rebar,
    view_direction: Union[FreeCAD.Vector,
                          WorkingPlane.Plane] = FreeCAD.Vector(0, 0, 0),
    include_mark: bool = True,
    stirrup_extended_edge_offset: float = 2,
    rebar_stroke_width: float = 0.35,
    rebar_color_style: str = "shape color",
    include_dimensions: bool = True,
    rebar_dimension_units: str = "mm",
    rebar_length_dimension_precision: int = 0,
    include_units_in_dimension_label: bool = False,
    bent_angle_dimension_exclude_list: Union[Tuple[float, ...],
                                             List[float]] = (
                                                 45,
                                                 90,
                                                 180,
                                             ),
    dimension_font_family: str = "DejaVu Sans",
    dimension_font_size: float = 2,
    helical_rebar_dimension_label_format: str = "%L,r=%R,pitch=%P",
    scale: float = 1,
    max_height: float = 0,
    max_width: float = 0,
    side_padding: float = 1,
    horizontal_shape: bool = False,
) -> ElementTree.Element:
    """Generate and return rebar shape svg.

    Parameters
    ----------
    rebar: <ArchRebar._Rebar> or <rebar2.BaseRebar>
        Rebar to generate its shape svg.
    view_direction: FreeCAD.Vector or WorkingPlane.Plane, optional
        The view point direction for rebar shape.
        Default is FreeCAD.Vector(0, 0, 0) to automatically choose
        view_direction.
    include_mark: bool, optional
        If True, then rebar.Mark will be included in rebar shape svg.
        Default is True.
    stirrup_extended_edge_offset: float, optional
        The offset of extended end edges of stirrup, so that end edges of
        stirrup with 90 degree bent angle do not overlap with stirrup edges.
        Default is 2.
    rebar_stroke_width: float, optional
        The stroke-width of rebar in svg.
        Default is 0.35
    rebar_color_style: {"shape color", "color_name", "hex_value_of_color"}
        The color style of rebar.
        "shape color" means select color of rebar shape.
    include_dimensions: bool, optional
        If True, then each rebar edge dimensions and bent angle dimensions will
        be included in rebar shape svg.
    rebar_dimension_units: str, optional
        The units to be used for rebar length dimensions.
        Default is "mm".
    rebar_length_dimension_precision: int, optional
        The number of decimals that should be shown for rebar length as
        dimension label. Set it to None to use user preferred unit precision
        from FreeCAD unit preferences.
        Default is 0
    include_units_in_dimension_label: bool, optional
        If it is True, then rebar length units will be shown in dimension label.
        Default is False.
    bent_angle_dimension_exclude_list: list or tuple of float, optional
        The list of bent angles to not include their dimensions.
        Default is (45, 90, 180).
    dimension_font_family: str, optional
        The font-family of dimension text.
        Default is "DejaVu Sans".
    dimension_font_size: float, optional
        The font-size of dimension text.
        Default is 2
    helical_rebar_dimension_label_format: str, optional
        The format of helical rebar dimension label.
            %L -> Length of helical rebar
            %R -> Helix radius of helical rebar
            %P -> Helix pitch of helical rebar
        Default is "%L,r=%R,pitch=%P".
    scale: float, optional
        The scale value to scale rebar svg. The scale parameter helps to
        scale down rebar_stroke_width and dimension_font_size to make them
        resolution independent.
        If max_height or max_width is set to non-zero value, then scale
        parameter will be ignored.
        Default is 1
    max_height: float, optional
        The maximum height of rebar shape svg.
        Default is 0 to set rebar shape svg height based on scale parameter.
    max_width: float, optional
        The maximum width of rebar shape svg.
        Default is 0 to set rebar shape svg width based on scale parameter.
    side_padding: float, optional
        The padding on each side of rebar shape.
        Default is 1.
    horizontal_shape: bool, optional
        If True, then rebar shape will be made horizontal by rotating max
        length edge of rebar shape.
        Default is False.

    Returns
    -------
    ElementTree.Element
        The generated rebar shape svg.
    """
    if isinstance(view_direction, FreeCAD.Vector):
        if DraftVecUtils.isNull(view_direction):
            if (hasattr(rebar, "RebarShape")
                    and rebar.RebarShape == "HelicalRebar"):
                view_direction = rebar.Base.Placement.Rotation.multVec(
                    FreeCAD.Vector(0, -1, 0))
                if hasattr(rebar, "Direction") and not DraftVecUtils.isNull(
                        rebar.Direction):
                    view_direction = FreeCAD.Vector(rebar.Direction)
                    view_direction.normalize()
            else:
                view_direction = getRebarsSpanAxis(rebar)
        view_plane = getSVGPlaneFromAxis(view_direction)
    elif isinstance(view_direction, WorkingPlane.Plane):
        view_plane = view_direction
    else:
        FreeCAD.Console.PrintError(
            "Invalid view_direction type. Supported view_direction types: "
            "FreeCAD.Vector, WorkingPlane.Plane\n")
        return ElementTree.Element("g")

    if rebar_length_dimension_precision is None:
        # Get user preferred unit precision
        precision: int = FreeCAD.ParamGet(
            "User parameter:BaseApp/Preferences/Units").GetInt("Decimals")
    else:
        precision = abs(int(rebar_length_dimension_precision))

    rebar_color = getRebarColor(rebar, rebar_color_style)

    # Create required svg elements
    svg = getSVGRootElement()
    rebar_shape_svg = ElementTree.Element("g", attrib={"id": str(rebar.Name)})
    svg.append(rebar_shape_svg)
    rebar_edges_svg = ElementTree.Element("g")
    edge_dimension_svg = ElementTree.Element("g")
    rebar_shape_svg.extend([rebar_edges_svg, edge_dimension_svg])

    # Get basewire and fillet_basewire (basewire with round edges)
    basewire = rebar.Base.Shape.Wires[0].copy()
    fillet_radius = rebar.Rounding * rebar.Diameter.Value
    if fillet_radius:
        fillet_basewire = DraftGeomUtils.filletWire(basewire, fillet_radius)
    else:
        fillet_basewire = basewire

    (
        rebar_shape_min_x,
        rebar_shape_min_y,
        rebar_shape_max_x,
        rebar_shape_max_y,
    ) = getVertexesMinMaxXY(fillet_basewire.Vertexes, view_plane)

    # If rebar shape should be horizontal and its width is less than its
    # height, then we should rotate basewire to make rebar shape horizontal
    rebar_shape_rotation_angle = 0
    if horizontal_shape:
        line_type_edges = [
            edge for edge in basewire.Edges
            if DraftGeomUtils.geomType(edge) == "Line"
        ]
        if line_type_edges:
            max_length_edge = max(line_type_edges, key=lambda x: x.Length)
            rebar_shape_rotation_angle = math.degrees(
                DraftVecUtils.angle(
                    max_length_edge.lastVertex().Point.sub(
                        max_length_edge.firstVertex().Point),
                    view_plane.u,
                    view_plane.axis,
                ))
        elif (rebar_shape_max_x - rebar_shape_min_x) < (rebar_shape_max_y -
                                                        rebar_shape_min_y):
            rebar_shape_rotation_angle = -90
        basewire.rotate(basewire.CenterOfMass, view_plane.axis,
                        rebar_shape_rotation_angle)

        fillet_radius = rebar.Rounding * rebar.Diameter.Value
        if fillet_radius:
            fillet_basewire = DraftGeomUtils.filletWire(
                basewire, fillet_radius)
        else:
            fillet_basewire = basewire

        (
            rebar_shape_min_x,
            rebar_shape_min_y,
            rebar_shape_max_x,
            rebar_shape_max_y,
        ) = getVertexesMinMaxXY(fillet_basewire.Vertexes, view_plane)

    # Check if stirrup will be having extended edges separated apart
    if (hasattr(rebar, "RebarShape") and rebar.RebarShape == "Stirrup"
            and hasattr(rebar, "BentAngle") and rebar.BentAngle == 90):
        apply_stirrup_extended_edge_offset = True
    else:
        apply_stirrup_extended_edge_offset = False

    # Apply max_height and max_width of rebar shape svg And calculate scaling
    # factor
    rebar_shape_height = (rebar_shape_max_y - rebar_shape_min_y) or 1
    rebar_shape_width = (rebar_shape_max_x - rebar_shape_min_x) or 1
    h_scaling_factor = v_scaling_factor = scale
    if max_height:
        v_scaling_factor = (
            max_height - dimension_font_size *
            ((2 if include_mark else 0) +
             (2 if include_dimensions else 0)) - 2 * side_padding -
            (stirrup_extended_edge_offset
             if apply_stirrup_extended_edge_offset and (round(
                 getProjectionToSVGPlane(
                     Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                     view_plane,
                 ).y) in (round(rebar_shape_min_y), round(rebar_shape_max_y)))
             else 0)) / rebar_shape_height
    if max_width:
        h_scaling_factor = (
            max_width - dimension_font_size *
            (2 if include_dimensions else 0) - 2 * side_padding -
            (stirrup_extended_edge_offset
             if apply_stirrup_extended_edge_offset and (round(
                 getProjectionToSVGPlane(
                     Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                     view_plane,
                 ).x) in (round(rebar_shape_min_x), round(rebar_shape_max_x)))
             else 0)) / rebar_shape_width
    scale = min(h_scaling_factor, v_scaling_factor)
    svg_height = (
        rebar_shape_height * scale + dimension_font_size *
        ((2 if include_mark else 0) +
         (2 if include_dimensions else 0)) + 2 * side_padding +
        (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and
         (round(
             getProjectionToSVGPlane(
                 Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                 view_plane,
             ).y) in (round(rebar_shape_min_y), round(rebar_shape_max_y))) else
         0))
    svg_width = (
        rebar_shape_width * scale + dimension_font_size *
        (2 if include_dimensions else 0) + 2 * side_padding +
        (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and
         (round(
             getProjectionToSVGPlane(
                 Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                 view_plane,
             ).x) in (round(rebar_shape_min_x), round(rebar_shape_max_x))) else
         0))

    # Move (min_x, min_y) point in svg plane to (0, 0) so that entire basewire
    # should be visible in svg view box and apply required scaling
    translate_x = round(
        -(rebar_shape_min_x -
          (dimension_font_size if include_dimensions else 0) / scale -
          side_padding / scale -
          (stirrup_extended_edge_offset /
           scale if apply_stirrup_extended_edge_offset and (round(
               getProjectionToSVGPlane(
                   Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                   view_plane,
               ).x) == round(rebar_shape_min_x)) else 0)))
    translate_y = round(
        -(rebar_shape_min_y -
          ((2 if include_mark else 0) +
           (1 if include_dimensions else 0)) * dimension_font_size / scale -
          side_padding / scale -
          (stirrup_extended_edge_offset /
           scale if apply_stirrup_extended_edge_offset and (round(
               getProjectionToSVGPlane(
                   Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point,
                   view_plane,
               ).y) == round(rebar_shape_min_y)) else 0)))
    rebar_shape_svg.set(
        "transform",
        "scale({}) translate({} {})".format(scale, translate_x, translate_y),
    )

    svg.set("width", "{}mm".format(round(svg_width)))
    svg.set("height", "{}mm".format(round(svg_height)))
    svg.set("viewBox", "0 0 {} {}".format(round(svg_width), round(svg_height)))

    # Scale down rebar_stroke_width and dimension_font_size to make them
    # resolution independent
    rebar_stroke_width /= scale
    dimension_font_size /= scale

    # Include rebar.Mark in rebar shape svg
    if include_mark:
        if hasattr(rebar, "Mark"):
            mark = rebar.Mark
        elif hasattr(rebar, "MarkNumber"):
            mark = rebar.MarkNumber
        else:
            mark = ""
        rebar_shape_svg.append(
            getSVGTextElement(
                mark,
                rebar_shape_min_x,
                rebar_shape_min_y -
                (0.5 + bool(include_dimensions)) * dimension_font_size,
                dimension_font_family,
                1.5 * dimension_font_size,
            ))

    if hasattr(rebar, "RebarShape") and rebar.RebarShape == "HelicalRebar":
        helical_rebar_shape_svg = Draft.getSVG(
            rebar,
            direction=view_plane,
            linewidth=rebar_stroke_width,
            fillstyle="none",
            color=rebar_color,
        )
        if helical_rebar_shape_svg:
            helical_rebar_shape_svg_element = ElementTree.fromstring(
                "<g>{}</g>".format(helical_rebar_shape_svg))
            rebar_edges_svg.append(helical_rebar_shape_svg_element)
            helical_rebar_center = getProjectionToSVGPlane(
                rebar.Base.Shape.CenterOfMass, view_plane)
            helical_rebar_shape_svg_element.set(
                "transform",
                "rotate({} {} {})".format(
                    rebar_shape_rotation_angle,
                    helical_rebar_center.x,
                    helical_rebar_center.y,
                ),
            )

        if include_dimensions:
            # Create rebar dimension svg
            top_mid_point = FreeCAD.Vector(
                (rebar_shape_min_x + rebar_shape_max_x) / 2, rebar_shape_min_y)
            helical_rebar_length = str(
                round(
                    FreeCAD.Units.Quantity("{}mm".format(
                        rebar.Base.Shape.Wires[0].Length)).getValueAs(
                            rebar_dimension_units).Value,
                    precision,
                ))
            helix_radius = str(
                round(
                    rebar.Base.Radius.getValueAs(rebar_dimension_units).Value,
                    precision,
                ))
            helix_pitch = str(
                round(
                    rebar.Base.Pitch.getValueAs(rebar_dimension_units).Value,
                    precision,
                ))
            if "." in helical_rebar_length:
                helical_rebar_length = helical_rebar_length.rstrip("0").rstrip(
                    ".")
            if "." in helix_radius:
                helix_radius = helix_radius.rstrip("0").rstrip(".")
            if "." in helix_pitch:
                helix_pitch = helix_pitch.rstrip("0").rstrip(".")
            if include_units_in_dimension_label:
                helical_rebar_length += rebar_dimension_units
                helix_radius += rebar_dimension_units
                helix_pitch += rebar_dimension_units
            edge_dimension_svg.append(
                getSVGTextElement(
                    helical_rebar_dimension_label_format.replace(
                        "%L", helical_rebar_length).replace(
                            "%R", helix_radius).replace("%P", helix_pitch),
                    top_mid_point.x,
                    top_mid_point.y - rebar_stroke_width * 2,
                    dimension_font_family,
                    dimension_font_size,
                    "middle",
                ))
    else:
        if stirrup_extended_edge_offset and apply_stirrup_extended_edge_offset:
            basewire = getBasewireOfStirrupWithExtendedEdges(
                rebar, view_plane, stirrup_extended_edge_offset / scale)
            basewire.rotate(
                basewire.CenterOfMass,
                view_plane.axis,
                rebar_shape_rotation_angle,
            )

            fillet_radius = rebar.Rounding * rebar.Diameter.Value
            if fillet_radius:
                fillet_basewire = DraftGeomUtils.filletWire(
                    basewire, fillet_radius)
            else:
                fillet_basewire = basewire

        edges = Part.__sortEdges__(fillet_basewire.Edges)
        straight_edges = Part.__sortEdges__(rebar.Base.Shape.Wires[0].Edges)
        for edge in list(straight_edges):
            if DraftGeomUtils.geomType(edge) != "Line":
                straight_edges.remove(edge)

        current_straight_edge_index = 0
        for edge_index, edge in enumerate(edges):
            if DraftGeomUtils.geomType(edge) == "Line":
                p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point,
                                             view_plane)
                p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point,
                                             view_plane)
                # Create Edge svg
                if round(p1.x) == round(p2.x) and round(p1.y) == round(p2.y):
                    edge_svg = getPointSVG(p1,
                                           radius=2 * rebar_stroke_width,
                                           fill=rebar_color)
                else:
                    edge_svg = getLineSVG(p1, p2, rebar_stroke_width,
                                          rebar_color)

                if include_dimensions:
                    # Create edge dimension svg
                    mid_point = FreeCAD.Vector((p1.x + p2.x) / 2,
                                               (p1.y + p2.y) / 2)
                    dimension_rotation = (math.degrees(
                        math.atan((p2.y - p1.y) / (p2.x - p1.x))) if
                                          round(p2.x) != round(p1.x) else -90)
                    edge_length = str(
                        round(
                            FreeCAD.Units.Quantity("{}mm".format(
                                straight_edges[current_straight_edge_index].
                                Length)).getValueAs(
                                    rebar_dimension_units).Value,
                            precision,
                        ))
                    if "." in edge_length:
                        edge_length = edge_length.rstrip("0").rstrip(".")
                    if include_units_in_dimension_label:
                        edge_length += rebar_dimension_units
                    edge_dimension_svg.append(
                        getSVGTextElement(
                            edge_length,
                            mid_point.x,
                            mid_point.y - rebar_stroke_width * 2,
                            dimension_font_family,
                            dimension_font_size,
                            "middle",
                        ))
                    edge_dimension_svg[-1].set(
                        "transform",
                        "rotate({} {} {})".format(
                            dimension_rotation,
                            round(mid_point.x),
                            round(mid_point.y),
                        ),
                    )
                    current_straight_edge_index += 1
                    if (0 <= edge_index - 1 and DraftGeomUtils.geomType(
                            edges[edge_index - 1]) == "Line"):
                        radius = max(fillet_radius, dimension_font_size * 0.8)
                        bent_angle_svg = getEdgesAngleSVG(
                            edges[edge_index - 1],
                            edge,
                            radius,
                            view_plane,
                            dimension_font_family,
                            dimension_font_size * 0.8,
                            bent_angle_dimension_exclude_list,
                            0.2 / scale,
                        )
                        edge_dimension_svg.append(bent_angle_svg)
            elif DraftGeomUtils.geomType(edge) == "Circle":
                p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point,
                                             view_plane)
                p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point,
                                             view_plane)
                if round(p1.x) == round(p2.x) or round(p1.y) == round(p2.y):
                    edge_svg = getLineSVG(p1, p2, rebar_stroke_width,
                                          rebar_color)
                else:
                    edge_svg = getRoundEdgeSVG(edge, view_plane,
                                               rebar_stroke_width, rebar_color)
                    if include_dimensions:
                        # Create bent angle svg
                        if 0 <= edge_index - 1 and edge_index + 1 < len(edges):
                            prev_edge = edges[edge_index - 1]
                            next_edge = edges[edge_index + 1]
                            if (DraftGeomUtils.geomType(prev_edge) ==
                                    DraftGeomUtils.geomType(next_edge) ==
                                    "Line"):
                                radius = max(fillet_radius,
                                             dimension_font_size * 0.8)
                                bent_angle_svg = getEdgesAngleSVG(
                                    prev_edge,
                                    next_edge,
                                    radius,
                                    view_plane,
                                    dimension_font_family,
                                    dimension_font_size * 0.8,
                                    bent_angle_dimension_exclude_list,
                                    0.2 / scale,
                                )
                                edge_dimension_svg.append(bent_angle_svg)
            else:
                edge_svg = ElementTree.Element("g")
            rebar_edges_svg.append(edge_svg)

    return svg
Example #28
0
    def execute(self, obj):

        if self.clone(obj):
            return

        import Part, math, DraftGeomUtils
        pl = obj.Placement
        #self.baseface = None

        base = None
        w = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Solids:
                    base = obj.Base.Shape
                    #pl = obj.Base.Placement
                else:
                    if (obj.Base.Shape.Faces and obj.Face):
                        w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
                    elif obj.Base.Shape.Wires:
                        w = obj.Base.Shape.Wires[0]
        if w:
            if w.isClosed():
                self.profilsDico = []
                self.shps = []
                self.subVolshps = []
                heights = []
                edges = Part.__sortEdges__(w.Edges)
                l = len(edges)
                for i in range(l):
                    self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i],
                                            obj.IdRel[i], obj.Overhang[i],
                                            obj.Thickness[i])
                for i in range(l):
                    self.calcMissingData(i)
                for i in range(l):
                    self.calcEdgeGeometry(edges, i)
                for i in range(l):
                    self.calcDraftEdges(i)
                for i in range(l):
                    self.calcEave(i)
                for p in self.profilsDico:
                    heights.append(p["height"])
                obj.Heights = heights
                for i in range(l):
                    self.getRoofPaneProject(i)
                    profilCurrent = self.findProfil(i)
                    midpoint = DraftGeomUtils.findMidpoint(
                        profilCurrent["edge"])
                    ptsPaneProject = profilCurrent["points"]
                    lp = len(ptsPaneProject)
                    if lp != 0:
                        ptsPaneProject.append(ptsPaneProject[0])
                        edgesWire = []
                        for p in range(lp):
                            edge = Part.makeLine(ptsPaneProject[p],
                                                 ptsPaneProject[p + 1])
                            edgesWire.append(edge)
                        wire = Part.Wire(edgesWire)
                        d = wire.BoundBox.DiagonalLength
                        thicknessV = profilCurrent["thickness"] / (math.cos(
                            math.radians(profilCurrent["angle"])))
                        overhangV = profilCurrent["overhang"] * math.tan(
                            math.radians(profilCurrent["angle"]))
                        if wire.isClosed():
                            f = Part.Face(wire)
                            f = f.extrude(
                                FreeCAD.Vector(
                                    0, 0, profilCurrent["height"] + 1000000.0))
                            f.translate(
                                FreeCAD.Vector(0.0, 0.0, -2 * overhangV))
                        ptsPaneProfil = [
                            FreeCAD.Vector(-profilCurrent["overhang"],
                                           -overhangV, 0.0),
                            FreeCAD.Vector(profilCurrent["run"],
                                           profilCurrent["height"], 0.0),
                            FreeCAD.Vector(
                                profilCurrent["run"],
                                profilCurrent["height"] + thicknessV, 0.0),
                            FreeCAD.Vector(-profilCurrent["overhang"],
                                           -overhangV + thicknessV, 0.0)
                        ]
                        self.shps.append(
                            self.createProfilShape(ptsPaneProfil, midpoint,
                                                   profilCurrent["rot"],
                                                   profilCurrent["vec"],
                                                   profilCurrent["run"], d, f))
                        ## subVolume shape
                        ptsSubVolumeProfil = [
                            FreeCAD.Vector(-profilCurrent["overhang"],
                                           -overhangV, 0.0),
                            FreeCAD.Vector(profilCurrent["run"],
                                           profilCurrent["height"], 0.0),
                            FreeCAD.Vector(profilCurrent["run"],
                                           profilCurrent["height"] + 900000.0,
                                           0.0),
                            FreeCAD.Vector(-profilCurrent["overhang"],
                                           profilCurrent["height"] + 900000.0,
                                           0.0)
                        ]
                        self.subVolshps.append(
                            self.createProfilShape(ptsSubVolumeProfil,
                                                   midpoint,
                                                   profilCurrent["rot"],
                                                   profilCurrent["vec"],
                                                   profilCurrent["run"], d, f))
                ## SubVolume
                self.sub = self.subVolshps.pop()
                for s in self.subVolshps:
                    self.sub = self.sub.fuse(s)
                self.sub = self.sub.removeSplitter()
                if not self.sub.isNull():
                    if not DraftGeomUtils.isNull(pl):
                        self.sub.Placement = pl
                ## BaseVolume
                base = self.shps.pop()
                for s in self.shps:
                    base = base.fuse(s)
                base = self.processSubShapes(obj, base)
                self.applyShape(obj, base, pl, allownosolid=True)
        elif base:
            base = self.processSubShapes(obj, base)
            self.applyShape(obj, base, pl, allownosolid=True)
        else:
            FreeCAD.Console.PrintMessage(
                translate("Arch", "Unable to create a roof"))
Example #29
0
def export(exportList, filename, colors=None, camera=None):
    """Exports objects to an html file"""

    global disableCompression, base, baseFloat

    data = {'camera': {}, 'file': {}, 'objects': []}

    if not FreeCADGui and not camera:
        camera = OfflineRenderingUtils.getCamera(
            FreeCAD.ActiveDocument.FileName)

    if camera:
        # REF: https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Arch/OfflineRenderingUtils.py
        camnode = OfflineRenderingUtils.getCoinCamera(camera)
        cameraPosition = camnode.position.getValue().getValue()
        data['camera']['type'] = 'Orthographic'
        if 'PerspectiveCamera' in camera:
            data['camera']['type'] = 'Perspective'
        data['camera']['focalDistance'] = camnode.focalDistance.getValue()
        data['camera']['position_x'] = cameraPosition[0]
        data['camera']['position_y'] = cameraPosition[1]
        data['camera']['position_z'] = cameraPosition[2]
    else:
        v = FreeCADGui.ActiveDocument.ActiveView
        data['camera']['type'] = v.getCameraType()
        data['camera']['focalDistance'] = v.getCameraNode(
        ).focalDistance.getValue()
        data['camera']['position_x'] = v.viewPosition().Base.x
        data['camera']['position_y'] = v.viewPosition().Base.y
        data['camera']['position_z'] = v.viewPosition().Base.z

    # Take the objects out of groups
    objectslist = Draft.get_group_contents(exportList,
                                           walls=True,
                                           addgroups=False)
    # objectslist = Arch.pruneIncluded(objectslist)

    for obj in objectslist:

        # Pull all obj data before we dig down the links
        label = obj.Label

        color = '#cccccc'
        opacity = 1.0
        if FreeCADGui:
            color = Draft.getrgb(obj.ViewObject.ShapeColor, testbw=False)
            opacity = int((100 - obj.ViewObject.Transparency) /
                          5) / 20  # 0>>1 with step of 0.05
        elif colors:
            if label in colors:
                color = Draft.getrgb(colors[label], testbw=False)

        validObject = False
        if obj.isDerivedFrom('Mesh::Feature'):
            mesh = obj.Mesh
            validObject = True
        if obj.isDerivedFrom('Part::Feature'):
            objShape = obj.Shape
            validObject = True
        if obj.isDerivedFrom('App::Link'):
            linkPlacement = obj.LinkPlacement
            while True:  # drill down to get to the actual obj
                if obj.isDerivedFrom("App::Link"):
                    if obj.ViewObject.OverrideMaterial:
                        color = Draft.getrgb(
                            obj.ViewObject.ShapeMaterial.DiffuseColor,
                            testbw=False)
                    obj = obj.LinkedObject
                    if hasattr(obj, "__len__"):
                        FreeCAD.Console.PrintMessage(
                            label + ": Sub-Links are Unsupported.\n")
                        break
                elif obj.isDerivedFrom('Part::Feature'):
                    objShape = obj.Shape.copy(False)
                    objShape.Placement = linkPlacement
                    validObject = True
                    break
                elif obj.isDerivedFrom("Mesh::Feature"):
                    mesh = obj.Mesh.copy()
                    mesh.Placement = linkPlacement
                    validObject = True
                    break

        if not validObject: continue

        objdata = {
            'name': label,
            'color': color,
            'opacity': opacity,
            'verts': '',
            'facets': '',
            'wires': [],
            'faceColors': [],
            'facesToFacets': [],
            'floats': []
        }

        if obj.isDerivedFrom('Part::Feature'):

            deviation = 0.5
            if FreeCADGui:
                deviation = obj.ViewObject.Deviation

                # obj.ViewObject.DiffuseColor is length=1 when all faces are the same color, length=len(faces) for when they're not
                if len(obj.ViewObject.DiffuseColor) == len(objShape.Faces):
                    for fc in obj.ViewObject.DiffuseColor:
                        objdata['faceColors'].append(
                            Draft.getrgb(fc, testbw=False))

            # get verts and facets for ENTIRE object
            shapeData = objShape.tessellate(deviation)
            mesh = Mesh.Mesh(shapeData)

            if len(objShape.Faces) > 1:
                # Map each Facet created by tessellate() to a Face so that it can be colored correctly using faceColors
                # This is done by matching the results of a tessellate() on EACH FACE to the overall tessellate stored in shapeData
                # if there is any error in matching these two then we display the whole object as one face and forgo the face colors
                for f in objShape.Faces:
                    faceData = f.tessellate(deviation)
                    found = True
                    for fv in range(len(
                            faceData[0])):  # face verts. List of type Vector()
                        found = False
                        for sv in range(len(shapeData[0])):  #shape verts
                            if faceData[0][fv] == shapeData[0][
                                    sv]:  # do not use isEqual() here
                                faceData[0][
                                    fv] = sv  # replace with the index of shapeData[0]
                                found = True
                                break
                        if not found: break
                    if not found:
                        FreeCAD.Console.PrintMessage(
                            "Facet to Face Mismatch.\n")
                        objdata['facesToFacets'] = []
                        break

                    # map each of the face facets to the shape facets and make a list of shape facet indices that belong to this face
                    facetList = []
                    for ff in faceData[1]:  # face facets
                        found = False
                        for sf in range(len(shapeData[1])):  #shape facets
                            if faceData[0][ff[0]] in shapeData[1][
                                    sf] and faceData[0][ff[1]] in shapeData[1][
                                        sf] and faceData[0][
                                            ff[2]] in shapeData[1][sf]:
                                facetList.append(sf)
                                found = True
                                break
                        if not found: break
                    if not found:
                        FreeCAD.Console.PrintMessage("Facet List Mismatch.\n")
                        objdata['facesToFacets'] = []
                        break

                    objdata['facesToFacets'].append(baseEncode(facetList))

            wires = []  # Add wires
            for f in objShape.Faces:
                for w in f.Wires:
                    wo = Part.Wire(Part.__sortEdges__(w.Edges))
                    wire = []
                    for v in wo.discretize(QuasiDeflection=0.005):
                        wire.append(
                            '{:.5f}'.format(v.x)
                        )  # use strings to avoid 0.00001 written as 1e-05
                        wire.append('{:.5f}'.format(v.y))
                        wire.append('{:.5f}'.format(v.z))
                    wires.append(wire)

            if not disableCompression:
                for w in range(len(wires)):
                    for wv in range(len(wires[w])):
                        found = False
                        for f in range(len(objdata['floats'])):
                            if objdata['floats'][f] == wires[w][wv]:
                                wires[w][wv] = f
                                found = True
                                break
                        if not found:
                            objdata['floats'].append(wires[w][wv])
                            wires[w][wv] = len(objdata['floats']) - 1
                    wires[w] = baseEncode(wires[w])
            objdata['wires'] = wires

        vIndex = {}
        verts = []
        for p in range(len(mesh.Points)):
            vIndex[mesh.Points[p].Index] = p
            verts.append('{:.5f}'.format(mesh.Points[p].Vector.x))
            verts.append('{:.5f}'.format(mesh.Points[p].Vector.y))
            verts.append('{:.5f}'.format(mesh.Points[p].Vector.z))

        # create floats list to compress verts and wires being written into the JS
        if not disableCompression:
            for v in range(len(verts)):
                found = False
                for f in range(len(objdata['floats'])):
                    if objdata['floats'][f] == verts[v]:
                        verts[v] = f
                        found = True
                        break
                if not found:
                    objdata['floats'].append(verts[v])
                    verts[v] = len(objdata['floats']) - 1
        objdata['verts'] = baseEncode(verts)

        facets = []
        for f in mesh.Facets:
            for i in f.PointIndices:
                facets.append(vIndex[i])
        objdata['facets'] = baseEncode(facets)

        # compress floats
        if not disableCompression:
            # use ratio of 7x base13 to 4x base90 because 13^7 ~ 90^4
            fullstr = json.dumps(objdata['floats'], separators=(',', ':'))
            fullstr = fullstr.replace('[', '').replace(']',
                                                       '').replace('"', '')
            floatStr = ''
            baseFloatCt = len(baseFloat)
            baseCt = len(base)
            for fs in range(0, len(fullstr),
                            7):  # chunks of 7 chars, skip the first one
                str7 = fullstr[fs:(fs + 7)]
                quotient = 0
                for s in range(len(str7)):
                    quotient += baseFloat.find(str7[s]) * pow(
                        baseFloatCt, (6 - s))
                for v in range(4):
                    floatStr += base[quotient % baseCt]
                    quotient = int(quotient / baseCt)
            objdata['floats'] = floatStr

        data['objects'].append(objdata)

    html = getHTMLTemplate()

    html = html.replace('$pagetitle', FreeCAD.ActiveDocument.Label)
    version = FreeCAD.Version()
    html = html.replace('$version',
                        version[0] + '.' + version[1] + '.' + version[2])

    # Remove data compression in JS
    data['compressed'] = not disableCompression
    data['base'] = base
    data['baseFloat'] = baseFloat

    html = html.replace('$data',
                        json.dumps(data, separators=(',', ':')))  # Shape Data

    if six.PY2:
        outfile = pythonopen(filename, "wb")
    else:
        outfile = pythonopen(filename, "w")
    outfile.write(html)
    outfile.close()
    FreeCAD.Console.PrintMessage(
        translate("Arch", "Successfully written") + ' ' + filename + "\n")
Example #30
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

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            edges = obj.Base.Shape.Edges
            if hasattr(obj,"Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z,reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
            for e in edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                if hasattr(obj,"Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Example #31
0
    def proceed(self):
        """Proceed with execution of the command after proper selection."""
        if self.call:
            self.view.removeEventCallback("SoEvent", self.call)
        sel = Gui.Selection.getSelection()
        if len(sel) == 2:
            self.trimObjects(sel)
            self.finish()
            return
        self.obj = sel[0]
        self.ui.trimUi()
        self.linetrack = trackers.lineTracker()

        import DraftGeomUtils
        import Part

        if "Shape" not in self.obj.PropertiesList:
            return
        if "Placement" in self.obj.PropertiesList:
            self.placement = self.obj.Placement
        if len(self.obj.Shape.Faces) == 1:
            # simple extrude mode, the object itself is extruded
            self.extrudeMode = True
            self.ghost = [trackers.ghostTracker([self.obj])]
            self.normal = self.obj.Shape.Faces[0].normalAt(0.5, 0.5)
            for v in self.obj.Shape.Vertexes:
                self.ghost.append(trackers.lineTracker())
        elif len(self.obj.Shape.Faces) > 1:
            # face extrude mode, a new object is created
            ss = Gui.Selection.getSelectionEx()[0]
            if len(ss.SubObjects) == 1:
                if ss.SubObjects[0].ShapeType == "Face":
                    self.obj = self.doc.addObject("Part::Feature", "Face")
                    self.obj.Shape = ss.SubObjects[0]
                    self.extrudeMode = True
                    self.ghost = [trackers.ghostTracker([self.obj])]
                    self.normal = self.obj.Shape.Faces[0].normalAt(0.5, 0.5)
                    for v in self.obj.Shape.Vertexes:
                        self.ghost.append(trackers.lineTracker())
        else:
            # normal wire trimex mode
            self.color = self.obj.ViewObject.LineColor
            self.width = self.obj.ViewObject.LineWidth
            # self.obj.ViewObject.Visibility = False
            self.obj.ViewObject.LineColor = (0.5, 0.5, 0.5)
            self.obj.ViewObject.LineWidth = 1
            self.extrudeMode = False
            if self.obj.Shape.Wires:
                self.edges = self.obj.Shape.Wires[0].Edges
                self.edges = Part.__sortEdges__(self.edges)
            else:
                self.edges = self.obj.Shape.Edges
            self.ghost = []
            lc = self.color
            sc = (lc[0], lc[1], lc[2])
            sw = self.width
            for e in self.edges:
                if DraftGeomUtils.geomType(e) == "Line":
                    self.ghost.append(
                        trackers.lineTracker(scolor=sc, swidth=sw))
                else:
                    self.ghost.append(trackers.arcTracker(scolor=sc,
                                                          swidth=sw))
        if not self.ghost:
            self.finish()
        for g in self.ghost:
            g.on()
        self.activePoint = 0
        self.nodes = []
        self.shift = False
        self.alt = False
        self.force = None
        self.cv = None
        self.call = self.view.addEventCallback("SoEvent", self.action)
        _msg(translate("draft", "Pick distance"))
Example #32
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""
        toolLoad = PathUtils.getLastToolLoad(obj)
        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter / 2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        if obj.Base:
            hfaces = []
            vfaces = []
            wires = []

            for b in obj.Base:
                for sub in b[1]:
                    # we only consider the outer wire if this is a Face
                    # Horizontal and vertical faces are handled differently
                    shape = getattr(b[0].Shape, sub)
                    if numpy.isclose(shape.normalAt(0, 0).z,
                                     1):  # horizontal face
                        hfaces.append(shape)

                    elif numpy.isclose(shape.normalAt(0, 0).z,
                                       0):  # vertical face
                        vfaces.append(shape)
                    else:
                        FreeCAD.Console.PrintError(
                            translate(
                                "Path",
                                "Face doesn't appear to be parallel or perpendicular to the XY plane. No path will be generated for: \n"
                            ))
                        FreeCAD.Console.PrintError(b[0].Name + "." + sub +
                                                   "\n")
            for h in hfaces:
                wires.append(h.OuterWire)

            tempshell = Part.makeShell(vfaces)
            slices = tempshell.slice(FreeCAD.Base.Vector(0, 0, 1),
                                     tempshell.CenterOfMass.z)

            wires = wires + slices

            for wire in wires:
                if obj.Algorithm == "OCC Native":
                    output += self._buildPathOCC(obj, wire)
                else:
                    try:
                        import area
                    except:
                        FreeCAD.Console.PrintError(
                            translate(
                                "Path",
                                "libarea needs to be installed for this command to work.\n"
                            ))
                        return
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #33
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter / 2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        output += "(" + obj.Label + ")"
        if not obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(
                self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            return
        print "base object: " + baseobject.Name
        contourwire = PathUtils.silhouette(baseobject)

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)
        try:
            output += self._buildPathLibarea(obj, edgelist)
        except:
            FreeCAD.Console.PrintError(
                "Something unexpected happened. Unable to generate a contour path. Check project and tool config."
            )
        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
def getBasewireOfStirrupWithExtendedEdges(
        stirrup, view_plane: WorkingPlane.Plane,
        extension_offset: float) -> Part.Wire:
    """Returns stirrup base wire after adding extension_offset to stirrup
    extended edges, so that end edges of stirrup with 90 degree bent angle do
    not overlap with stirrup edges.

    Parameters
    ----------
    stirrup: <ArchRebar._Rebar>
        The stirrup with 90 degree bent angle.
    view_plane: WorkingPlane.Plane
        The view plane from which stirrup shape is visible.
    extension_offset: float
        The distance to move extended end edges of stirrup apart.

    Returns
    -------
    Part.Wire
        The generated stirrup base wire.
    """
    basewire = stirrup.Base.Shape.Wires[0].copy()

    # This function is meant for stirrup with bent angle 90 degree
    if stirrup.BentAngle != 90:
        return basewire

    min_x, min_y, max_x, max_y = getVertexesMinMaxXY(basewire.Vertexes,
                                                     view_plane)

    def getModifiedEndEdgePoints(end_edge, coincident_edge):
        p1 = getProjectionToSVGPlane(end_edge.firstVertex().Point, view_plane)
        p2 = getProjectionToSVGPlane(end_edge.lastVertex().Point, view_plane)
        p3 = getProjectionToSVGPlane(coincident_edge.firstVertex().Point,
                                     view_plane)
        p4 = getProjectionToSVGPlane(coincident_edge.lastVertex().Point,
                                     view_plane)

        # The extended edge is vertical and is left side of stirrup And
        # coincident edge is horizontal
        if (round(p1.x) == round(p2.x) == round(min_x)) and (round(p3.y)
                                                             == round(p4.y)):
            mod_p1 = end_edge.firstVertex().Point.add(
                extension_offset * view_plane.u.negative().normalize())
            mod_p2 = end_edge.lastVertex().Point.add(
                extension_offset * view_plane.u.negative().normalize())
        # The extended edge is vertical and is right side of stirrup And
        # coincident edge is horizontal
        elif (round(p1.x) == round(p2.x) == round(max_x)) and (round(p3.y)
                                                               == round(p4.y)):
            mod_p1 = end_edge.firstVertex().Point.add(extension_offset *
                                                      view_plane.u.normalize())
            mod_p2 = end_edge.lastVertex().Point.add(extension_offset *
                                                     view_plane.u.normalize())
        # The extended edge is horizontal and is top side of stirrup And
        # coincident edge is vertical
        elif (round(p1.y) == round(p2.y) == round(min_y)) and (round(p3.x)
                                                               == round(p4.x)):
            mod_p1 = end_edge.firstVertex().Point.add(
                extension_offset * view_plane.v.negative().normalize())
            mod_p2 = end_edge.lastVertex().Point.add(
                extension_offset * view_plane.v.negative().normalize())
        # The extended edge is horizontal and is bottom side of stirrup And
        # coincident edge is vertical
        elif (round(p1.y) == round(p2.y) == round(max_y)) and (round(p3.x)
                                                               == round(p4.x)):
            mod_p1 = end_edge.firstVertex().Point.add(extension_offset *
                                                      view_plane.v.normalize())
            mod_p2 = end_edge.lastVertex().Point.add(extension_offset *
                                                     view_plane.v.normalize())
        else:
            # Don't modify any point
            mod_p1 = end_edge.firstVertex().Point
            mod_p2 = end_edge.lastVertex().Point
        return mod_p1, mod_p2

    edges = Part.__sortEdges__(basewire.Edges)
    # Modify one end edge
    point_1, point_2 = getModifiedEndEdgePoints(edges[0], edges[1])
    edges[0] = DraftGeomUtils.edg(point_1, point_2)
    edges[1] = DraftGeomUtils.edg(point_2, edges[1].lastVertex().Point)
    # Modify second end edge
    extension_offset = -1 * extension_offset
    point_1, point_2 = getModifiedEndEdgePoints(edges[-1], edges[-2])
    edges[-1] = DraftGeomUtils.edg(point_1, point_2)
    edges[-2] = DraftGeomUtils.edg(edges[-2].firstVertex().Point, point_1)

    return DraftGeomUtils.connect(edges)
Example #35
0
 def getPath(edges=[],wires=[],pathname=None):
     import Part,DraftGeomUtils
     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 = []
         for w in wires:
             w1=w.copy()
             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
Example #36
0
    def execute(self, obj):
        debug("\n\nExecuting PipeShell\n")
        path = None
        profs = []
        edges =  _utils.getShape(obj, "Spine", "Edge")
        path = Part.Wire(Part.__sortEdges__(edges))
        if path.isValid():
            debug("Valid spine : %s"%path)
        if hasattr(obj, "Profiles"):
            profs = obj.Profiles
        if not (path and profs):
            return(None)
        debug("Creating PipeShell")
        # create the pipeShell object
        ps = Part.BRepOffsetAPI.MakePipeShell(path)
        ps.setMaxDegree(self.getprop(obj, "MaxDegree") or 3)
        ps.setMaxSegments(self.getprop(obj, "MaxSegments") or 32)
        t3 = self.getprop(obj, "Tol3d") or 1.0e-4
        tb = self.getprop(obj, "TolBound") or 1.0e-4
        ta = self.getprop(obj, "TolAng") or 1.0e-2
        ps.setTolerance(t3, tb, ta)
        
        mode = self.getprop(obj, "Mode")# or "DiscreteTrihedron"
        if mode in ["Binormal","FixedTrihedron"]:
            direction = self.getprop(obj, "Direction")
            if not direction:
                direction = FreeCAD.Vector(0,0,1)
                obj.Direction = direction
                FreeCAD.Console.PrintError("\nWrong direction, defaulting to +Z\n")
            elif direction.Length < 1e-7:
                direction = FreeCAD.Vector(0,0,1)
                obj.Direction = direction
                FreeCAD.Console.PrintError("\nDirection has null length, defaulting to +Z\n")
            if mode == "Binormal":
                debug("Binormal mode (%r)"%direction)
                ps.setBiNormalMode(direction)
            elif mode == "FixedTrihedron":
                loc = self.getprop(obj, "Location") or FreeCAD.Vector(0,0,0)
                debug("FixedTrihedron mode (%r %r)"%(loc, direction))
                ps.setTrihedronMode(loc, direction)
        elif mode == "Frenet":
            fre = self.getprop(obj, "Corrected")
            debug("Frenet mode (%r)"%fre)
            ps.setFrenetMode(fre)
        elif mode == "AuxiliarySpine":
            aux = self.getprop(obj, "Auxiliary")
            w = None
            if aux:
                if aux.Shape.Wires:
                    w = aux.Shape.Wires[0]
                elif aux.Shape.Edges:
                    w = Part.Wire(Part.__sortEdges__(aux.Shape.Edges))
            if w:
                curv = self.getprop(obj, "EquiCurvi") or False
                cont = self.getprop(obj, "Contact") or "NoContact"
                n = self.getCode(cont)
                debug("AuxiliarySpine mode (%r %s)"%(curv,cont))
                ps.setAuxiliarySpine(w,curv,n)
            else:
                FreeCAD.Console.PrintError("\nPlease set a valid Auxiliary Spine Object\n")
        elif mode == "ShapeSupport":
            sup = self.getprop(obj, "Support")
            sh = None
            if sup:
                sh = sup.Shape
            if sh:
                debug("ShapeSupport mode")
                ps.setSpineSupport(sh)
            else:
                FreeCAD.Console.PrintError("\nPlease set a valid Spine support Object\n")


        for p in profs:
            self.add(ps,p)
        
        if ps.isReady():
            output = self.getprop(obj, "Output")
            solid = self.getprop(obj, "Solid") or False
            if (output == "Surface") or (not hasattr(ps,'simulate')):
                ps.build()
                if solid:
                    ps.makeSolid()
                obj.Shape = ps.shape()
            else:
                shapes = ps.simulate(self.getprop(obj, "Samples") or 100)
                if output == "Lofted sections":
                    obj.Shape = Part.makeLoft(shapes, solid, False, False, self.getprop(obj, "MaxDegree"))
                else:
                    rails = self.getRails(shapes)
                    c = Part.Compound(shapes + rails)
                    obj.Shape = c
        else:
            FreeCAD.Console.PrintError("\nFailed to create shape\n")
Example #37
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

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.Shape:
                return
            if obj.Profile.Shape.findPlane() is None:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj, "ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(
                        baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            edges = obj.Base.Shape.Edges
            if hasattr(obj, "Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 1, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges,
                                   key=lambda x: x.CenterOfMass.z,
                                   reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges, key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
            for e in edges:
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                rot = None  # New rotation.
                # Supplying FreeCAD.Rotation() with two parallel vectors and
                # a null vector may seem strange, but the function is perfectly
                # able to handle this. Its algorithm will use default axes in
                # such cases.
                if obj.Align:
                    if normal is None:
                        rot = FreeCAD.Rotation(FreeCAD.Vector(), bvec, bvec,
                                               "ZYX")
                    else:
                        rot = FreeCAD.Rotation(FreeCAD.Vector(), normal, bvec,
                                               "ZYX")
                    profile.Placement.Rotation = rot
                if hasattr(obj, "BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.Placement.Base]
                    for edge in edges:
                        basepointliste.append(
                            DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(
                            translate("Arch",
                                      "Crossing point not found in profile.") +
                            "\n")
                        basepoint = basepointliste[0]
                else:
                    basepoint = profile.Placement.Base
                delta = bpoint.sub(basepoint)  # Translation vector.
                if obj.Offset and (not DraftVecUtils.isNull(obj.Offset)):
                    if rot is None:
                        delta = delta + obj.Offset
                    else:
                        delta = delta + rot.multVec(obj.Offset)
                profile.translate(delta)
                if obj.Rotation:
                    profile.rotate(bpoint, bvec, obj.Rotation)
                # profile = wire.makePipeShell([profile], True, False, 2) TODO buggy
                profile = profile.extrude(bvec)
                shapes.append(profile)
            if shapes:
                if hasattr(obj, "Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Example #38
0
    def Activated(self):
        b = []
        selection = FreeCADGui.Selection.getSelectionEx()
        if selection:
            if len(selection) == 4:
                base = FreeCAD.ActiveDocument.getObject(
                    (selection[0].ObjectName))
                b = base.WingPanels
                _rootRib = FreeCAD.ActiveDocument.getObject(
                    (selection[1].ObjectName))
                _path = FreeCAD.ActiveDocument.getObject(
                    (selection[2].ObjectName))
                base.WingEdges.append(_path)
                _envelope = FreeCAD.ActiveDocument.getObject(
                    (selection[3].ObjectName))
                base.WingEdges.append(_envelope)
                _leadingedge = FreeCAD.ActiveDocument.getObject(
                    (selection[3].ObjectName))  # A netoyer en doublon
                wingsketch = FreeCAD.ActiveDocument.getObject(
                    (selection[3].ObjectName))
                # Separate leadInEdge & trailingEdge
                edges = Part.sortEdges(
                    wingsketch.Shape.Edges
                )  # Separate, #edges=Part.sortEdges(wingsketch.Shape.Edges) # deprecated ?
                paths = Part.__sortEdges__(_path.Shape.Edges)
                leadInEdges = edges[0]  #id the leading edge
                trailingEdges = edges[1]  #id the trailing edge
                FreeCAD.Console.PrintMessage("Edges number : " +
                                             str(len(edges)) + "\n")
                if len(edges) != 2:
                    FreeCAD.Console.PrintMessage("Edges must be 2 and not " +
                                                 str(len(edges)) + "\n")
                    return

                nbOfPanels = len(leadInEdges)
                FreeCAD.Console.PrintMessage(
                    "-------------------- Wing Panel --------------------" +
                    "\n")
                FreeCAD.Console.PrintMessage("  Rib :" + str(_rootRib.Label) +
                                             "\n")
                FreeCAD.Console.PrintMessage("  Wing :" + str(base.Label) +
                                             "\n")
                FreeCAD.Console.PrintMessage("  Path :" + str(_path.Label) +
                                             "\n")
                FreeCAD.Console.PrintMessage("  envelope :" +
                                             str(_envelope.Label) + "\n")
                FreeCAD.Console.PrintMessage("  envelope placement:" +
                                             str(_envelope.Placement) + "\n")
                FreeCAD.Console.PrintMessage("  Number of Panels :" +
                                             str(nbOfPanels) + "\n")

                pmin = 0
                pmax = 0
                for i in range(0, nbOfPanels):  # for each panel
                    pmin = 0  #pmax
                    pmax = leadInEdges[i].Length
                    param = leadInEdges[i].getParameterByLength(pmin)
                    param2 = leadInEdges[i].getParameterByLength(pmax)
                    direction = leadInEdges[i].tangentAt(param)
                    posvec = leadInEdges[i].valueAt(param)
                    posvec2 = leadInEdges[i].valueAt(param2)

                    #normal = CurvedShapes.getNormal(obj.Base)
                    #rotaxis = normal.cross(direction)
                    #angle = math.degrees(normal.getAngle(direction))
                    bbox = leadInEdges[i].BoundBox
                    bbox2 = trailingEdges[i].BoundBox

                    FreeCAD.Console.PrintMessage("  Panel n° " + str(i) +
                                                 " ------------------------\n")
                    FreeCAD.Console.PrintMessage("  leadInEdges id        :" +
                                                 str(leadInEdges[i]) + "\n")
                    FreeCAD.Console.PrintMessage("  leadInEdges Length    :" +
                                                 str(leadInEdges[i].Length) +
                                                 "\n")
                    FreeCAD.Console.PrintMessage("  trailingEdges id      :" +
                                                 str(trailingEdges[i]) + "\n")
                    FreeCAD.Console.PrintMessage("  trailingEdges Length  :" +
                                                 str(trailingEdges[i].Length) +
                                                 "\n")
                    FreeCAD.Console.PrintMessage("  direction             :" +
                                                 str(direction) + "\n")
                    FreeCAD.Console.PrintMessage("     pmin               : " +
                                                 str(pmin) + "\n")
                    FreeCAD.Console.PrintMessage("     Param              : " +
                                                 str(param) + "\n")
                    FreeCAD.Console.PrintMessage("     Position           : " +
                                                 str(posvec) + "\n")
                    FreeCAD.Console.PrintMessage("     Position2          : " +
                                                 str(posvec2) + "\n")
                    FreeCAD.Console.PrintMessage(
                        "     BoundBox leadInEdges   : " + str(bbox) + "\n")
                    FreeCAD.Console.PrintMessage(
                        "     BoundBox trailingEdges   : " + str(bbox2) + "\n")

                    FreeCADGui.activateWorkbench("DraftWorkbench")
                    plane = WorkingPlane.plane()
                    FreeCAD.DraftWorkingPlane = plane

                    #workplane = WorkingPlane.plane()
                    workplane = FreeCAD.DraftWorkingPlane
                    v1 = FreeCAD.Vector(
                        0, 1,
                        0).normalize()  #paths[i].tangentAt(param).normalize()
                    v2 = FreeCAD.Vector(0, 0, 1).normalize()
                    #workplane.alignToPointAndAxis(v1, v2, 0)

                    #FreeCAD.DraftWorkingPlane.alignToPointAndAxis(v1, v2, 0)
                    #FreeCADGui.Snapper.toggleGrid()

                    FreeCAD.Console.PrintMessage("     V1   : " + str(v1) +
                                                 "\n")
                    FreeCAD.Console.PrintMessage("     V2   : " + str(v2) +
                                                 "\n")

                    # workplane.alignToPointAndAxis( v1, v2, 0)
                    #FreeCADGui.Snapper.toggleGrid()
                    FreeCADGui.activeDocument().activeView(
                    ).setCameraOrientation(_path.Placement.Rotation)

                    #paths[i].

                    FreeCAD.Console.PrintMessage("     pathline   : " +
                                                 str(paths[i]) + "\n")
                    #pathline=Part.Line(paths[i].Geometry)

                    myObj0 = Draft.makeSketch(paths[i], autoconstraints=True)
                    #myObj1=Part.Line(paths[i].Content)
                    myObj0.Label = "path" + str(i)

                    vec = _envelope.Placement.Rotation
                    FreeCADGui.activeDocument().activeView(
                    ).setCameraOrientation(vec)  #(0,0,0,1))
                    myObj1 = Draft.makeSketch(leadInEdges[i],
                                              name="leadInEdges" + str(i),
                                              autoconstraints=True)
                    #myObj1=Part.Line()
                    myObj1.Label = "leadInEdges" + str(i)

                    FreeCADGui.activeDocument().activeView(
                    ).setCameraOrientation(vec)
                    myObj2 = Draft.makeSketch(trailingEdges[i],
                                              autoconstraints=True)
                    myObj2.Label = "trailingEdge" + str(i)

                    obj = FreeCAD.ActiveDocument.addObject(
                        "Part::FeaturePython", "WingPanel" + str(i))

                    WingPanel(obj, _rootRib, myObj0, _envelope, myObj1, myObj2,
                              200, 100, 100, 0, 0)
                    #WingPanel(obj,_rootRib,_path,_envelope,myObj1,myObj2,200,100,100,0,0)
                    #WingPanel(obj,_rootRib,_path,_envelope,leadInEdges[i],trailingEdges[i],200,100,100,0,0)

                    #WingPanel(obj,_rootRib,_path,leadInEdges[i],trailingEdges[i],200,100,100,0,0)
                    ViewProviderPanel(obj.ViewObject)
                    b.append(obj)
                    FreeCAD.ActiveDocument.recompute()
            else:
                #---------------------création des nervures temporaires
                #_rootRib=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","RibRoot_")
                #WingRib(_rootRib,"/Users/fredericnivoix/Library/Preferences/FreeCAD/Mod/AirPlaneDesign/wingribprofil/naca/naca2412.dat",False,0,200,0,0,0,0,0,0)
                #ViewProviderWingRib(_rootRib.ViewObject)

                #_tipRib=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","RibTip_")
                #WingRib(_tipRib,"/Users/fredericnivoix/Library/Preferences/FreeCAD/Mod/AirPlaneDesign/wingribprofil/naca/naca2412.dat",False,0,200,0,500,0,0,0,0)
                #ViewProviderWingRib(_tipRib.ViewObject)

                #----------

                obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",
                                                       "WingPanel")
                WingPanel(obj, None, None, None, None, None, 200, 100, 100, 0,
                          0)
                ViewProviderPanel(obj.ViewObject)

        if selection:  #selection==None :
            try:
                #b=base.WingPanels
                #b.append(obj)
                base.WingPanels = b
            except:
                print("The selection is not a wing")
        FreeCAD.Gui.activeDocument().activeView().viewAxonometric()
        FreeCAD.Gui.SendMsgToActiveView("ViewFit")
Example #39
0
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""
        import Part,DraftGeomUtils
        data = ArchComponent.Component.getExtrusionData(self,obj)
        if data:
            if not isinstance(data[0],list):
                # multifuses not considered here
                return data
        length  = obj.Length.Value
        width = obj.Width.Value
        height = obj.Height.Value
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        if not height:
            return None
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)
        base = None
        placement = None
        self.basewires = None
        # build wall layers
        layers = []
        if hasattr(obj,"Material"):
            if obj.Material:
                if hasattr(obj.Material,"Materials"):
                    varwidth = 0
                    restwidth = width - sum(obj.Material.Thicknesses)
                    if restwidth > 0:
                        varwidth = [t for t in obj.Material.Thicknesses if t == 0]
                        if varwidth:
                            varwidth = restwidth/len(varwidth)
                    for t in obj.Material.Thicknesses:
                        if t:
                            layers.append(t)
                        elif varwidth:
                            layers.append(varwidth)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Face > 0:
                        if len(obj.Base.Shape.Faces) >= obj.Face:
                            face = obj.Base.Shape.Faces[obj.Face-1]
                            # this wall is based on a specific face of its base object
                            if obj.Normal != Vector(0,0,0):
                                normal = face.normalAt(0,0)
                            if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                                normal.multiply(width)
                                base = face.extrude(normal)
                                if obj.Align == "Center":
                                    base.translate(normal.negative().multiply(0.5))
                                elif obj.Align == "Right":
                                    base.translate(normal.negative())
                            else:
                                normal.multiply(height)
                                base = face.extrude(normal)
                            base,placement = self.rebase(base)
                            return (base,normal,placement)
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                    elif len(obj.Base.Shape.Edges) == 1:
                        self.basewires = [Part.Wire(obj.Base.Shape.Edges)]
                    else:
                        # self.basewires = obj.Base.Shape.Wires
                        self.basewires = []
                        for cluster in Part.getSortedClusters(obj.Base.Shape.Edges):
                            for c in Part.sortEdges(cluster):
                                self.basewires.append(Part.Wire(c))

                    if self.basewires and width:
                        if (len(self.basewires) == 1) and layers:
                            self.basewires = [self.basewires[0] for l in layers]
                        layeroffset = 0
                        baseface = None
                        for i,wire in enumerate(self.basewires):
                            e = wire.Edges[0]
                            if isinstance(e.Curve,Part.Circle):
                                dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                            else:
                                dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                            if not DraftVecUtils.isNull(dvec):
                                dvec.normalize()
                            sh = None
                            if obj.Align == "Left":
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Right":
                                dvec = dvec.negative()
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Center":
                                if layers:
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w1 = DraftGeomUtils.offsetWire(wire,d1)
                                    layeroffset += layers[i]
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w2 = DraftGeomUtils.offsetWire(wire,d1)
                                else:
                                    dvec.multiply(width/2)
                                    w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                    dvec = dvec.negative()
                                    w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                sh = DraftGeomUtils.bind(w1,w2)
                            if sh:
                                sh.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(sh)
                                if baseface:
                                    if layers:
                                        baseface.append(f)
                                    else:
                                        baseface = baseface.fuse(f)
                                        # baseface = baseface.removeSplitter()
                                        s = DraftGeomUtils.removeSplitter(baseface)
                                        if s:
                                            baseface = s
                                else:
                                    if layers:
                                        baseface = [f]
                                    else:
                                        baseface = f
                        if baseface:
                            base,placement = self.rebase(baseface)
        else:
            if layers:
                totalwidth = sum(layers)
                offset = 0
                base = []
                for l in layers:
                    l2 = length/2 or 0.5
                    w1 = -totalwidth/2 + offset
                    w2 = w1 + l
                    v1 = Vector(-l2,w1,0)
                    v2 = Vector(l2,w1,0)
                    v3 = Vector(l2,w2,0)
                    v4 = Vector(-l2,w2,0)
                    base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])))
                    offset += l
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
                base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            placement = FreeCAD.Placement()
        if base and placement:
            extrusion = normal.multiply(height)
            if placement.Rotation.Angle > 0:
                extrusion = placement.inverse().Rotation.multVec(extrusion)
            return (base,extrusion,placement)
        return None
Example #40
0
    def getProfiles(self, obj, noplacement=False):
        "Returns the base profile(s) of this component, if applicable"
        wires = []
        n, l, w, h = self.getDefaultValues(obj)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Extrusion"):
                if obj.Base.Base:
                    base = obj.Base.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    return [base]
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    base = obj.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    if not base.Solids:
                        if base.Faces:
                            import DraftGeomUtils
                            if not DraftGeomUtils.isCoplanar(base.Faces):
                                return []
                            return [base]

                        basewires = []
                        if not base.Wires:
                            if len(base.Edges) == 1:
                                import Part
                                basewires = [Part.Wire(base.Edges)]
                        else:
                            basewires = base.Wires
                        if basewires:
                            import DraftGeomUtils, DraftVecUtils, Part
                            for wire in basewires:
                                e = wire.Edges[0]
                                if isinstance(e.Curve, Part.Circle):
                                    dvec = e.Vertexes[0].Point.sub(
                                        e.Curve.Center)
                                else:
                                    dvec = DraftGeomUtils.vec(
                                        wire.Edges[0]).cross(n)
                                if not DraftVecUtils.isNull(dvec):
                                    dvec.normalize()
                                sh = None
                                if hasattr(obj, "Align"):
                                    if obj.Align == "Left":
                                        dvec.multiply(w)
                                        if hasattr(obj, "Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(
                                                    dvec, obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(
                                                    wire, dvec2)
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        w1 = Part.Wire(
                                            Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    elif obj.Align == "Right":
                                        dvec.multiply(w)
                                        dvec = dvec.negative()
                                        if hasattr(obj, "Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(
                                                    dvec, obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(
                                                    wire, dvec2)
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        w1 = Part.Wire(
                                            Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    elif obj.Align == "Center":
                                        dvec.multiply(w / 2)
                                        w1 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        dvec = dvec.negative()
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    if sh:
                                        wires.append(sh)
                                else:
                                    wires.append(wire)
        elif Draft.getType(obj) in ["Wall", "Structure"]:
            if (Draft.getType(obj) == "Structure") and (l > h):
                if noplacement:
                    h2 = h / 2 or 0.5
                    w2 = w / 2 or 0.5
                    v1 = Vector(-h2, -w2, 0)
                    v2 = Vector(h2, -w2, 0)
                    v3 = Vector(h2, w2, 0)
                    v4 = Vector(-h2, w2, 0)
                else:
                    h2 = h / 2 or 0.5
                    w2 = w / 2 or 0.5
                    v1 = Vector(0, -w2, -h2)
                    v2 = Vector(0, -w2, h2)
                    v3 = Vector(0, w2, h2)
                    v4 = Vector(0, w2, -h2)
            else:
                l2 = l / 2 or 0.5
                w2 = w / 2 or 0.5
                v1 = Vector(-l2, -w2, 0)
                v2 = Vector(l2, -w2, 0)
                v3 = Vector(l2, w2, 0)
                v4 = Vector(-l2, w2, 0)
            import Part
            base = Part.makePolygon([v1, v2, v3, v4, v1])
            return [base]
        return wires
Example #41
0
    def execute(self,obj):

        if self.clone(obj):
            return

        import Part, math, DraftGeomUtils
        pl = obj.Placement
        #self.baseface = None

        base = None
        w = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Solids:
                    base = obj.Base.Shape
                    #pl = obj.Base.Placement
                else:
                    if (obj.Base.Shape.Faces and obj.Face):
                        w = obj.Base.Shape.Faces[obj.Face-1].Wires[0]
                    elif obj.Base.Shape.Wires:
                        w = obj.Base.Shape.Wires[0]
        if w:
            if w.isClosed():
                self.profilsDico = []
                self.shps = []
                self.subVolshps = []
                heights = []
                edges = Part.__sortEdges__(w.Edges)
                l = len(edges)
                for i in range(l):
                    self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i])
                for i in range(l):
                    self.calcMissingData(i)
                for i in range(l):
                    self.calcEdgeGeometry(edges, i)
                for i in range(l):
                    self.calcDraftEdges(i)
                for i in range(l):
                    self.calcEave(i)
                for p in self.profilsDico:
                    heights.append(p["height"])
                obj.Heights = heights
                for i in range(l):
                    self.getRoofPaneProject(i)
                    profilCurrent = self.findProfil(i)
                    midpoint = DraftGeomUtils.findMidpoint(profilCurrent["edge"])
                    ptsPaneProject = profilCurrent["points"]
                    lp = len(ptsPaneProject)
                    if lp != 0:
                        ptsPaneProject.append(ptsPaneProject[0])
                        edgesWire = []
                        for p in range(lp):
                            edge = Part.makeLine(ptsPaneProject[p],ptsPaneProject[p+1])
                            edgesWire.append(edge)
                        wire = Part.Wire(edgesWire)
                        d = wire.BoundBox.DiagonalLength
                        thicknessV = profilCurrent["thickness"]/(math.cos(math.radians(profilCurrent["angle"])))
                        overhangV = profilCurrent["overhang"]*math.tan(math.radians(profilCurrent["angle"]))
                        if wire.isClosed():
                            f = Part.Face(wire)
                            f = f.extrude(FreeCAD.Vector(0,0,profilCurrent["height"]+1000000.0))
                            f.translate(FreeCAD.Vector(0.0,0.0,-2*overhangV))
                        ptsPaneProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+thicknessV,0.0),FreeCAD.Vector(-profilCurrent["overhang"],-overhangV+thicknessV,0.0)]
                        self.shps.append(self.createProfilShape(ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f))
                        ## subVolume shape
                        ptsSubVolumeProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+900000.0,0.0),FreeCAD.Vector(-profilCurrent["overhang"],profilCurrent["height"]+900000.0,0.0)]
                        self.subVolshps.append(self.createProfilShape(ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f))
                ## SubVolume
                self.sub = self.subVolshps.pop()
                for s in self.subVolshps:
                    self.sub = self.sub.fuse(s)
                self.sub = self.sub.removeSplitter()
                if not self.sub.isNull():
                    if not DraftGeomUtils.isNull(pl):
                        self.sub.Placement = pl
                ## BaseVolume
                base = self.shps.pop()
                for s in self.shps :
                    base = base.fuse(s)
                base = self.processSubShapes(obj,base)
                self.applyShape(obj,base,pl,allownosolid=True)
        elif base :
            base = self.processSubShapes(obj,base)
            self.applyShape(obj,base,pl,allownosolid=True)
        else:
            FreeCAD.Console.PrintMessage(translate("Arch","Unable to create a roof"))
Example #42
0
    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
Example #43
0
def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
    '''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. '''
    if firstedge:
        edgelist = wire.Edges[:]
        if wire.isClosed():
            elindex = None
            n = 0
            for e in edgelist:
                if isSameEdge(e, firstedge):
                    #                    FreeCAD.Console.PrintMessage('found first edge\n')
                    elindex = n
                n = n + 1
            l1 = edgelist[:elindex]
            l2 = edgelist[elindex:]
            newedgelist = l2 + l1

            if clockwise:
                newedgelist.reverse()
                last = newedgelist.pop(-1)
                newedgelist.insert(0, last)

            preoffset = []
            for e in newedgelist:
                if clockwise:
                    r = reverseEdge(e)
                    preoffset.append(r)
                else:
                    preoffset.append(e)

            sortedpreoff = Part.__sortEdges__(preoffset)
            wire = Part.Wire(sortedpreoff)
            #wire = findWires(sortedpreoff)[0]
        else:
            sortedpreoff = Part.__sortEdges__(edgelist)
            wire = Part.Wire(sortedpreoff)
            #wire = findWires(sortedpreoff)[0]

    edgelist = []
    for e in wire.Edges:
        if geomType(e) == "Circle":
            arclist = filterArcs(e)
            for a in arclist:
                edgelist.append(a)
        elif geomType(e) == "Line":
            edgelist.append(e)
        elif geomType(e) == "BSplineCurve" or \
                geomType(e) == "BezierCurve" or \
                geomType(e) == "Ellipse":
            edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
    #newwire = Part.Wire(edgelist)
    sortededges = Part.__sortEdges__(edgelist)
    newwire = findWires(sortededges)[0]

    print "newwire is clockwise: " + str(is_clockwise(newwire))
    if is_clockwise(newwire) is not clockwise:
        newwire.reverse()

    print "newwire is clockwise: " + str(is_clockwise(newwire))

    if Side == 'Left':
        # we use the OCC offset feature
        offset = newwire.makeOffset(radius)  # tool is outside line
    elif Side == 'Right':
        offset = newwire.makeOffset(-radius)  # tool is inside line
    else:
        if wire.isClosed():
            offset = newwire.makeOffset(0.0)
        else:
            offset = newwire
    print "offset wire is clockwise: " + str(is_clockwise(offset))
    offset.reverse()
    print "offset wire is clockwise: " + str(is_clockwise(offset))

    return offset
Example #44
0
def makeRoof(baseobj=None,
             facenr=0,
             angles=[
                 45.,
             ],
             run=[],
             idrel=[
                 0,
             ],
             thickness=[
                 50.,
             ],
             overhang=[
                 100.,
             ],
             name="Roof"):
    '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on
    a closed wire or an object. You can provide a list of angles, run,
    idrel, thickness, overhang for each edges in the wire to define the
    roof shape. The default for angle is 45 and the list is
    automatically complete to match with number of edges in the wire.
    If the base object is a solid the roof take the shape.'''
    import Part
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
    obj.Label = translate("Arch", name)
    w = None
    _Roof(obj)
    if FreeCAD.GuiUp:
        _ViewProviderRoof(obj.ViewObject)
    if baseobj:
        obj.Base = baseobj
        if obj.Base.isDerivedFrom("Part::Feature"):
            if obj.Base.Shape.Solids:
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
            else:
                if (obj.Base.Shape.Faces and obj.Face):
                    w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
                    if FreeCAD.GuiUp:
                        obj.Base.ViewObject.hide()
                elif obj.Base.Shape.Wires:
                    w = obj.Base.Shape.Wires[0]
                    if FreeCAD.GuiUp:
                        obj.Base.ViewObject.hide()
        if w:
            if w.isClosed():
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
                edges = Part.__sortEdges__(w.Edges)
                l = len(edges)

                la = len(angles)
                alist = angles
                for i in range(l - la):
                    alist.append(angles[0])
                obj.Angles = alist

                lr = len(run)
                rlist = run
                for i in range(l - lr):
                    #rlist.append(w.Edges[i].Length/2.)
                    rlist.append(250.)
                obj.Runs = rlist

                lidrel = len(idrel)
                rellist = idrel
                for i in range(l - lidrel):
                    rellist.append(0)
                obj.IdRel = rellist

                lthick = len(thickness)
                tlist = thickness
                for i in range(l - lthick):
                    tlist.append(thickness[0])
                obj.Thickness = tlist

                lover = len(overhang)
                olist = overhang
                for i in range(l - lover):
                    olist.append(overhang[0])
                obj.Overhang = olist
    obj.Face = facenr
    return obj
Example #45
0
def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
    '''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. '''
    if firstedge:
        edgelist = wire.Edges[:]
        if wire.isClosed():
            elindex = None
            n = 0
            for e in edgelist:
                if isSameEdge(e, firstedge):
                    #                    FreeCAD.Console.PrintMessage('found first edge\n')
                    elindex = n
                n = n + 1
            l1 = edgelist[:elindex]
            l2 = edgelist[elindex:]
            newedgelist = l2 + l1

            if clockwise:
                newedgelist.reverse()
                last = newedgelist.pop(-1)
                newedgelist.insert(0, last)

            preoffset = []
            for e in newedgelist:
                if clockwise:
                    r = reverseEdge(e)
                    preoffset.append(r)
                else:
                    preoffset.append(e)

            sortedpreoff = Part.__sortEdges__(preoffset)
            wire = Part.Wire(sortedpreoff)
        else:
            sortedpreoff = Part.__sortEdges__(edgelist)
            wire = Part.Wire(sortedpreoff)

    edgelist = []
    for e in wire.Edges:
        if geomType(e) == "Circle":
            arclist = filterArcs(e)
            for a in arclist:
                edgelist.append(a)
        elif geomType(e) == "Line":
            edgelist.append(e)
        elif geomType(e) == "BSplineCurve" or \
                 geomType(e) == "BezierCurve" or \
                 geomType(e) == "Ellipse":
            edgelist.append(Part.Wire(curvetowire(e, (SegLen))))

    newwire = Part.Wire(edgelist)
    if Side == 'Left':
        # we use the OCC offset feature
        offset = newwire.makeOffset(radius)  #tool is outside line
    elif Side == 'Right':
        offset = newwire.makeOffset(-radius)  #tool is inside line
    else:
        if wire.isClosed():
            offset = newwire.makeOffset(0.0)
        else:
            offset = newwire

    return offset
Example #46
0
    def getProfiles(self,obj,noplacement=False):
        "Returns the base profile(s) of this component, if applicable"
        wires = []
        n,l,w,h = self.getDefaultValues(obj)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Extrusion"):
                if obj.Base.Base:
                    base = obj.Base.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    return [base]
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    base = obj.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    if not base.Solids:
                        if base.Faces:
                            import DraftGeomUtils
                            if not DraftGeomUtils.isCoplanar(base.Faces):
                                return []
                            return [base]

                        basewires = []
                        if not base.Wires:
                            if len(base.Edges) == 1:
                                import Part
                                basewires = [Part.Wire(base.Edges)]
                        else:
                            basewires = base.Wires
                        if basewires:
                            import DraftGeomUtils,DraftVecUtils,Part
                            for wire in basewires:
                                e = wire.Edges[0]
                                if isinstance(e.Curve,Part.Circle):
                                    dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                                else:
                                    dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(n)
                                if not DraftVecUtils.isNull(dvec):
                                    dvec.normalize()
                                sh = None
                                if hasattr(obj,"Align"):
                                    if obj.Align == "Left":
                                        dvec.multiply(w)
                                        if hasattr(obj,"Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                        w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                        w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1,w2)
                                    elif obj.Align == "Right":
                                        dvec.multiply(w)
                                        dvec = dvec.negative()
                                        if hasattr(obj,"Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                        w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                        w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1,w2)
                                    elif obj.Align == "Center":
                                        dvec.multiply(w/2)
                                        w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                        dvec = dvec.negative()
                                        w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                        sh = DraftGeomUtils.bind(w1,w2)
                                    if sh:
                                        wires.append(sh)
                                else:
                                    wires.append(wire)
        elif Draft.getType(obj) in ["Wall","Structure"]:
            if (Draft.getType(obj) == "Structure") and (l > h):
                if noplacement:
                    h2 = h/2 or 0.5
                    w2 = w/2 or 0.5
                    v1 = Vector(-h2,-w2,0)
                    v2 = Vector(h2,-w2,0)
                    v3 = Vector(h2,w2,0)
                    v4 = Vector(-h2,w2,0)
                else:
                    h2 = h/2 or 0.5
                    w2 = w/2 or 0.5
                    v1 = Vector(0,-w2,-h2)
                    v2 = Vector(0,-w2,h2)
                    v3 = Vector(0,w2,h2)
                    v4 = Vector(0,w2,-h2)
            else:
                l2 = l/2 or 0.5
                w2 = w/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
            import Part
            base = Part.makePolygon([v1,v2,v3,v4,v1])
            return [base]
        return wires
Example #47
0
def getObjectData(obj, wireframeMode=wireframeStyle, color=None):
    """returns the geometry data of an object as three.js snippet. 
    wireframeMode can be multimaterial, faceloop, or None"""

    result = ""
    wires = []

    if hasattr(obj, 'Shape'):
        fcmesh = obj.Shape.tessellate(0.1)
        result = "var geom = new THREE.Geometry();\n"
        # adding vertices data
        for i in range(len(fcmesh[0])):
            v = fcmesh[0][i]
            result += tab + "var v" + str(i) + " = new THREE.Vector3(" + str(
                v.x) + "," + str(v.y) + "," + str(v.z) + ");\n"
        result += tab + "console.log(geom.vertices)\n"
        for i in range(len(fcmesh[0])):
            result += tab + "geom.vertices.push(v" + str(i) + ");\n"
        # adding facets data
        for f in fcmesh[1]:
            result += tab + "geom.faces.push( new THREE.Face3" + str(
                f).replace("L", "") + " );\n"
        for f in obj.Shape.Faces:
            for w in f.Wires:
                wo = Part.Wire(Part.__sortEdges__(w.Edges))
                wires.append(wo.discretize(QuasiDeflection=0.1))

    elif obj.isDerivedFrom("Mesh::Feature"):
        mesh = obj.Mesh
        result = "var geom = new THREE.Geometry();\n"
        # adding vertices data
        for p in mesh.Points:
            v = p.Vector
            i = p.Index
            result += tab + "var v" + str(i) + " = new THREE.Vector3(" + str(
                v.x) + "," + str(v.y) + "," + str(v.z) + ");\n"
        result += tab + "console.log(geom.vertices)\n"
        for p in mesh.Points:
            result += tab + "geom.vertices.push(v" + str(p.Index) + ");\n"
        # adding facets data
        for f in mesh.Facets:
            pointIndices = tuple([int(i) for i in f.PointIndices])
            result += tab + "geom.faces.push( new THREE.Face3" + str(
                pointIndices).replace("L", "") + " );\n"

    if result:
        # adding a base material
        if color:
            rgb = Draft.getrgb(color, testbw=False)
        elif FreeCADGui:
            col = obj.ViewObject.ShapeColor
            rgb = Draft.getrgb(col, testbw=False)
        else:
            rgb = "#888888"  # test color
        result += tab + "var basematerial = new THREE.MeshBasicMaterial( { color: 0x" + str(
            rgb)[1:] + " } );\n"
        #result += tab+"var basematerial = new THREE.MeshLambertMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"

        if wireframeMode == "faceloop":
            # adding the mesh to the scene with a wireframe copy
            result += tab + "var mesh = new THREE.Mesh( geom, basematerial );\n"
            result += tab + "scene.add( mesh );\n"
            result += tab + "var linematerial = new THREE.LineBasicMaterial({linewidth: %d, color: 0x000000,});\n" % linewidth
            for w in wires:
                result += tab + "var wire = new THREE.Geometry();\n"
                for p in w:
                    result += tab + "wire.vertices.push(new THREE.Vector3("
                    result += str(p.x) + ", " + str(p.y) + ", " + str(
                        p.z) + "));\n"
                result += tab + "var line = new THREE.Line(wire, linematerial);\n"
                result += tab + "scene.add(line);\n"

        elif wireframeMode == "multimaterial":
            # adding a wireframe material
            result += tab + "var wireframe = new THREE.MeshBasicMaterial( { color: "
            result += "0x000000, wireframe: true, transparent: true } );\n"
            result += tab + "var material = [ basematerial, wireframe ];\n"
            result += tab + "var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n"
            result += tab + "scene.add( mesh );\n" + tab

        else:
            # adding the mesh to the scene with simple material
            result += tab + "var mesh = new THREE.Mesh( geom, basematerial );\n"
            result += tab + "scene.add( mesh );\n" + tab

    return result
Example #48
0
    def execute(self, obj):

        if not obj.Active:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
            return

        #Tool may have changed.  Refresh data
        toolLoad = PathUtils.getLastToolLoad(obj)
        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horiRrapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter / 2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        #Build preliminary comments
        output = ""
        output += "(" + obj.Label + ")"

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        #Facing is done either against base objects
        if obj.Base:
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                    else:
                        print('falling out')
                        return
            planeshape = Part.makeCompound(faces)

        #If no base object, do planing of top surface of entire model
        else:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return
            planeshape = baseobject.Shape

        #if user wants the boundbox, calculate that
        if obj.BoundaryShape == 'Boundbox':
            bb = planeshape.BoundBox
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1,
                                   Vector(bb.XMin, bb.YMin, bb.ZMin),
                                   Vector(0, 0, 1))
            contourwire = TechDraw.findShapeOutline(bbperim, 1,
                                                    Vector(0, 0, 1))
        else:
            contourwire = TechDraw.findShapeOutline(planeshape, 1,
                                                    Vector(0, 0, 1))

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)

        #use libarea to build the pattern
        a = area.Area()
        c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW')
        a.append(c)
        a.Reorder()
        output += self.buildpathlibarea(obj, a)

        path = Path.Path(output)
        obj.Path = path
        obj.ViewObject.Visibility = True
def makeAreaCurve(edges, direction, startpt=None, endpt=None):
    curveobj = area.Curve()

    cleanededges = Part.__sortEdges__(PathUtils.cleanedges(edges, 0.01))

    # for e in cleanededges:
    # print str(e.valueAt(e.FirstParameter)) + "," +
    # str(e.valueAt(e.LastParameter))
    edgelist = []

    if len(cleanededges) == 1:  # user selected a single edge.
        edgelist = cleanededges
    else:
        # edgelist = [] #Multiple edges.  Need to sequence the vetexes.
        # First get the first segment oriented correctly.

        # We first compare the last parameter of the first segment to see if it
        # matches either end of the second segment. If not, it must need
        # flipping.
        if cleanededges[0].valueAt(cleanededges[0].LastParameter) in [cleanededges[1].valueAt(cleanededges[1].FirstParameter), cleanededges[1].valueAt(cleanededges[1].LastParameter)]:
            edge0 = cleanededges[0]
        else:
            edge0 = PathUtils.reverseEdge(cleanededges[0])

        edgelist.append(edge0)

        # Now iterate the rest of the edges matching the last parameter of the
        # previous segment.
        for edge in cleanededges[1:]:

            if edge.valueAt(edge.FirstParameter) == edgelist[-1].valueAt(edgelist[-1].LastParameter):
                nextedge = edge
            else:
                nextedge = PathUtils.reverseEdge(edge)
            edgelist.append(nextedge)
    # print "makeareacurve 87: " + "area.Point(" +
    # str(edgelist[0].Vertexes[0].X) + ", " +
    # str(edgelist[0].Vertexes[0].Y)+")"
    curveobj.append(area.Point(edgelist[0].Vertexes[
                    0].X, edgelist[0].Vertexes[0].Y))
#     seglist =[]
#     if direction=='CW':
#         edgelist.reverse()
#         for e in edgelist:
#             seglist.append(PathUtils.reverseEdge(e)) #swap end points on every segment
#     else:
#         for e in edgelist:
#             seglist.append(e)

    for s in edgelist:
        curveobj.append(makeAreaVertex(s))

    if startpt:
        # future nearest point code yet to be worked out -fixme
        #         v1 = Vector(startpt.X,startpt.Y,startpt.Z)
        #         perppoint1 = DraftGeomUtils.findPerpendicular(v1,firstedge)
        #         perppoint1 = DraftGeomUtils.findDistance(v1,firstedge)
        #         if  perppoint1:
        #             curveobj.ChangeStart(area.Point(perppoint1[0].x,perppoint1[0].y))
        #         else:
        #             curveobj.ChangeStart(area.Point(startpt.X,startpt.Y))
        curveobj.ChangeStart(area.Point(startpt.x, startpt.y))
    if endpt:
        # future nearest point code yet to be worked out -fixme
        #         v2 = Vector(endpt.X,endpt.Y,endpt.Z)
        #         perppoint2 = DraftGeomUtils.findPerpendicular(v2,lastedge)
        #         if perppoint2:
        #             curveobj.ChangeEnd(area.Point(perppoint2[0].x,perppoint2[0].y))
        #         else:
        #             curveobj.ChangeEnd(area.Point(endpt.X,endpt.Y))
        curveobj.ChangeEnd(area.Point(endpt.x, endpt.y))

    if curveobj.IsClockwise() and direction == 'CCW':
        curveobj.Reverse()
    elif not curveobj.IsClockwise() and direction == 'CW':
        curveobj.Reverse()
    return curveobj
Example #50
0
 def getWire(self):
     return (Part.Wire(Part.__sortEdges__(self.getEdges())))
Example #51
0
def getIndices(shape, offset):
    "returns a list with 2 lists: vertices and face indexes, offsetted with the given amount"
    vlist = []
    elist = []
    flist = []
    curves = None
    for e in shape.Edges:
        try:
            if not isinstance(e.Curve, Part.Line):
                if not curves:
                    curves = shape.tessellate(1)
                    FreeCAD.Console.PrintWarning(
                        translate(
                            "Arch",
                            "Found a shape containing curves, triangulating\n")
                    )
                    break
        except:  # unimplemented curve type
            curves = shape.tessellate(1)
            FreeCAD.Console.PrintWarning(
                translate("Arch",
                          "Found a shape containing curves, triangulating\n"))
            break
    if curves:
        for v in curves[0]:
            vlist.append(" " + str(round(v.x, p)) + " " + str(round(v.y, p)) +
                         " " + str(round(v.z, p)))
        for f in curves[1]:
            fi = ""
            for vi in f:
                fi += " " + str(vi + offset)
            flist.append(fi)
    else:
        for v in shape.Vertexes:
            vlist.append(" " + str(round(v.X, p)) + " " + str(round(v.Y, p)) +
                         " " + str(round(v.Z, p)))
        if not shape.Faces:
            for e in shape.Edges:
                if DraftGeomUtils.geomType(e) == "Line":
                    ei = " " + str(
                        findVert(e.Vertexes[0], shape.Vertexes) + offset)
                    ei += " " + str(
                        findVert(e.Vertexes[-1], shape.Vertexes) + offset)
                    elist.append(ei)
        for f in shape.Faces:
            if len(f.Wires) > 1:
                # if we have holes, we triangulate
                tris = f.tessellate(1)
                for fdata in tris[1]:
                    fi = ""
                    for vi in fdata:
                        vdata = Part.Vertex(tris[0][vi])
                        fi += " " + str(
                            findVert(vdata, shape.Vertexes) + offset)
                    flist.append(fi)
            else:
                fi = ""
                # OCC vertices are unsorted. We need to sort in the right order...
                edges = Part.__sortEdges__(f.OuterWire.Edges)
                #print edges
                for e in edges:
                    #print e.Vertexes[0].Point,e.Vertexes[1].Point
                    v = e.Vertexes[0]
                    ind = findVert(v, shape.Vertexes)
                    if ind == None:
                        return None, None, None
                    fi += " " + str(ind + offset)
                flist.append(fi)
    return vlist, elist, flist
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)
        # obj.ToolController = PathUtils.getToolControllers(obj)
        # toolLoad = PathUtils.getToolLoad(obj, obj.ToolController)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        output += "(" + obj.Label + ")"
        if obj.Side != "On":
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        if obj.Base:
            # hfaces = []
            # vfaces = []
            wires = []

            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                wires.extend(findWires(edgelist))

            for wire in wires:
                edgelist = wire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #53
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         if not isinstance(data[0],list):
             # multifuses not considered here
             return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     if obj.Normal == Vector(0,0,0):
         normal = Vector(0,0,1)
     else:
         normal = Vector(obj.Normal)
     base = None
     placement = None
     basewires = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Face > 0:
                     if len(obj.Base.Shape.Faces) >= obj.Face:
                         face = obj.Base.Shape.Faces[obj.Face-1]
                         # this wall is based on a specific face of its base object
                         normal = face.normalAt(0,0)
                         if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                             normal.multiply(width)
                             base = face.extrude(normal)
                             if obj.Align == "Center":
                                 base.translate(normal.negative().multiply(0.5))
                             elif obj.Align == "Right":
                                 base.translate(normal.negative())
                         else:
                             normal.multiply(height)
                             base = face.extrude(normal)
                         base,placement = self.rebase(base)
                         return (base,normal,placement)
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                 elif obj.Base.Shape.Wires:
                     basewires = obj.Base.Shape.Wires
                 elif len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 if basewires and width:
                     baseface = None
                     for wire in basewires:
                         e = wire.Edges[0]
                         if isinstance(e.Curve,Part.Circle):
                             dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                         else:
                             dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                         if not DraftVecUtils.isNull(dvec):
                             dvec.normalize()
                         sh = None
                         if obj.Align == "Left":
                             dvec.multiply(width)
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Right":
                             dvec.multiply(width)
                             dvec = dvec.negative()
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Center":
                             dvec.multiply(width/2)
                             w1 = DraftGeomUtils.offsetWire(wire,dvec)
                             dvec = dvec.negative()
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             sh = DraftGeomUtils.bind(w1,w2)
                         if sh:
                             sh.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(sh)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                     if baseface:
                         base,placement = self.rebase(baseface)
     else:
         l2 = length/2 or 0.5
         w2 = width/2 or 0.5
         v1 = Vector(-l2,-w2,0)
         v2 = Vector(l2,-w2,0)
         v3 = Vector(l2,w2,0)
         v4 = Vector(-l2,w2,0)
         base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         placement = FreeCAD.Placement()
     if base and placement:
         extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Example #54
0
    def execute(self, obj):

        if self.clone(obj):
            return

        pl = obj.Placement
        #self.baseface = None
        self.flip = False
        if hasattr(obj, "Flip"):
            if obj.Flip:
                self.flip = True
        base = None
        baseWire = None
        if obj.Base:
            if hasattr(obj.Base, "Shape"):
                if obj.Base.Shape.Solids:
                    base = obj.Base.Shape
                    #pl = obj.Base.Placement
                else:
                    if (obj.Base.Shape.Faces and obj.Face):
                        baseWire = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
                    elif obj.Base.Shape.Wires:
                        baseWire = obj.Base.Shape.Wires[0]
        if baseWire:
            if baseWire.isClosed():
                self.profilsDico = []
                self.shps = []
                self.subVolShps = []
                heights = []
                edges = Part.__sortEdges__(baseWire.Edges)
                if self.flip:
                    edges = self.flipEdges(edges)

                ln = len(edges)

                obj.Angles = adjust_list_len(obj.Angles, ln, obj.Angles[0])
                obj.Runs = adjust_list_len(obj.Runs, ln, obj.Runs[0])
                obj.IdRel = adjust_list_len(obj.IdRel, ln, obj.IdRel[0])
                obj.Thickness = adjust_list_len(obj.Thickness, ln,
                                                obj.Thickness[0])
                obj.Overhang = adjust_list_len(obj.Overhang, ln,
                                               obj.Overhang[0])

                for i in range(ln):
                    self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i],
                                            obj.IdRel[i], obj.Overhang[i],
                                            obj.Thickness[i])
                for i in range(ln):
                    self.calcEdgeGeometry(i, edges[i])
                for i in range(ln):
                    self.calcApex(
                        i, ln)  # after calcEdgeGeometry as it uses vec data
                for i in range(ln):
                    self.calcMissingData(
                        i, ln
                    )  # after calcApex so it can use recalculated heights
                for i in range(ln):
                    self.calcDraftEdges(i)
                for i in range(ln):
                    self.calcEave(i)
                for profil in self.profilsDico:
                    heights.append(profil["height"])
                obj.Heights = heights
                for i in range(ln):
                    self.getRoofPaneProject(i)
                    profilCurr = self.profilsDico[i]
                    ptsPaneProject = profilCurr["points"]
                    if len(ptsPaneProject) == 0:
                        continue
                    face = face_from_points(ptsPaneProject)
                    if face:
                        diag = face.BoundBox.DiagonalLength
                        midpoint = DraftGeomUtils.findMidpoint(
                            profilCurr["edge"])
                        thicknessV = profilCurr["thickness"] / (math.cos(
                            math.radians(profilCurr["angle"])))
                        overhangV = profilCurr["overhang"] * math.tan(
                            math.radians(profilCurr["angle"]))
                        sol = face.extrude(
                            Vector(0.0, 0.0, profilCurr["height"] + 1000000.0))
                        sol.translate(Vector(0.0, 0.0, -2.0 * overhangV))

                        ## baseVolume shape
                        ptsPaneProfil = [
                            Vector(-profilCurr["overhang"], -overhangV, 0.0),
                            Vector(profilCurr["run"], profilCurr["height"],
                                   0.0),
                            Vector(profilCurr["run"],
                                   profilCurr["height"] + thicknessV, 0.0),
                            Vector(-profilCurr["overhang"],
                                   -overhangV + thicknessV, 0.0)
                        ]
                        self.shps.append(
                            self.createProfilShape(ptsPaneProfil, midpoint,
                                                   profilCurr["rot"],
                                                   profilCurr["vec"],
                                                   profilCurr["run"], diag,
                                                   sol))

                        ## subVolume shape
                        ptsSubVolProfil = [
                            Vector(-profilCurr["overhang"], -overhangV, 0.0),
                            Vector(profilCurr["run"], profilCurr["height"],
                                   0.0),
                            Vector(profilCurr["run"],
                                   profilCurr["height"] + 900000.0, 0.0),
                            Vector(-profilCurr["overhang"],
                                   profilCurr["height"] + 900000.0, 0.0)
                        ]
                        self.subVolShps.append(
                            self.createProfilShape(ptsSubVolProfil, midpoint,
                                                   profilCurr["rot"],
                                                   profilCurr["vec"],
                                                   profilCurr["run"], diag,
                                                   sol))

                if len(
                        self.shps
                ) == 0:  # occurs if all segments have angle=90 or run=0.
                    # create a flat roof using the eavePtLst outline:
                    ptsPaneProject = []
                    for i in range(ln):
                        ptsPaneProject.append(
                            self.profilsDico[i]["eavePtLst"][0])
                    face = face_from_points(ptsPaneProject)
                    if face:
                        thk = max(
                            1.0, self.profilsDico[0]["thickness"]
                        )  # FreeCAD will crash when extruding with a null vector here
                        self.shps = [face.extrude(Vector(0.0, 0.0, thk))]
                        self.subVolShps = [
                            face.extrude(Vector(0.0, 0.0, 1000000.0))
                        ]

                ## baseVolume
                base = self.shps.pop()
                for s in self.shps:
                    base = base.fuse(s)
                base = self.processSubShapes(obj, base, pl)
                self.applyShape(obj, base, pl, allownosolid=True)

                ## subVolume
                self.sub = self.subVolShps.pop()
                for s in self.subVolShps:
                    self.sub = self.sub.fuse(s)
                self.sub = self.sub.removeSplitter()
                if not self.sub.isNull():
                    if not DraftGeomUtils.isNull(pl):
                        self.sub.Placement = pl

        elif base:
            base = self.processSubShapes(obj, base, pl)
            self.applyShape(obj, base, pl, allownosolid=True)
        else:
            FreeCAD.Console.PrintMessage(
                translate("Arch", "Unable to create a roof"))
Example #55
0
def offsetOpenWire(wx, dist, sym, normal):
    """Offsets an open wire returning a face"""
    resultFace = None
    try:
        if sym:
            logging.debug('open wire sym...')
            if isWireSingleArcOrCircle(wx):
                logging.debug('...Wire is a single arc')
                ex = wx.Edges[0]
                #construct outside offset of arc as an edge, and list of edges
                c1 = Part.Circle()
                c1.Center = ex.centerOfCurvatureAt(ex.FirstParameter)
                c1.Axis = ex.Curve.Axis
                c1.Radius = ex.Curve.Radius + dist.Value / 2
                ax1 = Part.Arc(c1, ex.FirstParameter, ex.LastParameter)
                baseEdge = ax1.toShape()
                base = Part.Wire([baseEdge])
                #construct inside offset of arc
                c2 = Part.Circle()
                c2.Center = ex.centerOfCurvatureAt(ex.FirstParameter)
                c2.Axis = ex.Curve.Axis
                c2.Radius = ex.Curve.Radius - dist.Value / 2
                ax2 = Part.Arc(c2, ex.FirstParameter, ex.LastParameter)
                offEdge = ax2.toShape()
                offset = Part.Wire([offEdge])
                #get the connector points
                p1 = baseEdge.firstVertex().Point
                p2 = baseEdge.lastVertex().Point
                p3 = offEdge.lastVertex().Point
                p4 = offEdge.firstVertex().Point
            else:
                base = wx.makeOffset2D(-dist / 2,
                                       fill=False,
                                       openResult=True,
                                       intersection=True,
                                       join=2)
                offset = wx.makeOffset2D(dist / 2,
                                         fill=False,
                                         openResult=True,
                                         intersection=True,
                                         join=2)
            logging.debug('getting sorting baseEdges...')
            baseEdges = Part.__sortEdges__(base.Edges)
            logging.debug('getting sorting offset edges...')
            offEdges = Part.__sortEdges__(offset.Edges)
            p1 = baseEdges[0].Vertexes[0].Point
            p2 = baseEdges[len(baseEdges) - 1].Vertexes[1].Point
            p3 = offEdges[len(offEdges) - 1].Vertexes[1].Point
            p4 = offEdges[0].Vertexes[0].Point
        else:
            logging.debug('...open wire non-sym')
            if isWireSingleArcOrCircle(wx):
                logging.debug('...Wire is a single arc')
                ex = wx.Edges[0]
                base = wx
                c2 = Part.Circle()
                c2.Center = ex.centerOfCurvatureAt(0.0)
                c2.Axis = ex.Curve.Axis
                c2.Radius = ex.Curve.Radius + dist.Value
                ax = Part.Arc(c2, ex.FirstParameter, ex.LastParameter)
                offEdge = ax.toShape()
                offset = Part.Wire([offEdge])
                p1 = ex.firstVertex().Point
                p2 = ex.lastVertex().Point
                p3 = offEdge.lastVertex().Point
                p4 = offEdge.firstVertex().Point

            else:
                resultFace = wx.makeOffset2D(dist,
                                             fill=True,
                                             openResult=True,
                                             intersection=True,
                                             join=2)


#in the case of a straight line wire, makeOffset2D will fail. In that case construct the shape
    except:
        traceback.print_exc()
        logging.debug('-->exception caught')
        wireEdges = Part.__sortEdges__(wx.Edges)
        p1 = wireEdges[0].Vertexes[0].Point
        p2 = wireEdges[len(wireEdges) - 1].Vertexes[1].Point
        vWire = p2 - p1
        vWire.normalize()
        offdir = normal.cross(vWire)
        offdir.multiply(dist)
        if sym:
            p1 = p1 - offdir * 0.5
            p2 = p2 - offdir * 0.5
        p4 = p1 + offdir
        p3 = p2 + offdir
        base = Part.makeLine(p1, p2)
        offset = Part.makeLine(p3, p4)
    if resultFace is None:
        logging.debug('building face...')
        end1 = Part.makeLine(p2, p3)
        end2 = Part.makeLine(p4, p1)
        bndyEdges = base.Edges + [end1] + offset.Edges + [end2]
        bndyEdges = Part.__sortEdges__(bndyEdges)
        faceWire = Part.Wire(bndyEdges)
        resultFace = Part.Face(faceWire)
    return resultFace
Example #56
0
def makeRoof(baseobj=None,facenr=0, angles=[45.,], run = [], idrel = [0,],thickness = [50.,], overhang=[100.,], name="Roof"):
    '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on
    a closed wire or an object. You can provide a list of angles, run,
    idrel, thickness, overhang for each edges in the wire to define the
    roof shape. The default for angle is 45 and the list is
    automatically complete to match with number of edges in the wire.
    If the base object is a solid the roof take the shape.'''
    import Part
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
    obj.Label = translate("Arch",name)
    w = None
    _Roof(obj)
    if FreeCAD.GuiUp:
        _ViewProviderRoof(obj.ViewObject)
    if baseobj:
        obj.Base = baseobj
        if obj.Base.isDerivedFrom("Part::Feature"):
            if obj.Base.Shape.Solids:
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
            else:
                if (obj.Base.Shape.Faces and obj.Face):
                    w = obj.Base.Shape.Faces[obj.Face-1].Wires[0]
                    if FreeCAD.GuiUp:
                        obj.Base.ViewObject.hide()
                elif obj.Base.Shape.Wires:
                    w = obj.Base.Shape.Wires[0]
                    if FreeCAD.GuiUp:
                        obj.Base.ViewObject.hide()
        if w:
            if w.isClosed():
                if FreeCAD.GuiUp:
                    obj.Base.ViewObject.hide()
                edges = Part.__sortEdges__(w.Edges)
                l = len(edges)

                la = len(angles)
                alist = angles
                for i in range(l-la):
                    alist.append(angles[0])
                obj.Angles=alist

                lr = len(run)
                rlist = run
                for i in range(l-lr):
                    #rlist.append(w.Edges[i].Length/2.)
                    rlist.append(250.)
                obj.Runs = rlist

                lidrel = len(idrel)
                rellist = idrel
                for i in range(l-lidrel):
                    rellist.append(0)
                obj.IdRel = rellist

                lthick = len(thickness)
                tlist = thickness
                for i in range(l-lthick):
                    tlist.append(thickness[0])
                obj.Thickness = tlist

                lover = len(overhang)
                olist = overhang
                for i in range(l-lover):
                    olist.append(overhang[0])
                obj.Overhang = olist
    obj.Face = facenr
    return obj
Example #57
0
centre = FreeCAD.Vector(0, 0, 0)

pos = obj.Placement.Base

newplace = FreeCAD.Placement(pos, rot, centre)

obj.Placement = newplace

App.getDocument('TOBERA').recompute()

#####################  CARAS ENTRADA y SALIDA ############

Part.Face(
    Part.Wire(Part.__sortEdges__([
        App.ActiveDocument.TOBERA.Shape.Edge1,
    ])))

App.ActiveDocument.addObject('Part::Feature', 'SALIDA').Shape = _

######################    MALLADO  #####################

__doc__ = FreeCAD.getDocument("TOBERA")

__mesh__ = __doc__.addObject("Mesh::Feature", "tobera_mesh")

__mesh__.Mesh = MeshPart.meshFromShape(Shape=__doc__.getObject("TOBERA").Shape,
                                       MaxLength=m_tobera)

__mesh__.Label = "tobera_mesh"
Example #58
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""
        toolLoad = PathUtils.getLastToolLoad(obj)
        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " (" + obj.ToolDescription + ")"
        else:
            obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"


        if obj.Base:
            hfaces = []
            vfaces = []
            wires = []

            for b in obj.Base:
                for sub in b[1]:
                    # we only consider the outer wire if this is a Face
                    # Horizontal and vertical faces are handled differently
                    shape = getattr(b[0].Shape, sub)
                    if numpy.isclose(shape.normalAt(0, 0).z, 1):  # horizontal face
                        hfaces.append(shape)

                    elif numpy.isclose(shape.normalAt(0, 0).z, 0):  # vertical face
                        vfaces.append(shape)
                    else:
                        FreeCAD.Console.PrintError(translate("Path", "Face doesn't appear to be parallel or perpendicular to the XY plane. No path will be generated for: \n"))
                        FreeCAD.Console.PrintError(b[0].Name + "." + sub + "\n")
            for h in hfaces:
                wires.append(h.OuterWire)

            tempshell = Part.makeShell(vfaces)
            slices = tempshell.slice(FreeCAD.Base.Vector(0, 0, 1), tempshell.CenterOfMass.z )

            wires = wires + slices

            for wire in wires:
                if obj.Algorithm == "OCC Native":
                    output += self._buildPathOCC(obj, wire)
                else:
                    try:
                        import area
                    except:
                        FreeCAD.Console.PrintError(translate("Path", "libarea needs to be installed for this command to work.\n"))
                        return
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #59
0
def Myarray2NurbsD3(arr,label="MyWall",degree=3):

	pstb=np.array(arr).swapaxes(0,1)
	pst2=np.concatenate([pstb[7:-1],pstb[1:7]])
	psta=pst2.swapaxes(1,0)

	# ptsa=np.array(arr)

	try: NbVPoles,NbUPoles,_t1 =psta.shape
	except: return (Part.Shape(),Part.Shape())

#	bs=Part.BSplineSurface()
#	bs.interpolate(psta)

	pst=psta

	FreeCAD.shoe_pst=pst
#	bs.setVPeriodic()

	pst[:,:,1] *= -1
	psta=pst

	# die flaeche
	bs=createBS(pst)

#	try: fa=App.ActiveDocument.curveA
#	except: fa=App.ActiveDocument.addObject('Part::Spline','curveA')
#
#	fa.Shape=bs.toShape()



	color=(random.random(),random.random(),random.random())

#- kann qwg
#	for i,pps in enumerate(psta):
#		if i == 0 : continue
#		bc=Part.BSplineCurve()
#		bc.interpolate(pps)
#		App.ActiveDocument.Ribs.OutList[i].Shape=bc.toShape()
#		App.ActiveDocument.Ribs.OutList[i].ViewObject.LineColor=color
#
#	for i,pps in enumerate(psta.swapaxes(0,1)):
#		bc=Part.BSplineCurve()
#		bc.interpolate(pps[2:])
#		App.ActiveDocument.Meridians.OutList[i].Shape=bc.toShape()
#		App.ActiveDocument.Meridians.OutList[i].ViewObject.LineColor=color

	if 1:
		sf2=bs.copy()
		sf2.setVPeriodic()
		uks=sf2.getUKnots()
		sf2.segment(uks[1],1,0,1)
		sh2=sf2.toShape()

	uks=bs.getUKnots()
	bs.segment(uks[1],1,0,1)
	sh=bs.toShape()

	vcp=False
	try:
		sp=App.ActiveDocument.Poles
		vcp=sp.ViewObject.ControlPoints
	except: sp=App.ActiveDocument.addObject("Part::Spline","Poles")
	sp.Shape=sh2
	sp.ViewObject.ControlPoints=vcp
	#sp.ViewObject.hide()

	try:
		fa=bs.uIso(0)
		sha1 = Part.Wire(fa.toShape())
		sha = Part.Face(sha1)

		fb=bs.uIso(1)
		shb1 = Part.Wire(fb.toShape())
		shb = Part.Face(shb1)

		sol=Part.Solid(Part.Shell([sha.Face1,shb.Face1,sh.Face1]))
	except:
		try:
			sha=Part.makeFilledFace(Part.__sortEdges__([App.ActiveDocument.Poles.Shape.Edge3, ]))
			shb=Part.makeFilledFace(Part.__sortEdges__([App.ActiveDocument.Poles.Shape.Edge1, ]))
			sol=Part.Solid(Part.Shell([sha.Face1,shb.Face1,sh.Face1]))
		except:
			sol=sh

	return (sol,bs)