Пример #1
0
 def snapToPolar(self,point,last):
     "snaps to polar lines from the given point"
     if self.isEnabled('ortho'): 
         if last:
             vecs = []
             if hasattr(FreeCAD,"DraftWorkingPlane"):
                 ax = [FreeCAD.DraftWorkingPlane.u,
                        FreeCAD.DraftWorkingPlane.v,
                        FreeCAD.DraftWorkingPlane.axis]
             else:
                 ax = [FreeCAD.Vector(1,0,0),
                       FreeCAD.Vector(0,1,0),
                       FreeCAD.Vector(0,0,1)]
             for a in self.polarAngles:
                     if a == 90:
                         vecs.extend([ax[0],fcvec.neg(ax[0])])
                         vecs.extend([ax[1],fcvec.neg(ax[1])])
                     else:
                         v = fcvec.rotate(ax[0],math.radians(a),ax[2])
                         vecs.extend([v,fcvec.neg(v)])
                         v = fcvec.rotate(ax[1],math.radians(a),ax[2])
                         vecs.extend([v,fcvec.neg(v)])
             for v in vecs:
                 de = Part.Line(last,last.add(v)).toShape()  
                 np = self.getPerpendicular(de,point)
                 if (np.sub(point)).Length < self.radius:
                     if self.tracker:
                         self.tracker.setCoords(np)
                         self.tracker.setMarker(self.mk['parallel'])
                         self.tracker.on()
                         self.setCursor('ortho')
                     return np,de
     return point,None
Пример #2
0
 def getbase(wire):
     "returns a full shape from a base wire"
     dvec = fcgeo.vec(wire.Edges[0]).cross(normal)
     dvec.normalize()
     if obj.Align == "Left":
         dvec = dvec.multiply(obj.Width)
         w2 = fcgeo.offsetWire(wire, dvec)
         sh = fcgeo.bind(wire, w2)
     elif obj.Align == "Right":
         dvec = dvec.multiply(obj.Width)
         dvec = fcvec.neg(dvec)
         w2 = fcgeo.offsetWire(wire, dvec)
         sh = fcgeo.bind(wire, w2)
     elif obj.Align == "Center":
         dvec = dvec.multiply(obj.Width / 2)
         w1 = fcgeo.offsetWire(wire, dvec)
         dvec = fcvec.neg(dvec)
         w2 = fcgeo.offsetWire(wire, dvec)
         sh = fcgeo.bind(w1, w2)
     # fixing self-intersections
     sh.fix(0.1, 0, 1)
     if height and (not flat):
         norm = Vector(normal).multiply(height)
         sh = sh.extrude(norm)
     return sh
Пример #3
0
 def getbase(wire):
     "returns a full shape from a base wire"
     dvec = fcgeo.vec(wire.Edges[0]).cross(normal)
     dvec.normalize()
     if obj.Align == "Left":
         dvec = dvec.multiply(width)
         w2 = fcgeo.offsetWire(wire,dvec)
         w1 = Part.Wire(fcgeo.sortEdges(wire.Edges))
         sh = fcgeo.bind(w1,w2)
     elif obj.Align == "Right":
         dvec = dvec.multiply(width)
         dvec = fcvec.neg(dvec)
         w2 = fcgeo.offsetWire(wire,dvec)
         w1 = Part.Wire(fcgeo.sortEdges(wire.Edges))
         sh = fcgeo.bind(w1,w2)
     elif obj.Align == "Center":
         dvec = dvec.multiply(width/2)
         w1 = fcgeo.offsetWire(wire,dvec)
         dvec = fcvec.neg(dvec)
         w2 = fcgeo.offsetWire(wire,dvec)
         sh = fcgeo.bind(w1,w2)
     # fixing self-intersections
     sh.fix(0.1,0,1)
     if height and (not flat):
         norm = Vector(normal).multiply(height)
         sh = sh.extrude(norm)
     return sh
Пример #4
0
def removeShape(objs,mark=True):
    '''takes an arch object (wall or structure) built on a cubic shape, and removes
    the inner shape, keeping its length, width and height as parameters.'''
    from draftlibs import fcgeo
    if not isinstance(objs,list):
        objs = [objs]
    for obj in objs:
        if fcgeo.isCubic(obj.Shape):
            dims = fcgeo.getCubicDimensions(obj.Shape)
            if dims:
                name = obj.Name
                tp = Draft.getType(obj)
                print tp
                if tp == "Structure":
                    FreeCAD.ActiveDocument.removeObject(name)
                    import ArchStructure
                    str = ArchStructure.makeStructure(length=dims[1],width=dims[2],height=dims[3],name=name)
                    str.Placement = dims[0]
                elif tp == "Wall":
                    FreeCAD.ActiveDocument.removeObject(name)
                    import ArchWall
                    length = dims[1]
                    width = dims[2]
                    v1 = Vector(length/2,0,0)
                    v2 = fcvec.neg(v1)
                    v1 = dims[0].multVec(v1)
                    v2 = dims[0].multVec(v2)
                    line = Draft.makeLine(v1,v2)
                    wal = ArchWall.makeWall(line,width=width,height=dims[3],name=name)
        else:
            if mark:
                obj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0)
