Example #1
0
 def createGeometry(self,obj):
     import Part
     from draftlibs import fcgeo
     pl = obj.Placement
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.WindowParts and (len(obj.WindowParts)%5 == 0):
                 shapes = []
                 for i in range(len(obj.WindowParts)/5):
                     wires = []
                     wstr = obj.WindowParts[(i*5)+2].split(',')
                     for s in wstr:
                         j = int(s[4:])
                         if obj.Base.Shape.Wires:
                             if len(obj.Base.Shape.Wires) >= j:
                                 wires.append(obj.Base.Shape.Wires[j])
                     if wires:
                         max_length = 0
                         for w in wires:
                             if w.BoundBox.DiagonalLength > max_length:
                                 max_length = w.BoundBox.DiagonalLength
                                 ext = w
                         wires.remove(ext)
                         shape = Part.Face(ext)
                         norm = shape.normalAt(0,0)
                         thk = float(obj.WindowParts[(i*5)+3])
                         if thk:
                             exv = fcvec.scaleTo(norm,thk)
                             shape = shape.extrude(exv)
                             for w in wires:
                                 f = Part.Face(w)
                                 f = f.extrude(exv)
                                 shape = shape.cut(f)
                         if obj.WindowParts[(i*5)+4]:
                             zof = float(obj.WindowParts[(i*5)+4])
                             if zof:
                                 zov = fcvec.scaleTo(norm,zof)
                                 shape.translate(zov)
                         print shape
                         shapes.append(shape)
                 obj.Shape = Part.makeCompound(shapes)
     if not fcgeo.isNull(pl):
         obj.Placement = pl
Example #2
0
 def createGeometry(self, obj):
     import Part
     from draftlibs import fcgeo
     pl = obj.Placement
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.WindowParts and (len(obj.WindowParts) % 5 == 0):
                 shapes = []
                 for i in range(len(obj.WindowParts) / 5):
                     wires = []
                     wstr = obj.WindowParts[(i * 5) + 2].split(',')
                     for s in wstr:
                         j = int(s[4:])
                         if len(obj.Base.Shape.Wires) >= j:
                             wires.append(obj.Base.Shape.Wires[j])
                     if wires:
                         max_length = 0
                         for w in wires:
                             if w.BoundBox.DiagonalLength > max_length:
                                 max_length = w.BoundBox.DiagonalLength
                                 ext = w
                         wires.remove(ext)
                         shape = Part.Face(ext)
                         norm = shape.normalAt(0, 0)
                         thk = float(obj.WindowParts[(i * 5) + 3])
                         if thk:
                             exv = fcvec.scaleTo(norm, thk)
                             shape = shape.extrude(exv)
                             for w in wires:
                                 f = Part.Face(w)
                                 f = f.extrude(exv)
                                 shape = shape.cut(f)
                         if obj.WindowParts[(i * 5) + 4]:
                             zof = float(obj.WindowParts[(i * 5) + 4])
                             if zof:
                                 zov = fcvec.scaleTo(norm, zof)
                                 shape.translate(zov)
                         shapes.append(shape)
                 obj.Shape = Part.makeCompound(shapes)
     if not fcgeo.isNull(pl):
         obj.Placement = pl
Example #3
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)])
Example #4
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)])
 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)
Example #6
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
Example #7
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
Example #8
0
 def snapToPerpendicular(self,shape,last):
     "returns a list of perpendicular snap locations"
     snaps = []
     if self.isEnabled("perpendicular"):
         if last:
             if isinstance(shape,Part.Edge):
                 if isinstance(shape.Curve,Part.Line):
                     np = self.getPerpendicular(shape,last)
                 elif isinstance(shape.Curve,Part.Circle):
                     dv = last.sub(shape.Curve.Center)
                     dv = fcvec.scaleTo(dv,shape.Curve.Radius)
                     np = (shape.Curve.Center).add(dv)
                 elif isinstance(shape.Curve,Part.BSplineCurve):
                     pr = shape.Curve.parameter(last)
                     np = shape.Curve.value(pr)
                 else:
                     return snaps
                 snaps.append([np,'perpendicular',np])
     return snaps
Example #9
0
 def update(self,line=None,normal=None):
     import WorkingPlane
     from draftlibs import fcgeo
     if not normal:
         normal = FreeCAD.DraftWorkingPlane.axis
     if line:
         if isinstance(line,list):
             bp = line[0]
             lvec = line[1].sub(line[0])
         else:
             lvec = fcgeo.vec(line.Shape.Edges[0])
             bp = line.Shape.Edges[0].Vertexes[0].Point
     elif self.baseline:
         lvec = fcgeo.vec(self.baseline.Shape.Edges[0])
         bp = self.baseline.Shape.Edges[0].Vertexes[0].Point
     else:
         return
     right = lvec.cross(normal)
     self.cube.width.setValue(lvec.Length)
     p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)])
     self.trans.rotation.setValue(p.Rotation.Q)
     bp = bp.add(fcvec.scale(lvec,0.5))
     bp = bp.add(fcvec.scaleTo(normal,self.cube.depth.getValue()/2))
     self.pos(bp)
    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
Example #11
0
    def cut(self,cutplane):
        "Cuts through the shapes with a given cut plane and builds section faces"
        if self.iscut:
            return
        if not self.shapes:
            if DEBUG: print "No objects to make sections"
        else:
            fill = (1.0,1.0,1.0,1.0)
            placement = FreeCAD.Placement(cutplane.Placement)

            # building boundbox
            bb = self.shapes[0][0].BoundBox 
            for sh in self.shapes[1:]:
                bb.add(sh[0].BoundBox)
            bb.enlarge(1)
            um = vm = wm = 0
            if not bb.isCutPlane(placement.Base,self.wp.axis):
                if DEBUG: print "No objects are cut by the plane"
            else:
                corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
                           FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
                           FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin),
                           FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin),
                           FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax),
                           FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax),
                           FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
                           FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
                for c in corners:
                    dv = c.sub(placement.Base)
                    um1 = fcvec.project(dv,self.wp.u).Length
                    um = max(um,um1)
                    vm1 = fcvec.project(dv,self.wp.v).Length
                    vm = max(vm,vm1)
                    wm1 = fcvec.project(dv,self.wp.axis).Length
                    wm = max(wm,wm1)
                p1 = FreeCAD.Vector(-um,vm,0)
                p2 = FreeCAD.Vector(um,vm,0)
                p3 = FreeCAD.Vector(um,-vm,0)
                p4 = FreeCAD.Vector(-um,-vm,0)
                cutface = Part.makePolygon([p1,p2,p3,p4,p1])
                cutface = Part.Face(cutface)
                cutface.Placement = placement
                cutnormal = fcvec.scaleTo(self.wp.axis,wm)
                cutvolume = cutface.extrude(cutnormal)
                shapes = []
                faces = []
                sections = []
                for sh in self.shapes:
                    for sol in sh[0].Solids:
                        c = sol.cut(cutvolume)
                        shapes.append([c]+sh[1:])
                        for f in c.Faces:
                            faces.append([f]+sh[1:])
                        sec = sol.section(cutface)
                        if sec.Edges:
                            wires = fcgeo.findWires(sec.Edges)
                            for w in wires:
                                sec = Part.Face(w)
                                sections.append([sec,fill])
                self.shapes = shapes
                self.faces = faces
                self.sections = sections
                if DEBUG: print "Built ",len(self.sections)," sections, ", len(self.faces), " faces retained"
                self.iscut = True
                self.oriented = False
                self.trimmed = False
                self.sorted = False
                self.joined = False