Пример #5
0
 def getClosestAxis(self, point):
     "returns which of the workingplane axes is closest from the given vector"
     ax = point.getAngle(self.u)
     ay = point.getAngle(self.v)
     az = point.getAngle(self.axis)
     bx = point.getAngle(fcvec.neg(self.u))
     by = point.getAngle(fcvec.neg(self.v))
     bz = point.getAngle(fcvec.neg(self.axis))
     b = min(ax, ay, az, bx, by, bz)
     if b in [ax, bx]:
         return "x"
     elif b in [ay, by]:
         return "y"
     elif b in [az, bz]:
         return "z"
     else:
         return None
Пример #6
0
 def getClosestAxis(self,point):
         "returns which of the workingplane axes is closest from the given vector"
         ax = point.getAngle(self.u)
         ay = point.getAngle(self.v)
         az = point.getAngle(self.axis)
         bx = point.getAngle(fcvec.neg(self.u))
         by = point.getAngle(fcvec.neg(self.v))
         bz = point.getAngle(fcvec.neg(self.axis))
         b = min(ax,ay,az,bx,by,bz)
         if b in [ax,bx]:
                 return "x"
         elif b in [ay,by]:
                 return "y"
         elif b in [az,bz]:
                 return "z"
         else:
                 return None
Пример #7
0
 def renderWireframeSVG(self, objs, direction):
     os = objs[:]
     if os:
         sh = os.pop().Shape
         for o in os:
             sh = sh.fuse(o.Shape)
     result = Drawing.projectToSVG(sh, fcvec.neg(direction))
     if result:
         result = result.replace('stroke-width="0.35"',
                                 'stroke-width="0.01 px"')
         return result
     return ''
Пример #8
0
 def calc(self):
     import Part
     if (self.p1 != None) and (self.p2 != None):
         points = [fcvec.tup(self.p1,True),fcvec.tup(self.p2,True),\
                       fcvec.tup(self.p1,True),fcvec.tup(self.p2,True)]
         if self.p3 != None:
             p1 = self.p1
             p4 = self.p2
             if fcvec.equals(p1,p4):
                 proj = None
             else:
                 base = Part.Line(p1,p4).toShape()
                 proj = fcgeo.findDistance(self.p3,base)
             if not proj:
                 p2 = p1
                 p3 = p4
             else:
                 p2 = p1.add(fcvec.neg(proj))
                 p3 = p4.add(fcvec.neg(proj))
             points = [fcvec.tup(p1),fcvec.tup(p2),fcvec.tup(p3),fcvec.tup(p4)]
         self.coords.point.setValues(0,4,points)
Пример #9
0
    def updateSVG(self, obj, join=False):
        "encapsulates a svg fragment into a transformation node"
        import Part
        from draftlibs import fcgeo

        if hasattr(obj, "Source"):
            if obj.Source:
                if obj.Source.Objects:
                    svg = ""

                    # generating SVG
                    linewidth = obj.LineWidth / obj.Scale
                    if obj.RenderingMode == "Solid":
                        # render using the Arch Vector Renderer
                        import ArchVRM

                        render = ArchVRM.Renderer()
                        render.setWorkingPlane(obj.Source.Placement)
                        render.addObjects(obj.Source.Objects)
                        render.cut(obj.Source.Shape)
                        svg += render.getViewSVG(linewidth=linewidth)
                        svg += render.getSectionSVG(linewidth=linewidth * 2)
                        # print render.info()

                    else:
                        # render using the Drawing module
                        shapes = []
                        for o in obj.Source.Objects:
                            if o.isDerivedFrom("Part::Feature"):
                                shapes.append(o.Shape)
                        if shapes:
                            base = shape.pop()
                        for sh in shapes:
                            base = base.fuse(sh)
                        svgf = Drawing.projectToSVG(base, fcvec.neg(direction))
                        if svgf:
                            svgf = svgf.replace('stroke-width="0.35"', 'stroke-width="' + str(linewidth) + 'px"')
                        svg += svgf

                    result = ""
                    result += '<g id="' + obj.Name + '"'
                    result += ' transform="'
                    result += "rotate(" + str(obj.Rotation) + "," + str(obj.X) + "," + str(obj.Y) + ") "
                    result += "translate(" + str(obj.X) + "," + str(obj.Y) + ") "
                    result += "scale(" + str(obj.Scale) + "," + str(-obj.Scale) + ")"
                    result += '">\n'
                    result += svg
                    result += "</g>\n"
                    # print "complete node:",result
                    return result
        return ""
Пример #10
0
 def update(self, point):
     "this function is called by the Snapper when the mouse is moved"
     b = self.points[0]
     n = FreeCAD.DraftWorkingPlane.axis
     bv = point.sub(b)
     dv = bv.cross(n)
     dv = fcvec.scaleTo(dv, self.Width / 2)
     if self.Align == "Center":
         self.tracker.update([b, point])
     elif self.Align == "Left":
         self.tracker.update([b.add(dv), point.add(dv)])
     else:
         dv = fcvec.neg(dv)
         self.tracker.update([b.add(dv), point.add(dv)])
Пример #11
0
 def update(self,point):
     "this function is called by the Snapper when the mouse is moved"
     b = self.points[0]
     n = FreeCAD.DraftWorkingPlane.axis
     bv = point.sub(b)
     dv = bv.cross(n)
     dv = fcvec.scaleTo(dv,self.Width/2)
     if self.Align == "Center":
         self.tracker.update([b,point])
     elif self.Align == "Left":
         self.tracker.update([b.add(dv),point.add(dv)])
     else:
         dv = fcvec.neg(dv)
         self.tracker.update([b.add(dv),point.add(dv)])
Пример #12
0
 def getSubVolume(self, base, width, delta=None):
     "returns a subvolume from a base object"
     import Part
     max_length = 0
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     f = Part.Face(f)
     n = f.normalAt(0, 0)
     v1 = fcvec.scaleTo(n, width)
     f.translate(v1)
     v2 = fcvec.neg(v1)
     v2 = fcvec.scale(v1, -2)
     f = f.extrude(v2)
     if delta:
         f.translate(delta)
     return f
Пример #13
0
 def getSubVolume(self,base,width,delta=None):
     "returns a subvolume from a base object"
     import Part
     max_length = 0
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     f = Part.Face(f)
     n = f.normalAt(0,0)
     v1 = fcvec.scaleTo(n,width)
     f.translate(v1)
     v2 = fcvec.neg(v1)
     v2 = fcvec.scale(v1,-2)
     f = f.extrude(v2)
     if delta:
         f.translate(delta)
     return f
Пример #14
0
 def renderOutlineSVG(self, objs, direction):
     plane = None
     plane = WorkingPlane.plane()
     if direction != Vector(0, 0, 0):
         plane.alignToPointAndAxis(Vector(0, 0, 0), fcvec.neg(direction), 0)
     else:
         direction = Vector(0, 0, -1)
     faces = []
     for obj in objs:
         for face in obj.Shape.Faces:
             normal = face.normalAt(0, 0)
             if normal.getAngle(direction) > math.pi / 2:
                 faces.append(face)
     print "faces:", faces
     if faces:
         base = faces.pop()
         for face in faces:
             base = base.oldFuse(face)
     result = self.getPath(base, plane)
     return result
Пример #15
0
def removeShape(objs, mark=True):
    '''takes an arch object (wall or structure) built on a cubic shape, and removes
    the inner shape, keeping its length, width and height as parameters.'''
    from draftlibs import fcgeo
    if not isinstance(objs, list):
        objs = [objs]
    for obj in objs:
        if fcgeo.isCubic(obj.Shape):
            dims = fcgeo.getCubicDimensions(obj.Shape)
            if dims:
                name = obj.Name
                tp = Draft.getType(obj)
                print tp
                if tp == "Structure":
                    FreeCAD.ActiveDocument.removeObject(name)
                    import ArchStructure
                    str = ArchStructure.makeStructure(length=dims[1],
                                                      width=dims[2],
                                                      height=dims[3],
                                                      name=name)
                    str.Placement = dims[0]
                elif tp == "Wall":
                    FreeCAD.ActiveDocument.removeObject(name)
                    import ArchWall
                    length = dims[1]
                    width = dims[2]
                    v1 = Vector(length / 2, 0, 0)
                    v2 = fcvec.neg(v1)
                    v1 = dims[0].multVec(v1)
                    v2 = dims[0].multVec(v2)
                    line = Draft.makeLine(v1, v2)
                    wal = ArchWall.makeWall(line,
                                            width=width,
                                            height=dims[3],
                                            name=name)
        else:
            if mark:
                obj.ViewObject.ShapeColor = (1.0, 0.0, 0.0, 1.0)
Пример #16
0
    def renderClassicSVG(self, objs, direction, base=None):
        """returns an svg fragment from a SectionPlane object,
        a direction vector and optionally a base point"""
        def intersection(p1, p2, p3, p4):
            "returns the intersection of line (p1,p2) with plane (p3,p4)"
            # http://paulbourke.net/geometry/planeline/
            dn = p4.dot(p2.sub(p1))
            if dn != 0:
                u = (p4.dot(p3.sub(p1))) / dn
                p = p1.add((p2.sub(p1)).scale(u, u, u))
                return p
            else:
                # line is parallel to normal
                vp = fcvec.project(p3.sub(p1), p2.sub(p1))
                l = vp.Length
                if vp.getAngle(p2.sub(p1)) > 1:
                    l = -l
                return fcvec.scaleTo(p2.sub(p1), l)

        def getFirstIndex(list1, list2):
            "returns the first index from list2 where there is an item of list1"
            for i1 in range(len(list1)):
                for i2 in range(len(list2)):
                    if list1[i1].hashCode() == list2[i2].hashCode():
                        return i2
            return None

        def getLastIndex(list1, list2):
            "returns the last index from list2 where there is an item of list1"
            i = None
            for i1 in range(len(list1)):
                for i2 in range(len(list2)):
                    if list1[i1].hashCode() == list2[i2].hashCode():
                        i = i2
            return i

        def findPrevious(base, dir, faces):
            "returns the highest index in faces that is crossed by the given line"
            for i in range(len(faces) - 1, -1, -1):
                print "p1:", base, " p2: ", base.add(dir)
                obb = faces[i].BoundBox
                print "bo: ", obb
                op = intersection(base, base.add(dir), faces[i].CenterOfMass,
                                  faces[i].normalAt(0, 0))
                print "int:", op
                if obb.isInside(op):
                    dv = op.sub(base)
                    if dv.getAngle(dir) < math.pi / 2:
                        return i
            return None

        def findNext(base, dir, faces):
            "returns the lowest index in faces that is crossed by the given line"
            for i in range(len(faces)):
                obb = faces[i].BoundBox
                op = intersection(base, base.add(dir), faces[i].CenterOfMass,
                                  faces[i].normalAt(0, 0))
                if obb.isInside(op):
                    dv = op.sub(base)
                    if dv.getAngle(dir) > math.pi / 2:
                        return i
            return None

        print "getting representation at ", direction, " =======================================>"

        # using Draft WorkingPlane
        plane = None
        plane = WorkingPlane.plane()
        if direction != Vector(0, 0, 0):
            plane.alignToPointAndAxis(Vector(0, 0, 0), fcvec.neg(direction), 0)
        else:
            direction = Vector(0, 0, -1)
        print "plane:", plane

        sortedFaces = []

        if not base:
            # getting the base point = first point from the bounding box
            bb = FreeCAD.BoundBox()
            for o in objs:
                bb.add(o.Shape.BoundBox)
            rad = bb.DiagonalLength / 2
            rv = bb.Center.add(direction)
            rv = fcvec.scaleTo(rv, rad)
            rv = fcvec.neg(rv)
            base = bb.Center.add(rv)

        print "base:", base

        # getting faces
        unsortedFaces = []
        notFoundFaces = []
        for o in objs:
            unsortedFaces.append(o.Name)
            unsortedFaces.extend(o.Shape.Faces[:])
        print "analyzing ", len(unsortedFaces), " faces"

        for face in unsortedFaces:

            if isinstance(face, str):
                print "OBJECT ", face, " =======================================>"
                continue

            print "testing face ", unsortedFaces.index(face)

            # testing if normal points outwards
            normal = face.normalAt(0, 0)
            if normal.getAngle(direction) <= math.pi / 2:
                print "normal pointing outwards"
                continue

            fprev = 0
            fnext = len(sortedFaces)
            notFound = True

            print "checking ", len(face.Vertexes), " verts"

            for v in face.Vertexes:
                vprev = findPrevious(v.Point, direction, sortedFaces)
                vnext = findNext(v.Point, direction, sortedFaces)
                print "temp indexes:", vprev, vnext
                if (vprev != None):
                    notfound = False
                    if (vprev > fprev):
                        fprev = vprev
                if (vnext != None):
                    notfound = False
                    if (vnext < fnext):
                        fnext = vnext

            print "fprev:", fprev
            print "fnext:", fnext
            print "notFound", notFound

            if fnext < fprev:
                raise "Error, impossible index"
            elif fnext == fprev:
                sortedFaces.insert(fnext, face)
            else:
                sortedFaces.insert(fnext, face)

            print len(sortedFaces), " sorted faces:", sortedFaces

        # building SVG representation in correct order
        svg = ''
        for f in sortedFaces:
            svg += self.getPath(f, plane)

        return svg