Ejemplo n.º 1
0
 def getBase(self,obj,wire,normal,width,height):
     "returns a full shape from a base wire"
     import DraftGeomUtils,Part
     flat = False
     if hasattr(obj.ViewObject,"DisplayMode"):
         flat = (obj.ViewObject.DisplayMode == "Flat 2D")
     dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
     if not DraftVecUtils.isNull(dvec):
         dvec.normalize()
     if obj.Align == "Left":
         dvec = dvec.multiply(width)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Right":
         dvec = dvec.multiply(width)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Center":
         dvec = dvec.multiply(width/2)
         w1 = DraftGeomUtils.offsetWire(wire,dvec)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         sh = DraftGeomUtils.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
Ejemplo n.º 2
0
 def getbase(wire):
     "returns a full shape from a base wire"
     dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
     dvec.normalize()
     if obj.Align == "Left":
         dvec = dvec.multiply(width)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Right":
         dvec = dvec.multiply(width)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Center":
         dvec = dvec.multiply(width/2)
         w1 = DraftGeomUtils.offsetWire(wire,dvec)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         sh = DraftGeomUtils.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
Ejemplo n.º 3
0
 def getGlobalCoords(self, point):
     "returns the global coordinates of the given point, taken relatively to this working plane"
     vx = DraftVecUtils.scale(self.u, point.x)
     vy = DraftVecUtils.scale(self.v, point.y)
     vz = DraftVecUtils.scale(self.axis, point.z)
     pt = (vx.add(vy)).add(vz)
     return pt.add(self.position)
Ejemplo n.º 4
0
 def align(self,basepoint,align,widthvec):
     "moves a given basepoint according to the alignment"
     if align == "Center":
         basepoint = basepoint.add(DraftVecUtils.scale(widthvec,-0.5))
     elif align == "Right":
         basepoint = basepoint.add(DraftVecUtils.scale(widthvec,-1))
     return basepoint
Ejemplo n.º 5
0
 def snapToPolar(self,point,last):
     "snaps to polar lines from the given point"
     if self.isEnabled('ortho') and (not self.mask): 
         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],ax[0].negative()])
                         vecs.extend([ax[1],ax[1].negative()])
                     else:
                         v = DraftVecUtils.rotate(ax[0],math.radians(a),ax[2])
                         vecs.extend([v,v.negative()])
                         v = DraftVecUtils.rotate(ax[1],math.radians(a),ax[2])
                         vecs.extend([v,v.negative()])
             for v in vecs:
                 de = Part.Line(last,last.add(v)).toShape()  
                 np = self.getPerpendicular(de,point)
                 if ((self.radius == 0) and (point.sub(last).getAngle(v) < 0.087)) \
                 or ((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
Ejemplo n.º 6
0
    def makeStraightStairsWithLanding(self,obj,edge):
        
        "builds a straight staircase with a landing in the middle"

        if obj.NumberOfSteps < 3:
            return
        import Part,DraftGeomUtils
        v = DraftGeomUtils.vec(edge)
        reslength = edge.Length - obj.Width.Value
        vLength = DraftVecUtils.scaleTo(v,float(reslength)/(obj.NumberOfSteps-2))
        vLength = Vector(vLength.x,vLength.y,0)
        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        p1 = edge.Vertexes[0].Point
        if round(v.z,Draft.precision()) != 0:
            h = v.z
        else:
            h = obj.Height.Value
        hstep = h/obj.NumberOfSteps
        landing = obj.NumberOfSteps/2
        p2 = p1.add(DraftVecUtils.scale(vLength,landing-1).add(Vector(0,0,landing*hstep)))
        p3 = p2.add(DraftVecUtils.scaleTo(vLength,obj.Width.Value))
        p4 = p3.add(DraftVecUtils.scale(vLength,obj.NumberOfSteps-(landing+1)).add(Vector(0,0,(obj.NumberOfSteps-landing)*hstep)))
        self.makeStraightStairs(obj,Part.Line(p1,p2).toShape(),landing)
        self.makeStraightLanding(obj,Part.Line(p2,p3).toShape())
        self.makeStraightStairs(obj,Part.Line(p3,p4).toShape(),obj.NumberOfSteps-landing)
Ejemplo n.º 7
0
    def getIncidentAngle(self, queue):
        global currLocation
        '''returns in the incident angle in radians between the current and previous moves'''
        # get the vector of the last move
        if queue[1].Name in arccommands:
            print queue
            print currLocation
            arcLoc = FreeCAD.Base.Vector(queue[2].X + queue[1].I, queue[2].Y + queue[1].J, currLocation['Z'])
            radvector = queue[1].Placement.Base.sub(arcLoc)  # vector of chord from center to point
            # vector of line perp to chord.
            v1 = radvector.cross(FreeCAD.Base.Vector(0, 0, 1))
        else:
            v1 = queue[1].Placement.Base.sub(queue[2].Placement.Base)

        # get the vector of the current move
        if queue[0].Name in arccommands:
            arcLoc = FreeCAD.Base.Vector((queue[1].x + queue[0].I), (queue[1].y + queue[0].J), currLocation['Z'])
            radvector = queue[1].Placement.Base.sub(arcLoc)  # calculate arcangle

            v2 = radvector.cross(FreeCAD.Base.Vector(0, 0, 1))

            # if switching between G2 and G3, reverse orientation
            if queue[1].Name in arccommands:
                if queue[0].Name != queue[1].Name:
                    v2 = D.rotate2D(v2, math.radians(180))
        else:
            v2 = queue[0].Placement.Base.sub(queue[1].Placement.Base)

        incident_angle = D.angle(v1, v2, FreeCAD.Base.Vector(0, 0, -1))
        return incident_angle
Ejemplo n.º 8
0
 def getGlobalRot(self, point):
     "Same as getGlobalCoords, but discards the WP position"
     vx = DraftVecUtils.scale(self.u, point.x)
     vy = DraftVecUtils.scale(self.v, point.y)
     vz = DraftVecUtils.scale(self.axis, point.z)
     pt = (vx.add(vy)).add(vz)
     return pt
Ejemplo n.º 9
0
    def onChanged(self,obj,prop):

        if prop == "Height":
            for child in obj.Group:
                if Draft.getType(child) in ["Wall","Structure"]:
                    if not child.Height.Value:
                        #print("Executing ",child.Label)
                        child.Proxy.execute(child)
        elif prop == "Placement":
            if hasattr(self,"oldPlacement"):
                if self.oldPlacement:
                    deltap = obj.Placement.Base.sub(self.oldPlacement.Base)
                    if deltap.Length == 0:
                        deltap = None
                    deltar = self.oldPlacement.Rotation.multiply(obj.Placement.Rotation)
                    #print "Rotation",deltar.Axis,deltar.Angle
                    if deltar.Angle < 0.0001:
                        deltar = None
                    for child in obj.Group:
                        if ((not hasattr(child,"MoveWithHost")) or child.MoveWithHost) and hasattr(child,"Placement"):
                            #print "moving ",child.Label
                            if deltap:
                                child.Placement.move(deltap)
                            if deltar:
                                #child.Placement.Rotation = child.Placement.Rotation.multiply(deltar) - not enough, child must also move
                                # use shape methods to obtain a correct placement
                                import Part,math
                                shape = Part.Shape()
                                shape.Placement = child.Placement
                                shape.rotate(DraftVecUtils.tup(obj.Placement.Base), DraftVecUtils.tup(deltar.Axis), math.degrees(deltar.Angle))
                                child.Placement = shape.Placement
 def update(self,point):
     "sets the opposite (diagonal) point of the rectangle"
     diagonal = point.sub(self.origin)
     inpoint1 = self.origin.add(DraftVecUtils.project(diagonal,self.v))
     inpoint2 = self.origin.add(DraftVecUtils.project(diagonal,self.u))
     self.coords.point.set1Value(1,inpoint1.x,inpoint1.y,inpoint1.z)
     self.coords.point.set1Value(2,point.x,point.y,point.z)
     self.coords.point.set1Value(3,inpoint2.x,inpoint2.y,inpoint2.z)
Ejemplo n.º 11
0
 def __repr__(self):
     return (
         "Workplane x="
         + str(DraftVecUtils.rounded(self.u))
         + " y="
         + str(DraftVecUtils.rounded(self.v))
         + " z="
         + str(DraftVecUtils.rounded(self.axis))
     )
Ejemplo n.º 12
0
    def getRebarData(self,obj):

        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].Shape:
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.InList[0]
        wire = obj.Base.Shape.Wires[0]
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,0,-1))
        size = (ArchCommands.projectToVector(father.Shape.copy(),axis)).Length
        if hasattr(obj,"Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
        if hasattr(obj,"Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        if hasattr(obj,"Rounding"):
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire,radius)
        wires = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis,size/2)
            wire.translate(offset)
            wires.append(wire)
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis,obj.OffsetStart.Value)
            else:
                baseoffset = None
            interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis,interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        wire.translate(baseoffset)
                    wires.append(wire)
                else:
                    wire = wire.copy()
                    wire.translate(vinterval)
                    wires.append(wire)
        return [wires,obj.Diameter.Value/2]
Ejemplo n.º 13
0
def convert(toolpath, Side, radius, clockwise=False, Z=0.0, firstedge=None, vf=1.0, hf=2.0):
    '''convert(toolpath,Side,radius,clockwise=False,Z=0.0,firstedge=None) Converts lines and arcs to G1,G2,G3 moves. Returns a string.'''
    last = None
    output = ""
    # create the path from the offset shape
    for edge in toolpath:
        if not last:
            # set the first point
            last = edge.Vertexes[0].Point
            # FreeCAD.Console.PrintMessage("last pt= " + str(last)+ "\n")
            output += "G1 X" + str(fmt(last.x)) + " Y" + str(fmt(last.y)) + \
                " Z" + str(fmt(Z)) + " F" + str(vf) + "\n"
        if isinstance(edge.Curve, Part.Circle):
            # FreeCAD.Console.PrintMessage("arc\n")
            arcstartpt = edge.valueAt(edge.FirstParameter)
            midpt = edge.valueAt(
                (edge.FirstParameter + edge.LastParameter) * 0.5)
            arcendpt = edge.valueAt(edge.LastParameter)
            # arcchkpt = edge.valueAt(edge.LastParameter * .99)

            if DraftVecUtils.equals(last, arcstartpt):
                startpt = arcstartpt
                endpt = arcendpt
            else:
                startpt = arcendpt
                endpt = arcstartpt
            center = edge.Curve.Center
            relcenter = center.sub(last)
            # FreeCAD.Console.PrintMessage("arc  startpt= " + str(startpt)+ "\n")
            # FreeCAD.Console.PrintMessage("arc  midpt= " + str(midpt)+ "\n")
            # FreeCAD.Console.PrintMessage("arc  endpt= " + str(endpt)+ "\n")
            arc_cw = check_clockwise(
                [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
            # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
            if arc_cw:
                output += "G2"
            else:
                output += "G3"
            output += " X" + str(fmt(endpt.x)) + " Y" + \
                str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
            output += " I" + str(fmt(relcenter.x)) + " J" + \
                str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
            output += "\n"
            last = endpt
            # FreeCAD.Console.PrintMessage("last pt arc= " + str(last)+ "\n")
        else:
            point = edge.Vertexes[-1].Point
            if DraftVecUtils.equals(point, last):  # edges can come flipped
                point = edge.Vertexes[0].Point
            output += "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
                " Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
            last = point
            # FreeCAD.Console.PrintMessage("line\n")
            # FreeCAD.Console.PrintMessage("last pt line= " + str(last)+ "\n")
    return output
Ejemplo n.º 14
0
    def edge_to_path(lastpt, edge, Z):
        if isinstance(edge.Curve, Part.Circle):
            # FreeCAD.Console.PrintMessage("arc\n")
            arcstartpt = edge.valueAt(edge.FirstParameter)
            midpt = edge.valueAt(
                (edge.FirstParameter + edge.LastParameter) * 0.5)
            arcendpt = edge.valueAt(edge.LastParameter)
            # arcchkpt = edge.valueAt(edge.LastParameter * .99)

            if DraftVecUtils.equals(lastpt, arcstartpt):
                startpt = arcstartpt
                endpt = arcendpt
            else:
                startpt = arcendpt
                endpt = arcstartpt
            center = edge.Curve.Center
            relcenter = center.sub(lastpt)

            # start point and end point fall together in the given output precision?
            if fmt(startpt.x) == fmt(endpt.x) and fmt(startpt.y) == fmt(endpt.y):
                if edge.Length < 0.5 * 2 * math.pi * edge.Curve.Radius:
                    # because it is a very small circle -> omit, as that gcode would produce a full circle
                    return endpt, ""
                else:
                    # it is an actual full circle, emit a line for this
                    pass

            # FreeCAD.Console.PrintMessage("arc  startpt= " + str(startpt)+ "\n")
            # FreeCAD.Console.PrintMessage("arc  midpt= " + str(midpt)+ "\n")
            # FreeCAD.Console.PrintMessage("arc  endpt= " + str(endpt)+ "\n")
            arc_cw = check_clockwise(
                [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
            # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
            if arc_cw:
                output = "G2"
            else:
                output = "G3"
            output += " X" + str(fmt(endpt.x)) + " Y" + \
                str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
            output += " I" + str(fmt(relcenter.x)) + " J" + \
                str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
            output += "\n"
            lastpt = endpt
            # FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n")
        else:
            point = edge.Vertexes[-1].Point
            if DraftVecUtils.equals(point, lastpt):  # edges can come flipped
                point = edge.Vertexes[0].Point
            output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
                " Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
            lastpt = point
            # FreeCAD.Console.PrintMessage("line\n")
            # FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n")
        return lastpt, output
Ejemplo n.º 15
0
def getProj(vec, plane):
    if not plane: return vec
    nx = DraftVecUtils.project(vec,plane.u)
    lx = nx.Length
    if abs(nx.getAngle(plane.u)) > 0.1: lx = -lx
    ny = DraftVecUtils.project(vec,plane.v)
    ly = ny.Length
    if abs(ny.getAngle(plane.v)) > 0.1: ly = -ly
    #if techdraw: buggy - we now simply do it at the end
    #    ly = -ly
    return Vector(lx,ly,0)
Ejemplo n.º 16
0
 def projectPointOld(self, p, direction=None):
     '''project point onto plane, default direction is orthogonal. Obsolete'''
     if not direction:
         direction = self.axis
     t = Vector(direction)
     #t.normalize()
     a = round(t.getAngle(self.axis),DraftVecUtils.precision())
     pp = round((math.pi)/2,DraftVecUtils.precision())
     if a == pp:
         return p
     t.multiply(self.offsetToPoint(p, direction))
     return p.add(t)
Ejemplo n.º 17
0
 def getCoupleFacesEquerre(self, faces):
     listeCouple = []
     lenfaces = len(faces)
     faces.append(faces[0])
     for n in range(lenfaces):
         norm2 = faces[n+1].normalAt(0,0)
         norm1 = faces[n].normalAt(0,0)
         norm0 = faces[n-1].normalAt(0,0)
         if abs(round(math.degrees(DraftVecUtils.angle(norm1,norm0)))) == 90.:
             listeCouple.append([faces[n],faces[n-1]])
         if abs(round(math.degrees(DraftVecUtils.angle(norm1,norm2)))) == 90.:
             listeCouple.append([faces[n],faces[n+1]])
     return listeCouple
Ejemplo n.º 18
0
 def isInside(self,point):
     "returns True if the given point is inside the rectangle"
     vp = point.sub(self.p1())
     uv = self.p2().sub(self.p1())
     vv = self.p4().sub(self.p1())
     uvp = DraftVecUtils.project(vp,uv)
     vvp = DraftVecUtils.project(vp,vv)
     if uvp.getAngle(uv) < 1:
         if vvp.getAngle(vv) < 1:
             if uvp.Length <= uv.Length:
                 if vvp.Length <= vv.Length:
                     return True
     return False
Ejemplo n.º 19
0
    def calc(self):
        import Part

        if (self.p1 != None) and (self.p2 != None):
            points = [
                DraftVecUtils.tup(self.p1, True),
                DraftVecUtils.tup(self.p2, True),
                DraftVecUtils.tup(self.p1, True),
                DraftVecUtils.tup(self.p2, True),
            ]
            if self.p3 != None:
                p1 = self.p1
                p4 = self.p2
                if DraftVecUtils.equals(p1, p4):
                    proj = None
                else:
                    base = Part.Line(p1, p4).toShape()
                    proj = DraftGeomUtils.findDistance(self.p3, base)
                if not proj:
                    p2 = p1
                    p3 = p4
                else:
                    p2 = p1.add(proj.negative())
                    p3 = p4.add(proj.negative())
                points = [DraftVecUtils.tup(p1), DraftVecUtils.tup(p2), DraftVecUtils.tup(p3), DraftVecUtils.tup(p4)]
            self.coords.point.setValues(0, 4, points)
Ejemplo n.º 20
0
def isSameEdge(e1, e2):
    """isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same
    points - inspired by Yorik's function isSameLine"""
    if not (isinstance(e1.Curve, Part.Line) or isinstance(e1.Curve, Part.Circle)):
        return False
    if not (isinstance(e2.Curve, Part.Line) or isinstance(e2.Curve, Part.Circle)):
        return False
    if type(e1.Curve) != type(e2.Curve):
        return False
    if isinstance(e1.Curve, Part.Line):
        if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
           (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
            return True
        elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
                (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
            return True
    if isinstance(e1.Curve, Part.Circle):
        center = False
        radius = False
        endpts = False
        if e1.Curve.Center == e2.Curve.Center:
            center = True
        if e1.Curve.Radius == e2.Curve.Radius:
            radius = True
        if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
           (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
            endpts = True
        elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
                (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
            endpts = True
        if (center and radius and endpts):
            return True
    return False
Ejemplo n.º 21
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 = DraftVecUtils.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 = DraftVecUtils.neg(dv)
         self.tracker.update([b.add(dv),point.add(dv)])
Ejemplo n.º 22
0
 def projectPoint(self, p, direction=None):
     """project point onto plane, default direction is orthogonal"""
     if not direction:
         direction = self.axis
     lp = self.getLocalCoords(p)
     gp = self.getGlobalCoords(Vector(lp.x, lp.y, 0))
     a = direction.getAngle(gp.sub(p))
     if a > math.pi / 2:
         direction = DraftVecUtils.neg(direction)
         a = math.pi - a
     ld = self.getLocalRot(direction)
     gd = self.getGlobalRot(Vector(ld.x, ld.y, 0))
     hyp = abs(math.tan(a) * lp.z)
     return gp.add(DraftVecUtils.scaleTo(gd, hyp))
Ejemplo n.º 23
0
 def createGeometry(self,obj):
     import Part, DraftGeomUtils
     pl = obj.Placement
     base = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if hasattr(obj,"WindowParts"):
                 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 = DraftVecUtils.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 = DraftVecUtils.scaleTo(norm,zof)
                                     shape.translate(zov)
                             shapes.append(shape)
                     if shapes:
                         base = Part.makeCompound(shapes)
                         if not DraftGeomUtils.isNull(pl):
                             base.Placement = pl
                         
     base = self.processSubShapes(obj,base)
     if base:
         if not base.isNull():
             obj.Shape = base
Ejemplo n.º 24
0
def getCutVolume(cutplane, shapes):
    """getCutVolume(cutplane,shapes): returns a cut face and a cut volume
    from the given shapes and the given cutting plane"""
    import Part

    placement = FreeCAD.Placement(cutplane.Placement)
    # building boundbox
    bb = shapes[0].BoundBox
    for sh in shapes[1:]:
        bb.add(sh.BoundBox)
    bb.enlarge(1)
    um = vm = wm = 0
    ax = placement.Rotation.multVec(FreeCAD.Vector(0, 0, 1))
    u = placement.Rotation.multVec(FreeCAD.Vector(1, 0, 0))
    v = placement.Rotation.multVec(FreeCAD.Vector(0, 1, 0))
    if not bb.isCutPlane(placement.Base, ax):
        FreeCAD.Console.PrintMessage(str(translate("Arch", "No objects are cut by the plane")))
        return None, None, None
    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 = DraftVecUtils.project(dv, u).Length
            um = max(um, um1)
            vm1 = DraftVecUtils.project(dv, v).Length
            vm = max(vm, vm1)
            wm1 = DraftVecUtils.project(dv, ax).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 = DraftVecUtils.scaleTo(ax, wm)
        cutvolume = cutface.extrude(cutnormal)
        cutnormal = DraftVecUtils.neg(cutnormal)
        invcutvolume = cutface.extrude(cutnormal)
        return cutface, cutvolume, invcutvolume
Ejemplo n.º 25
0
 def getLocalRot(self,point):
     "Same as getLocalCoords, but discards the WP position"
     xv = DraftVecUtils.project(point,self.u)
     x = xv.Length
     if xv.getAngle(self.u) > 1:
             x = -x
     yv = DraftVecUtils.project(point,self.v)
     y = yv.Length
     if yv.getAngle(self.v) > 1:
             y = -y
     zv = DraftVecUtils.project(point,self.axis)
     z = zv.Length
     if zv.getAngle(self.axis) > 1:
             z = -z
     return Vector(x,y,z)
Ejemplo n.º 26
0
def getPlacement(entity):
    "returns a placement from the given entity"
    if DEBUG: print "getting placement ",entity
    if not entity: return None
    pl = None
    if entity.type == "IFCAXIS2PLACEMENT3D":
        x = getVector(entity.RefDirection)
        z = getVector(entity.Axis)
        y = z.cross(x)
        loc = getVector(entity.Location)
        m = DraftVecUtils.getPlaneRotation(x,y,z)
        pl = FreeCAD.Placement(m)
        pl.move(loc)
    elif entity.type == "IFCLOCALPLACEMENT":
        pl = getPlacement(entity.PlacementRelTo)
        relpl = getPlacement(entity.RelativePlacement)
        if pl and relpl:
            pl = relpl.multiply(pl)
        elif relpl:
            pl = relpl
    elif entity.type == "IFCCARTESIANPOINT":
        loc = getVector(entity)
        pl = FreeCAD.Placement()
        pl.move(loc)
    if DEBUG: print "made placement for",entity.id,":",pl
    return pl
Ejemplo n.º 27
0
 def rotateSel(sel, n):
     p = sel.Object.Placement
     loc = sel.Object.Placement.Base
     r = axis.cross(n) # rotation axis
     a = DraftVecUtils.angle(n, axis, r) * 180 / math.pi
     PathLog.debug("oh boy: (%.2f, %.2f, %.2f) -> %.2f" % (r.x, r.y, r.z, a))
     Draft.rotate(sel.Object, a, axis=r)
Ejemplo n.º 28
0
 def getPoint(self,point=None,obj=None):
     "this function is called by the snapper when it has a 3D point"
     self.tracker.finalize()
     if point == None:
         return
     FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
     FreeCADGui.addModule("Arch")
     if self.Profile:
         pr = Presets[self.Profile]
         FreeCADGui.doCommand('p = Arch.makeProfile('+str(pr[2])+','+str(pr[3])+','+str(pr[4])+','+str(pr[5])+')')
         if self.Length == pr[2]:
             # vertical
             FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Height)+')')
         else:
             # horizontal
             FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Length)+')')
             FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
         FreeCADGui.doCommand('s.Profile = "'+pr[1]+'"')
     else:
         FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')')
     FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
     FreeCADGui.doCommand('s.Placement.Rotation=FreeCAD.DraftWorkingPlane.getRotation().Rotation')
     FreeCAD.ActiveDocument.commitTransaction()
     FreeCAD.ActiveDocument.recompute()
     if self.continueCmd:
         self.Activated()
Ejemplo n.º 29
0
    def getRoofPaneProject(self, i):
        self.ptsPaneProject=[]
        profilCurrent = self.findProfil(i)
        profilBack1 = self.findProfil(i-1)
        profilNext1 = self.findProfil(i+1)
        if profilCurrent["angle"] != 90.:
            if profilNext1["angle"] == 90. :
                self.nextPignon(i)
            elif profilNext1["height"] == profilCurrent["height"] :
                self.nextSameHeight(i)
            elif profilNext1["height"] < profilCurrent["height"] :
                self.nextSmaller(i)
            elif profilNext1["height"] > profilCurrent["height"] :
                self.nextHigher(i)
            else:
                print("Arch Roof : Case Not implemented")
            if profilBack1["angle"] == 90. :
                self.backPignon(i)
            elif profilBack1["height"] == profilCurrent["height"] :
                self.backSameHeight(i)
            elif profilBack1["height"] < profilCurrent["height"] :
                self.backSmaller(i)
            elif profilBack1["height"] > profilCurrent["height"] :
                self.backHigher(i)
            else:
                print("Arch Roof : Case Not implemented")
        else:
            self.ptsPaneProject=[]

        self.ptsPaneProject = DraftVecUtils.removeDoubles(self.ptsPaneProject)
        profilCurrent["points"] = self.ptsPaneProject
Ejemplo n.º 30
0
 def execute(self, obj):
     if obj.Source:
         if hasattr(obj.Source.Proxy,"BaseProfile"):
             p = obj.Source.Proxy.BaseProfile
             n = obj.Source.Proxy.ExtrusionVector
             import Drawing
             svg1 = ""
             svg2 = ""
             result = ""
             svg1 = Drawing.projectToSVG(p,DraftVecUtils.neg(n))
             if svg1:
                 w = str(obj.LineWidth/obj.Scale) #don't let linewidth be influenced by the scale...
                 svg1 = svg1.replace('stroke-width="0.35"','stroke-width="'+w+'"')
                 svg1 = svg1.replace('stroke-width="1"','stroke-width="'+w+'"')
                 svg1 = svg1.replace('stroke-width:0.01','stroke-width:'+w)
                 svg1 = svg1.replace('scale(1,-1)','scale('+str(obj.Scale)+',-'+str(obj.Scale)+')')
             if obj.Source.Tag:
                 svg2 = '<text id="tag'+obj.Name+'"'
                 svg2 += ' fill="'+Draft.getrgb(obj.TextColor)+'"'
                 svg2 += ' font-size="'+str(obj.FontSize)+'"'
                 svg2 += ' style="text-anchor:start;text-align:left;'
                 svg2 += ' font-family:'+obj.FontName+'" '
                 svg2 += ' transform="translate(' + str(obj.TextX) + ',' + str(obj.TextY) + ')">'
                 svg2 += '<tspan>'+obj.Source.Tag+'</tspan></text>\n'
             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 += '">\n  '
             result += svg1
             result += svg2
             result += '</g>'
             obj.ViewResult = result
Ejemplo n.º 31
0
 def rotate(self, axis, angle):
     "rotates the ghost of a given angle"
     self.trans.rotation.setValue(coin.SbVec3f(DraftVecUtils.tup(axis)),
                                  angle)
Ejemplo n.º 32
0
 def calcEdgeGeometry(self, edges, i):
     self.profilsDico[i]["edge"] = edges[i]
     vec = edges[i].Vertexes[-1].Point.sub(edges[i].Vertexes[0].Point)
     self.profilsDico[i]["vec"] = vec
     rot = math.degrees(DraftVecUtils.angle(vec))
     self.profilsDico[i]["rot"] = rot
Ejemplo n.º 33
0
    def onChanged(self, vobj, prop):

        if prop == "LineColor":
            if hasattr(vobj, "LineColor"):
                l = vobj.LineColor
                self.mat1.diffuseColor.setValue([l[0], l[1], l[2]])
                self.mat2.diffuseColor.setValue([l[0], l[1], l[2]])
        elif prop == "Transparency":
            if hasattr(vobj, "Transparency"):
                self.mat2.transparency.setValue(vobj.Transparency / 100.0)
        elif prop in ["DisplayLength", "DisplayHeight", "ArrowSize"]:
            if hasattr(vobj, "DisplayLength") and hasattr(
                    vobj, "DisplayHeight"):
                ld = vobj.DisplayLength.Value / 2
                hd = vobj.DisplayHeight.Value / 2
            elif hasattr(vobj, "DisplaySize"):
                # old objects
                ld = vobj.DisplaySize.Value / 2
                hd = vobj.DisplaySize.Value / 2
            else:
                ld = 1
                hd = 1
            verts = []
            fverts = []
            for v in [[-ld, -hd], [ld, -hd], [ld, hd], [-ld, hd]]:
                if hasattr(vobj, "ArrowSize"):
                    l1 = vobj.ArrowSize.Value if vobj.ArrowSize.Value > 0 else 0.1
                else:
                    l1 = 0.1
                l2 = l1 / 3
                pl = FreeCAD.Placement(vobj.Object.Placement)
                p1 = pl.multVec(Vector(v[0], v[1], 0))
                p2 = pl.multVec(Vector(v[0], v[1], -l1))
                p3 = pl.multVec(Vector(v[0] - l2, v[1], -l1 + l2))
                p4 = pl.multVec(Vector(v[0] + l2, v[1], -l1 + l2))
                p5 = pl.multVec(Vector(v[0], v[1] - l2, -l1 + l2))
                p6 = pl.multVec(Vector(v[0], v[1] + l2, -l1 + l2))
                verts.extend([[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]])
                fverts.append([p1.x, p1.y, p1.z])
                verts.extend([[p2.x, p2.y, p2.z], [p3.x, p3.y, p3.z],
                              [p4.x, p4.y, p4.z], [p2.x, p2.y, p2.z]])
                verts.extend([[p2.x, p2.y, p2.z], [p5.x, p5.y, p5.z],
                              [p6.x, p6.y, p6.z], [p2.x, p2.y, p2.z]])
            verts.extend(fverts + [fverts[0]])
            self.lcoords.point.setValues(verts)
            self.fcoords.point.setValues(fverts)
        elif prop == "LineWidth":
            self.drawstyle.lineWidth = vobj.LineWidth
        elif prop in ["CutView", "CutMargin"]:
            if hasattr(vobj,
                       "CutView") and FreeCADGui.ActiveDocument.ActiveView:
                sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
                if vobj.CutView:
                    if self.clip:
                        sg.removeChild(self.clip)
                        self.clip = None
                    for o in Draft.getGroupContents(vobj.Object.Objects,
                                                    walls=True):
                        if hasattr(o.ViewObject, "Lighting"):
                            o.ViewObject.Lighting = "One side"
                    self.clip = coin.SoClipPlane()
                    self.clip.on.setValue(True)
                    norm = vobj.Object.Proxy.getNormal(vobj.Object)
                    mp = vobj.Object.Shape.CenterOfMass
                    mp = DraftVecUtils.project(mp, norm)
                    dist = mp.Length  #- 0.1 # to not clip exactly on the section object
                    norm = norm.negative()
                    marg = 1
                    if hasattr(vobj, "CutMargin"):
                        marg = vobj.CutMargin.Value
                    if mp.getAngle(norm) > 1:
                        dist += marg
                        dist = -dist
                    else:
                        dist -= marg
                    plane = coin.SbPlane(coin.SbVec3f(norm.x, norm.y, norm.z),
                                         dist)
                    self.clip.plane.setValue(plane)
                    sg.insertChild(self.clip, 0)
                else:
                    if self.clip:
                        sg.removeChild(self.clip)
                        self.clip = None
        return
Ejemplo n.º 34
0
 def __repr__(self):
     return "Workplane x=" + str(DraftVecUtils.rounded(
         self.u)) + " y=" + str(DraftVecUtils.rounded(
             self.v)) + " z=" + str(DraftVecUtils.rounded(self.axis))
Ejemplo n.º 35
0
 def getPerpendicular(self, edge, pt):
     "returns a point on an edge, perpendicular to the given point"
     dv = pt.sub(edge.Vertexes[0].Point)
     nv = DraftVecUtils.project(dv, DraftGeomUtils.vec(edge))
     np = (edge.Vertexes[0].Point).add(nv)
     return np
Ejemplo n.º 36
0
def rotate(objectslist,
           angle,
           center=App.Vector(0, 0, 0),
           axis=App.Vector(0, 0, 1),
           copy=False):
    """rotate(objects,angle,[center,axis,copy])

    Rotates the objects contained in objects (that can be a list of objects
    or an object) of the given angle (in degrees) around the center, using
    axis as a rotation axis.

    Parameters
    ----------
    objectslist : list

    angle : rotation angle (in degrees)

    center : Base.Vector

    axis : Base.Vector
        If axis is omitted, the rotation will be around the vertical Z axis.

    copy : bool
        If copy is True, the actual objects are not moved, but copies
        are created instead.

    Return
    ----------
    The objects (or their copies) are returned.
    """
    import Part
    utils.type_check([(copy, bool)], "rotate")
    if not isinstance(objectslist, list):
        objectslist = [objectslist]

    objectslist.extend(groups.get_movable_children(objectslist))
    newobjlist = []
    newgroups = {}
    objectslist = utils.filter_objects_for_modifiers(objectslist, copy)

    if copy:
        doc = App.ActiveDocument
        for obj in objectslist:
            if obj.isDerivedFrom("App::DocumentObjectGroup") \
                    and obj.Name not in newgroups.keys():
                newgroups[obj.Name] = doc.addObject(
                    obj.TypeId, utils.get_real_name(obj.Name))

    for obj in objectslist:
        newobj = None

        # real_center and real_axis are introduced to take into account
        # the possibility that object is inside an App::Part
        if hasattr(obj, "getGlobalPlacement"):
            ci = obj.getGlobalPlacement().inverse().multVec(center)
            real_center = obj.Placement.multVec(ci)
            ai = obj.getGlobalPlacement().inverse().Rotation.multVec(axis)
            real_axis = obj.Placement.Rotation.multVec(ai)
        else:
            real_center = center
            real_axis = axis

        if obj.isDerivedFrom("App::Annotation"):
            # TODO: this is very different from how move handle annotations
            # maybe we can uniform the two methods
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            if axis.normalize() == App.Vector(1, 0, 0):
                newobj.ViewObject.RotationAxis = "X"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, 1, 0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, -1, 0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = -angle
            elif axis.normalize() == App.Vector(0, 0, 1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, 0, -1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = -angle

        elif utils.get_type(obj) == "Point":
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            v = App.Vector(newobj.X, newobj.Y, newobj.Z)
            rv = v.sub(real_center)
            rv = DraftVecUtils.rotate(rv, math.radians(angle), real_axis)
            v = real_center.add(rv)
            newobj.X = v.x
            newobj.Y = v.y
            newobj.Z = v.z

        elif obj.isDerivedFrom("App::DocumentObjectGroup"):
            if copy:
                newobj = newgroups[obj.Name]
            else:
                newobj = obj

        elif hasattr(obj, "Placement"):
            # App.Console.PrintMessage("placement rotation\n")
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            # Workaround for `faulty` implementation of Base.Placement.rotate(center, axis, angle).
            # See: https://forum.freecadweb.org/viewtopic.php?p=613196#p613196
            offset_rotation = App.Placement(App.Vector(0, 0, 0),
                                            App.Rotation(real_axis, angle),
                                            real_center)
            newobj.Placement = offset_rotation * newobj.Placement

        elif hasattr(obj, "Shape"):
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            shape = newobj.Shape.copy()
            shape.rotate(real_center, real_axis, angle)
            newobj.Shape = shape

        if newobj is not None:
            newobjlist.append(newobj)
            if copy:
                for parent in obj.InList:
                    if parent.isDerivedFrom("App::DocumentObjectGroup") \
                            and (parent in objectslist):
                        newgroups[parent.Name].addObject(newobj)
                    if utils.get_type(parent) == "Layer":
                        parent.Proxy.addObject(parent, newobj)

    if copy and utils.get_param("selectBaseObjects", False):
        gui_utils.select(objectslist)
    else:
        gui_utils.select(newobjlist)

    if len(newobjlist) == 1:
        return newobjlist[0]
    return newobjlist
Ejemplo n.º 37
0
    def redraw(self, point, snapped=None, shift=False, alt=False, real=None):
        """Redraw the ghost normally."""
        # initializing
        reverse = False
        for g in self.ghost:
            g.off()
        if real:
            newedges = []

        import DraftGeomUtils
        import Part

        # finding the active point
        vlist = []
        for e in self.edges:
            vlist.append(e.Vertexes[0].Point)
        vlist.append(self.edges[-1].Vertexes[-1].Point)
        if shift:
            npoint = self.activePoint
        else:
            npoint = DraftGeomUtils.findClosest(point, vlist)
        if npoint > len(self.edges) / 2:
            reverse = True
        if alt:
            reverse = not reverse
        self.activePoint = npoint

        # sorting out directions
        if reverse and (npoint > 0):
            npoint = npoint - 1
        if (npoint > len(self.edges) - 1):
            edge = self.edges[-1]
            ghost = self.ghost[-1]
        else:
            edge = self.edges[npoint]
            ghost = self.ghost[npoint]
        if reverse:
            v1 = edge.Vertexes[-1].Point
            v2 = edge.Vertexes[0].Point
        else:
            v1 = edge.Vertexes[0].Point
            v2 = edge.Vertexes[-1].Point

        # snapping
        if snapped:
            snapped = self.doc.getObject(snapped['Object'])
            if hasattr(snapped, "Shape"):
                pts = []
                for e in snapped.Shape.Edges:
                    int = DraftGeomUtils.findIntersection(edge, e, True, True)
                    if int:
                        pts.extend(int)
                if pts:
                    point = pts[DraftGeomUtils.findClosest(point, pts)]

        # modifying active edge
        if DraftGeomUtils.geomType(edge) == "Line":
            ve = DraftGeomUtils.vec(edge)
            chord = v1.sub(point)
            n = ve.cross(chord)
            if n.Length == 0:
                self.newpoint = point
            else:
                perp = ve.cross(n)
                proj = DraftVecUtils.project(chord, perp)
                self.newpoint = App.Vector.add(point, proj)
            dist = v1.sub(self.newpoint).Length
            ghost.p1(self.newpoint)
            ghost.p2(v2)
            self.ui.labelRadius.setText(translate("draft", "Distance"))
            self.ui.radiusValue.setToolTip(
                translate("draft", "The offset distance"))
            if real:
                if self.force:
                    ray = self.newpoint.sub(v1)
                    ray.multiply(self.force / ray.Length)
                    self.newpoint = App.Vector.add(v1, ray)
                newedges.append(Part.LineSegment(self.newpoint, v2).toShape())
        else:
            center = edge.Curve.Center
            rad = edge.Curve.Radius
            ang1 = DraftVecUtils.angle(v2.sub(center))
            ang2 = DraftVecUtils.angle(point.sub(center))
            _rot_rad = DraftVecUtils.rotate(App.Vector(rad, 0, 0), -ang2)
            self.newpoint = App.Vector.add(center, _rot_rad)
            self.ui.labelRadius.setText(translate("draft", "Angle"))
            self.ui.radiusValue.setToolTip(
                translate("draft", "The offset angle"))
            dist = math.degrees(-ang2)
            # if ang1 > ang2:
            #     ang1, ang2 = ang2, ang1
            # print("last calculated:",
            #       math.degrees(-ang1),
            #       math.degrees(-ang2))
            ghost.setEndAngle(-ang2)
            ghost.setStartAngle(-ang1)
            ghost.setCenter(center)
            ghost.setRadius(rad)
            if real:
                if self.force:
                    angle = math.radians(self.force)
                    newray = DraftVecUtils.rotate(App.Vector(rad, 0, 0),
                                                  -angle)
                    self.newpoint = App.Vector.add(center, newray)
                chord = self.newpoint.sub(v2)
                perp = chord.cross(App.Vector(0, 0, 1))
                scaledperp = DraftVecUtils.scaleTo(perp, rad)
                midpoint = App.Vector.add(center, scaledperp)
                _sh = Part.Arc(self.newpoint, midpoint, v2).toShape()
                newedges.append(_sh)
        ghost.on()

        # resetting the visible edges
        if not reverse:
            li = list(range(npoint + 1, len(self.edges)))
        else:
            li = list(range(npoint - 1, -1, -1))
        for i in li:
            edge = self.edges[i]
            ghost = self.ghost[i]
            if DraftGeomUtils.geomType(edge) == "Line":
                ghost.p1(edge.Vertexes[0].Point)
                ghost.p2(edge.Vertexes[-1].Point)
            else:
                ang1 = DraftVecUtils.angle(edge.Vertexes[0].Point.sub(center))
                ang2 = DraftVecUtils.angle(edge.Vertexes[-1].Point.sub(center))
                # if ang1 > ang2:
                #     ang1, ang2 = ang2, ang1
                ghost.setEndAngle(-ang2)
                ghost.setStartAngle(-ang1)
                ghost.setCenter(edge.Curve.Center)
                ghost.setRadius(edge.Curve.Radius)
            if real:
                newedges.append(edge)
            ghost.on()

        # finishing
        if real:
            return newedges
        else:
            return dist
Ejemplo n.º 38
0
    def trimObjects(self, objectslist):
        """Attempt to trim two objects together."""
        import Part
        import DraftGeomUtils

        wires = []
        for obj in objectslist:
            if not utils.getType(obj) in ["Wire", "Circle"]:
                _err(
                    translate(
                        "draft", "Unable to trim these objects, "
                        "only Draft wires and arcs are supported."))
                return
            if len(obj.Shape.Wires) > 1:
                _err(
                    translate(
                        "draft", "Unable to trim these objects, "
                        "too many wires"))
                return
            if len(obj.Shape.Wires) == 1:
                wires.append(obj.Shape.Wires[0])
            else:
                wires.append(Part.Wire(obj.Shape.Edges))
        ints = []
        edge1 = None
        edge2 = None
        for i1, e1 in enumerate(wires[0].Edges):
            for i2, e2 in enumerate(wires[1].Edges):
                i = DraftGeomUtils.findIntersection(e1, e2, dts=False)
                if len(i) == 1:
                    ints.append(i[0])
                    edge1 = i1
                    edge2 = i2
        if not ints:
            _err(translate("draft", "These objects don't intersect."))
            return
        if len(ints) != 1:
            _err(translate("draft", "Too many intersection points."))
            return

        v11 = wires[0].Vertexes[0].Point
        v12 = wires[0].Vertexes[-1].Point
        v21 = wires[1].Vertexes[0].Point
        v22 = wires[1].Vertexes[-1].Point
        if DraftVecUtils.closest(ints[0], [v11, v12]) == 1:
            last1 = True
        else:
            last1 = False
        if DraftVecUtils.closest(ints[0], [v21, v22]) == 1:
            last2 = True
        else:
            last2 = False
        for i, obj in enumerate(objectslist):
            if i == 0:
                ed = edge1
                la = last1
            else:
                ed = edge2
                la = last2
            if utils.getType(obj) == "Wire":
                if la:
                    pts = obj.Points[:ed + 1] + ints
                else:
                    pts = ints + obj.Points[ed + 1:]
                obj.Points = pts
            else:
                vec = ints[0].sub(obj.Placement.Base)
                vec = obj.Placement.inverse().Rotation.multVec(vec)
                _x = App.Vector(1, 0, 0)
                _ang = -DraftVecUtils.angle(vec,
                                            obj.Placement.Rotation.multVec(_x),
                                            obj.Shape.Edges[0].Curve.Axis)
                ang = math.degrees(_ang)
                if la:
                    obj.LastAngle = ang
                else:
                    obj.FirstAngle = ang
        self.doc.recompute()
Ejemplo n.º 39
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::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(DraftGeomUtils.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(DraftGeomUtils.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
Ejemplo n.º 40
0
def get_DXF(obj, direction=None):
    """getDXF(object,[direction]): returns a DXF entity from the given
    object. If direction is given, the object is projected in 2D."""
    plane = None
    result = ""
    if obj.isDerivedFrom("Drawing::View") or obj.isDerivedFrom(
            "TechDraw::DrawView"):
        if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
            for o in obj.Source.Group:
                result += getDXF(o, obj.Direction)
        else:
            result += getDXF(obj.Source, obj.Direction)
        return result
    if direction:
        if isinstance(direction, App.Vector):
            import WorkingPlane
            if direction != App.Vector(0, 0, 0):
                plane = WorkingPlane.Plane()
                plane.alignToPointAndAxis(App.Vector(0, 0, 0), direction)

    def getProj(vec):
        if not plane: return vec
        nx = DraftVecUtils.project(vec, plane.u)
        ny = DraftVecUtils.project(vec, plane.v)
        return App.Vector(nx.Length, ny.Length, 0)

    if getType(obj) in ["Dimension", "LinearDimension"]:
        p1 = getProj(obj.Start)
        p2 = getProj(obj.End)
        p3 = getProj(obj.Dimline)
        result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n"
        result += "10\n" + str(p3.x) + "\n20\n" + str(p3.y) + "\n30\n" + str(
            p3.z) + "\n"
        result += "13\n" + str(p1.x) + "\n23\n" + str(p1.y) + "\n33\n" + str(
            p1.z) + "\n"
        result += "14\n" + str(p2.x) + "\n24\n" + str(p2.y) + "\n34\n" + str(
            p2.z) + "\n"

    elif getType(obj) == "Annotation":
        p = getProj(obj.Position)
        count = 0
        for t in obj.LabeLtext:
            result += "0\nTEXT\n8\n0\n62\n0\n"
            result += "10\n" + str(
                p.x) + "\n20\n" + str(p.y + count) + "\n30\n" + str(p.z) + "\n"
            result += "40\n1\n"
            result += "1\n" + str(t) + "\n"
            result += "7\nSTANDARD\n"
            count += 1

    elif hasattr(obj, 'Shape'):
        # TODO do this the Draft way, for ex. using polylines and rectangles
        import Drawing
        import DraftVecUtils
        if not direction:
            direction = FreeCAD.Vector(0, 0, -1)
        if DraftVecUtils.isNull(direction):
            direction = FreeCAD.Vector(0, 0, -1)
        try:
            d = Drawing.projectToDXF(obj.Shape, direction)
        except:
            print("Draft.getDXF: Unable to project ", obj.Label, " to ",
                  direction)
        else:
            result += d

    else:
        print("Draft.getDXF: Unsupported object: ", obj.Label)

    return result
Ejemplo n.º 41
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 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
     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 len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 else:
                     # basewires = obj.Base.Shape.Wires
                     basewires = [
                         Part.Wire(cluster) for cluster in
                         Part.getSortedClusters(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)
                                     # 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)
         return (base, extrusion, placement)
     return None
Ejemplo n.º 42
0
def getCutVolume(cutplane, shapes):
    """getCutVolume(cutplane,shapes): returns a cut face and a cut volume
    from the given shapes and the given cutting plane"""
    import Part
    if not isinstance(shapes, list):
        shapes = [shapes]
    # building boundbox
    bb = shapes[0].BoundBox
    for sh in shapes[1:]:
        bb.add(sh.BoundBox)
    bb.enlarge(1)
    # building cutplane space
    placement = None
    um = vm = wm = 0
    try:
        if hasattr(cutplane, "Shape"):
            p = cutplane.Shape.copy().Faces[0]
        else:
            p = cutplane.copy().Faces[0]
    except:
        FreeCAD.Console.PrintMessage(translate("Arch", "Invalid cutplane"))
        return None, None, None
    ce = p.CenterOfMass
    ax = p.normalAt(0, 0)
    u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize()
    v = u.cross(ax)
    if not bb.isCutPlane(ce, ax):
        FreeCAD.Console.PrintMessage(
            translate("Arch", "No objects are cut by the plane"))
        return None, None, None
    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(ce)
            um1 = DraftVecUtils.project(dv, u).Length
            um = max(um, um1)
            vm1 = DraftVecUtils.project(dv, v).Length
            vm = max(vm, vm1)
            wm1 = DraftVecUtils.project(dv, ax).Length
            wm = max(wm, wm1)
        vu = DraftVecUtils.scaleTo(u, um)
        vui = vu.negative()
        vv = DraftVecUtils.scaleTo(v, vm)
        vvi = vv.negative()
        p1 = ce.add(vu.add(vvi))
        p2 = ce.add(vu.add(vv))
        p3 = ce.add(vui.add(vv))
        p4 = ce.add(vui.add(vvi))
        cutface = Part.makePolygon([p1, p2, p3, p4, p1])
        cutface = Part.Face(cutface)
        cutnormal = DraftVecUtils.scaleTo(ax, wm)
        cutvolume = cutface.extrude(cutnormal)
        cutnormal = cutnormal.negative()
        invcutvolume = cutface.extrude(cutnormal)
        return cutface, cutvolume, invcutvolume
Ejemplo n.º 43
0
    def compare(self, face1, face2):
        "zsorts two faces. Returns 1 if face1 is closer, 2 if face2 is closer, 0 otherwise"

        #print face1,face2

        if not face1:
            if DEBUG: print "Warning, undefined face!"
            return 31
        elif not face2:
            if DEBUG: print "Warning, undefined face!"
            return 32

        # theory from
        # http://www.siggraph.org/education/materials/HyperGraph/scanline/visibility/painter.htm
        # and practical application http://vrm.ao2.it/ (blender vector renderer)

        b1 = face1[0].BoundBox
        b2 = face2[0].BoundBox

        # test 1: if faces don't overlap, no comparison possible
        if DEBUG: print "doing test 1"
        if b1.XMax < b2.XMin:
            return 0
        if b1.XMin > b2.XMax:
            return 0
        if b1.YMax < b2.YMin:
            return 0
        if b1.YMin > b2.YMax:
            return 0
        if DEBUG: print "failed, faces bboxes are not distinct"

        # test 2: if Z bounds dont overlap, it's easy to know the closest
        if DEBUG: print "doing test 2"
        if b1.ZMax < b2.ZMin:
            return 2
        if b2.ZMax < b1.ZMin:
            return 1
        if DEBUG: print "failed, faces Z are not distinct"

        # test 3: all verts of face1 are in front or behind the plane of face2
        if DEBUG: print "doing test 3"
        norm = face2[0].normalAt(0, 0)
        behind = 0
        front = 0
        for v in face1[0].Vertexes:
            dv = v.Point.sub(face2[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv, norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print "front: ", front, " behind: ", behind
        if behind == len(face1[0].Vertexes):
            return 2
        elif front == len(face1[0].Vertexes):
            return 1
        if DEBUG: print "failed, cannot say if face 1 is in front or behind"

        # test 4: all verts of face2 are in front or behind the plane of face1
        if DEBUG: print "doing test 4"
        norm = face1[0].normalAt(0, 0)
        behind = 0
        front = 0
        for v in face2[0].Vertexes:
            dv = v.Point.sub(face1[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv, norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print "front: ", front, " behind: ", behind
        if behind == len(face2[0].Vertexes):
            return 1
        elif front == len(face2[0].Vertexes):
            return 2
        if DEBUG: print "failed, cannot say if face 2 is in front or behind"

        # test 5: see if faces projections don't overlap, vertexwise
        if DEBUG: print "doing test 5"
        if not self.zOverlaps(face1, face2):
            return 0
        elif not self.zOverlaps(face2, face1):
            return 0
        if DEBUG: print "failed, faces are overlapping"

        if DEBUG: print "Houston, all tests passed, and still no results"
        return 0
Ejemplo n.º 44
0
    def execute(self, obj):

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

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

        if not obj.Host:
            return
        if Draft.getType(obj.Host) != "Structure":
            return
        if not obj.Host.Shape:
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        wire = obj.Base.Shape.Wires[0]
        if Draft.getType(
                obj.Base) == "Wire":  # Draft Wires can have "wrong" placement
            import DraftGeomUtils
            axis = DraftGeomUtils.getNormal(obj.Base.Shape)
        else:
            axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(
                0, 0, -1))
        size = (ArchCommands.projectToVector(father.Shape.copy(), axis)).Length
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        if hasattr(obj, "Rounding"):
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        wires = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis, size / 2)
            wire.translate(offset)
            wires.append(wire)
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            if obj.ViewObject.RebarShape == "Stirrup":
                interval = size - (obj.OffsetStart.Value +
                                   obj.OffsetEnd.Value + obj.Diameter.Value)
            else:
                interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis, interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        wire.translate(baseoffset)
                    wires.append(wire)
                else:
                    wire = wire.copy()
                    wire.translate(vinterval)
                    wires.append(wire)
        return [wires, obj.Diameter.Value / 2]
Ejemplo n.º 46
0
def findIntersection(edge1, edge2,
                     infinite1=False, infinite2=False,
                     ex1=False, ex2=False,
                     dts=True, findAll=False):
    """Return a list containing the intersection points of 2 edges.

    You can also feed 4 points instead of `edge1` and `edge2`.
    If `dts` is used, `Shape.distToShape()` is used, which can be buggy.
    """

    def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
        if pt1:
            # first check if we don't already have coincident endpoints
            if pt1 in [pt3, pt4]:
                return [pt1]
            elif (pt2 in [pt3, pt4]):
                return [pt2]
        norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
        norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))

        if not DraftVecUtils.isNull(norm1):
            try:
                norm1.normalize()
            except Part.OCCError:
                return []

        if not DraftVecUtils.isNull(norm2):
            try:
                norm2.normalize()
            except Part.OCCError:
                return []

        if DraftVecUtils.isNull(norm1.cross(norm2)):
            vec1 = pt2.sub(pt1)
            vec2 = pt4.sub(pt3)
            if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2):
                return []  # One of the lines has zero-length
            try:
                vec1.normalize()
                vec2.normalize()
            except Part.OCCError:
                return []
            norm3 = vec1.cross(vec2)
            denom = norm3.x + norm3.y + norm3.z
            if not DraftVecUtils.isNull(norm3) and denom != 0:
                k = ((pt3.z - pt1.z) * (vec2.x - vec2.y)
                     + (pt3.y - pt1.y) * (vec2.z - vec2.x)
                     + (pt3.x - pt1.x) * (vec2.y - vec2.z))/denom
                vec1.scale(k, k, k)
                intp = pt1.add(vec1)

                if infinite1 is False and not isPtOnEdge(intp, edge1):
                    return []

                if infinite2 is False and not isPtOnEdge(intp, edge2):
                    return []

                return [intp]
            else:
                return []  # Lines have same direction
        else:
            return []  # Lines aren't on same plane

    # First, check bound boxes
    if (isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
            and (not infinite1) and (not infinite2)):
        if not edge1.BoundBox.intersect(edge2.BoundBox):
            return []  # bound boxes don't intersect

    # First, try to use distToShape if possible
    if (dts and isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
            and (not infinite1) and (not infinite2)):
        dist, pts, geom = edge1.distToShape(edge2)
        sol = []
        if round(dist, precision()) == 0:
            for p in pts:
                if p not in sol:
                    sol.append(p[0])
        return sol

    pt1 = None

    if isinstance(edge1, FreeCAD.Vector) and isinstance(edge2, FreeCAD.Vector):
        # we got points directly
        pt1 = edge1
        pt2 = edge2
        pt3 = infinite1
        pt4 = infinite2
        infinite1 = ex1
        infinite2 = ex2
        return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)

    elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line"):
        # we have 2 straight lines
        pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
                              edge1.Vertexes[1].Point,
                              edge2.Vertexes[0].Point,
                              edge2.Vertexes[1].Point]
        return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)

    elif ((geomType(edge1) == "Circle") and (geomType(edge2) == "Line")
          or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle")):

        # deals with an arc or circle and a line
        edges = [edge1, edge2]
        for edge in edges:
            if geomType(edge) == "Line":
                line = edge
            else:
                arc = edge

        dirVec = vec(line)
        dirVec.normalize()
        pt1 = line.Vertexes[0].Point
        pt2 = line.Vertexes[1].Point
        pt3 = arc.Vertexes[0].Point
        pt4 = arc.Vertexes[-1].Point
        center = arc.Curve.Center

        int = []
        # first check for coincident endpoints
        if DraftVecUtils.equals(pt1, pt3) or DraftVecUtils.equals(pt1, pt4):
            if findAll:
                int.append(pt1)
            else:
                return [pt1]
        elif pt2 in [pt3, pt4]:
            if findAll:
                int.append(pt2)
            else:
                return [pt2]

        if DraftVecUtils.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)):
            # Line and Arc are on same plane

            dOnLine = center.sub(pt1).dot(dirVec)
            onLine = FreeCAD.Vector(dirVec)
            onLine.scale(dOnLine, dOnLine, dOnLine)
            toLine = pt1.sub(center).add(onLine)

            if toLine.Length < arc.Curve.Radius:
                dOnLine = (arc.Curve.Radius**2 - toLine.Length**2)**(0.5)
                onLine = FreeCAD.Vector(dirVec)
                onLine.scale(dOnLine, dOnLine, dOnLine)
                int += [center.add(toLine).add(onLine)]
                onLine = FreeCAD.Vector(dirVec)
                onLine.scale(-dOnLine, -dOnLine, -dOnLine)
                int += [center.add(toLine).add(onLine)]
            elif round(toLine.Length - arc.Curve.Radius, precision()) == 0:
                int = [center.add(toLine)]
            else:
                return []

        else:
            # Line isn't on Arc's plane
            if dirVec.dot(arc.Curve.Axis) != 0:
                toPlane = FreeCAD.Vector(arc.Curve.Axis)
                toPlane.normalize()
                d = pt1.dot(toPlane)
                if not d:
                    return []
                dToPlane = center.sub(pt1).dot(toPlane)
                toPlane = FreeCAD.Vector(pt1)
                toPlane.scale(dToPlane/d, dToPlane/d, dToPlane/d)
                ptOnPlane = toPlane.add(pt1)
                if round(ptOnPlane.sub(center).Length - arc.Curve.Radius,
                         precision()) == 0:
                    int = [ptOnPlane]
                else:
                    return []
            else:
                return []

        if infinite1 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge1):
                    del int[i]
        if infinite2 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge2):
                    del int[i]
        return int

    elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Circle"):
        # deals with 2 arcs or circles
        cent1, cent2 = edge1.Curve.Center, edge2.Curve.Center
        rad1, rad2 = edge1.Curve.Radius, edge2.Curve.Radius
        axis1, axis2 = edge1.Curve.Axis, edge2.Curve.Axis
        c2c = cent2.sub(cent1)

        if cent1.sub(cent2).Length == 0:
            # circles are concentric
            return []

        if DraftVecUtils.isNull(axis1.cross(axis2)):
            if round(c2c.dot(axis1), precision()) == 0:
                # circles are on same plane
                dc2c = c2c.Length
                if not DraftVecUtils.isNull(c2c):
                    c2c.normalize()
                if (round(rad1 + rad2 - dc2c, precision()) < 0
                        or round(rad1 - dc2c - rad2, precision()) > 0
                        or round(rad2 - dc2c - rad1, precision()) > 0):
                    return []
                else:
                    norm = c2c.cross(axis1)
                    if not DraftVecUtils.isNull(norm):
                        norm.normalize()
                    if DraftVecUtils.isNull(norm):
                        x = 0
                    else:
                        x = (dc2c**2 + rad1**2 - rad2**2) / (2*dc2c)
                    y = abs(rad1**2 - x**2)**(0.5)
                    c2c.scale(x, x, x)
                    if round(y, precision()) != 0:
                        norm.scale(y, y, y)
                        int = [cent1.add(c2c).add(norm)]
                        int += [cent1.add(c2c).sub(norm)]
                    else:
                        int = [cent1.add(c2c)]
            else:
                return []  # circles are on parallel planes
        else:
            # circles aren't on same plane
            axis1.normalize()
            axis2.normalize()
            U = axis1.cross(axis2)
            V = axis1.cross(U)
            dToPlane = c2c.dot(axis2)
            d = V.add(cent1).dot(axis2)
            V.scale(dToPlane/d, dToPlane/d, dToPlane/d)
            PtOn2Planes = V.add(cent1)
            planeIntersectionVector = U.add(PtOn2Planes)
            intTemp = findIntersection(planeIntersectionVector,
                                       edge1, True, True)
            int = []
            for pt in intTemp:
                if round(pt.sub(cent2).Length-rad2, precision()) == 0:
                    int += [pt]

        if infinite1 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge1):
                    del int[i]
        if infinite2 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge2):
                    del int[i]

        return int
    else:
        print("DraftGeomUtils: Unsupported curve type: "
              "(" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")")
        return []
Ejemplo n.º 47
0
    def constrain(self, point, basepoint=None, axis=None):
        '''constrain(point,basepoint=None,axis=None: Returns a
        constrained point. Axis can be "x","y" or "z" or a custom vector. If None,
        the closest working plane axis will be picked.
        Basepoint is the base point used to figure out from where the point
        must be constrained. If no basepoint is given, the current point is
        used as basepoint.'''

        # without the Draft module fully loaded, no axes system!"
        if not hasattr(FreeCAD, "DraftWorkingPlane"):
            return point

        point = Vector(point)

        # setup trackers if needed
        if not self.constrainLine:
            self.constrainLine = DraftTrackers.lineTracker(dotted=True)

        # setting basepoint
        if not basepoint:
            if not self.basepoint:
                self.basepoint = point
        else:
            self.basepoint = basepoint
        delta = point.sub(self.basepoint)

        # setting constraint axis
        if self.mask:
            self.affinity = self.mask
        if not self.affinity:
            self.affinity = FreeCAD.DraftWorkingPlane.getClosestAxis(delta)
        if isinstance(axis, FreeCAD.Vector):
            self.constraintAxis = axis
        elif axis == "x":
            self.constraintAxis = FreeCAD.DraftWorkingPlane.u
        elif axis == "y":
            self.constraintAxis = FreeCAD.DraftWorkingPlane.v
        elif axis == "z":
            self.constraintAxis = FreeCAD.DraftWorkingPlane.axis
        else:
            if self.affinity == "x":
                self.constraintAxis = FreeCAD.DraftWorkingPlane.u
            elif self.affinity == "y":
                self.constraintAxis = FreeCAD.DraftWorkingPlane.v
            else:
                self.constraintAxis = FreeCAD.DraftWorkingPlane.axis

        # calculating constrained point
        cdelta = DraftVecUtils.project(delta, self.constraintAxis)
        npoint = self.basepoint.add(cdelta)

        # setting constrain line
        if self.constrainLine:
            if point != npoint:
                self.constrainLine.p1(point)
                self.constrainLine.p2(npoint)
                self.constrainLine.on()
            else:
                self.constrainLine.off()

        return npoint
Ejemplo n.º 48
0
def connect(edges, closed=False):
    """Connect the edges in the given list by their intersections."""
    nedges = []
    v2 = None

    for i in range(len(edges)):
        curr = edges[i]
        # print("debug: DraftGeomUtils.connect edge ", i, " : ",
        #       curr.Vertexes[0].Point, curr.Vertexes[-1].Point)
        if i > 0:
            prev = edges[i-1]
        else:
            if closed:
                prev = edges[-1]
            else:
                prev = None
        if i < (len(edges)-1):
            _next = edges[i+1]
        else:
            if closed:
                _next = edges[0]
            else:
                _next = None
        if prev:
            # print("debug: DraftGeomUtils.connect prev : ",
            #       prev.Vertexes[0].Point, prev.Vertexes[-1].Point)

            # If the edge pairs has intersection and if there is prev v2
            # (prev v2 was calculated intersection), do not calculate
            # again, just use it as current v1 - avoid chance of slight
            # difference in result.  And, if edge pairs
            # has no intersection (parallel edges, line
            # - arc do no intersect, etc.), so just just current
            # edge endpoints as v1 and connect these 2 non-intersecting
            # edges

            # Seem have chance that 2 parallel edges offset same width,
            # result in 2 colinear edges - Wall / DraftGeomUtils
            # seem make them 1 edge and thus 1 vertical plane
            i = findIntersection(curr, prev, True, True)
            if i:
                if v2:
                    v1 = v2
                else:
                    v1 = i[DraftVecUtils.closest(curr.Vertexes[0].Point, i)]
            else:
                v1 = curr.Vertexes[0].Point
                nedges.append(Part.LineSegment(v2, v1).toShape())
        else:
            v1 = curr.Vertexes[0].Point

        if _next:
            # print("debug: DraftGeomUtils.connect _next : ",
            #       _next.Vertexes[0].Point, _next.Vertexes[-1].Point)
            i = findIntersection(curr, _next, True, True)
            if i:
                v2 = i[DraftVecUtils.closest(curr.Vertexes[-1].Point, i)]
            else:
                v2 = curr.Vertexes[-1].Point
        else:
            v2 = curr.Vertexes[-1].Point
        if geomType(curr) == "Line":
            if v1 != v2:
                nedges.append(Part.LineSegment(v1, v2).toShape())
        elif geomType(curr) == "Circle":
            if v1 != v2:
                nedges.append(Part.Arc(v1,
                                       findMidpoint(curr),
                                       v2).toShape())
    try:
        return Part.Wire(nedges)
    except:
        print("DraftGeomUtils.connect: unable to connect edges")
        for e in nedges:
            print(e.Curve, " ",
                  e.Vertexes[0].Point, " ",
                  e.Vertexes[-1].Point)
        return None
Ejemplo n.º 49
0
    def snapToExtensions(self, point, last, constrain, eline):
        "returns a point snapped to extension or parallel line to last object, if any"

        if self.isEnabled("extension"):
            tsnap = self.snapToExtOrtho(last, constrain, eline)
            if tsnap:
                if (tsnap[0].sub(point)).Length < self.radius:
                    if self.tracker:
                        self.tracker.setCoords(tsnap[2])
                        self.tracker.setMarker(self.mk[tsnap[1]])
                        self.tracker.on()
                    if self.extLine:
                        self.extLine.p2(tsnap[2])
                        self.extLine.on()
                    self.setCursor(tsnap[1])
                    return tsnap[2], eline
            else:
                tsnap = self.snapToExtPerpendicular(last)
                if tsnap:
                    if (tsnap[0].sub(point)).Length < self.radius:
                        if self.tracker:
                            self.tracker.setCoords(tsnap[2])
                            self.tracker.setMarker(self.mk[tsnap[1]])
                            self.tracker.on()
                        if self.extLine:
                            self.extLine.p2(tsnap[2])
                            self.extLine.on()
                        self.setCursor(tsnap[1])
                        return tsnap[2], eline

        for o in [self.lastObj[1], self.lastObj[0]]:
            if o:
                ob = FreeCAD.ActiveDocument.getObject(o)
                if ob:
                    if ob.isDerivedFrom("Part::Feature"):
                        edges = ob.Shape.Edges
                        if (not self.maxEdges) or (len(edges) <=
                                                   self.maxEdges):
                            for e in edges:
                                if isinstance(e.Curve, Part.Line):
                                    np = self.getPerpendicular(e, point)
                                    if not DraftGeomUtils.isPtOnEdge(np, e):
                                        if (np.sub(point)
                                            ).Length < self.radius:
                                            if self.isEnabled('extension'):
                                                if np != e.Vertexes[0].Point:
                                                    if self.tracker:
                                                        self.tracker.setCoords(
                                                            np)
                                                        self.tracker.setMarker(
                                                            self.
                                                            mk['extension'])
                                                        self.tracker.on()
                                                    if self.extLine:
                                                        self.extLine.p1(
                                                            e.Vertexes[0].Point
                                                        )
                                                        self.extLine.p2(np)
                                                        self.extLine.on()
                                                    self.setCursor('extension')
                                                    return np, Part.Line(
                                                        e.Vertexes[0].Point,
                                                        np).toShape()
                                        else:
                                            if self.isEnabled('parallel'):
                                                if last:
                                                    ve = DraftGeomUtils.vec(e)
                                                    if not DraftVecUtils.isNull(
                                                            ve):
                                                        de = Part.Line(
                                                            last, last.add(
                                                                ve)).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(
                                                                'parallel')
                                                            return np, de
        return point, eline
Ejemplo n.º 50
0
def scale(objectslist,
          scale=App.Vector(1, 1, 1),
          center=App.Vector(0, 0, 0),
          copy=False):
    """scale(objects, scale, [center], copy)

    Scales the objects contained in objects (that can be a list of objects or
    an object) of the given  around given center.

    Parameters
    ----------
    objectlist : list

    scale : Base.Vector
        Scale factors defined by a given vector (in X, Y, Z directions).

    objectlist : Base.Vector
        Center of the scale operation.

    copy : bool
        If copy is True, the actual objects are not scaled, but copies
        are created instead.

    Return
    ----------
    The objects (or their copies) are returned.
    """
    if not isinstance(objectslist, list):
        objectslist = [objectslist]
    newobjlist = []
    for obj in objectslist:
        if copy:
            newobj = make_copy.make_copy(obj)
        else:
            newobj = obj
        if hasattr(obj, 'Shape'):
            scaled_shape = obj.Shape.copy()
            m = App.Matrix()
            m.move(center.negative())
            m.scale(scale.x, scale.y, scale.z)
            m.move(center)
            scaled_shape = scaled_shape.transformGeometry(m)
        if utils.get_type(obj) == "Rectangle":
            p = []
            for v in scaled_shape.Vertexes:
                p.append(v.Point)
            pl = obj.Placement.copy()
            pl.Base = p[0]
            diag = p[2].sub(p[0])
            bb = p[1].sub(p[0])
            bh = p[3].sub(p[0])
            nb = DraftVecUtils.project(diag, bb)
            nh = DraftVecUtils.project(diag, bh)
            if obj.Length < 0: l = -nb.Length
            else: l = nb.Length
            if obj.Height < 0: h = -nh.Length
            else: h = nh.Length
            newobj.Length = l
            newobj.Height = h
            tr = p[0].sub(obj.Shape.Vertexes[0].Point)  # unused?
            newobj.Placement = pl
        elif utils.get_type(obj) == "Wire" or utils.get_type(obj) == "BSpline":
            for index, point in enumerate(newobj.Points):
                scale_vertex(newobj, index, scale, center)
        elif hasattr(obj, 'Shape'):
            newobj.Shape = scaled_shape
        elif hasattr(obj, "Position"):
            d = obj.Position.sub(center)
            newobj.Position = center.add(
                App.Vector(d.x * scale.x, d.y * scale.y, d.z * scale.z))
        elif hasattr(obj, "Placement"):
            d = obj.Placement.Base.sub(center)
            newobj.Placement.Base = center.add(
                App.Vector(d.x * scale.x, d.y * scale.y, d.z * scale.z))
            if hasattr(obj, "Height"):
                obj.setExpression('Height', None)
                obj.Height = obj.Height * scale.y
            if hasattr(obj, "Width"):
                obj.setExpression('Width', None)
                obj.Width = obj.Width * scale.x
            if hasattr(obj, "XSize"):
                obj.setExpression('XSize', None)
                obj.XSize = obj.XSize * scale.x
            if hasattr(obj, "YSize"):
                obj.setExpression('YSize', None)
                obj.YSize = obj.YSize * scale.y
        if obj.ViewObject and hasattr(obj.ViewObject, "FontSize"):
            obj.ViewObject.FontSize = obj.ViewObject.FontSize * scale.y

        if copy:
            gui_utils.format_object(newobj, obj)
        newobjlist.append(newobj)
    if copy and utils.get_param("selectBaseObjects", False):
        gui_utils.select(objectslist)
    else:
        gui_utils.select(newobjlist)
    if len(newobjlist) == 1: return newobjlist[0]
    return newobjlist
Ejemplo n.º 51
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
Ejemplo n.º 52
0
    def cut(self,cutplane):
        "Cuts through the shapes with a given cut plane and builds section faces"
        if DEBUG: print "\n\n======> Starting cut\n\n"
        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 = DraftVecUtils.project(dv,self.wp.u).Length
                    um = max(um,um1)
                    vm1 = DraftVecUtils.project(dv,self.wp.v).Length
                    vm = max(vm,vm1)
                    wm1 = DraftVecUtils.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 = DraftVecUtils.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:])
                            print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
                            if DraftGeomUtils.isCoplanar([f,cutface]):
                                print "COPLANAR"
                                sections.append([f,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
        if DEBUG: print "\n\n======> Finished cut\n\n"
Ejemplo n.º 53
0
    def numericRadius(self, rad):
        """Validate the entry radius in the user interface.

        This function is called by the toolbar or taskpanel interface
        when a valid radius has been entered in the input field.
        """
        import DraftGeomUtils
        plane = App.DraftWorkingPlane

        if self.step == 1:
            self.rad = rad
            if len(self.tangents) == 2:
                cir = DraftGeomUtils.circleFrom2tan1rad(
                    self.tangents[0], self.tangents[1], rad)
                if self.center:
                    _c = DraftGeomUtils.findClosestCircle(self.center, cir)
                    self.center = _c.Center
                else:
                    self.center = cir[-1].Center
            elif self.tangents and self.tanpoints:
                cir = DraftGeomUtils.circleFrom1tan1pt1rad(
                    self.tangents[0], self.tanpoints[0], rad)
                if self.center:
                    _c = DraftGeomUtils.findClosestCircle(self.center, cir)
                    self.center = _c.Center
                else:
                    self.center = cir[-1].Center
            if self.closedCircle:
                self.drawArc()
            else:
                self.step = 2
                self.arctrack.setCenter(self.center)
                self.ui.labelRadius.setText(translate("draft", "Start angle"))
                self.ui.radiusValue.setToolTip(
                    translate("draft", "Start angle"))
                self.linetrack.p1(self.center)
                self.linetrack.on()
                self.ui.radiusValue.setText("")
                self.ui.radiusValue.setFocus()
                _msg(translate("draft", "Pick start angle"))
        elif self.step == 2:
            self.ui.labelRadius.setText(translate("draft", "Aperture angle"))
            self.ui.radiusValue.setToolTip(translate("draft",
                                                     "Aperture angle"))
            self.firstangle = math.radians(rad)
            if DraftVecUtils.equals(plane.axis, App.Vector(1, 0, 0)):
                u = App.Vector(0, self.rad, 0)
            else:
                u = DraftVecUtils.scaleTo(
                    App.Vector(1, 0, 0).cross(plane.axis), self.rad)
            urotated = DraftVecUtils.rotate(u, math.radians(rad), plane.axis)
            self.arctrack.setStartAngle(self.firstangle)
            self.step = 3
            self.ui.radiusValue.setText("")
            self.ui.radiusValue.setFocus()
            _msg(translate("draft", "Pick aperture angle"))
        else:
            self.updateAngle(rad)
            self.angle = math.radians(rad)
            self.step = 4
            self.drawArc()
Ejemplo n.º 54
0
 def pos(self, p):
     self.trans.translation.setValue(DraftVecUtils.tup(p))
Ejemplo n.º 55
0
def get_dxf(obj, direction=None):
    """Return a DXF entity from the given object.

    If direction is given, the object is projected in 2D.
    """
    plane = None
    result = ""
    if (obj.isDerivedFrom("Drawing::View")
            or obj.isDerivedFrom("TechDraw::DrawView")):
        if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
            for o in obj.Source.Group:
                result += get_dxf(o, obj.Direction)
        else:
            result += get_dxf(obj.Source, obj.Direction)
        return result

    if direction and isinstance(direction, App.Vector):
        if direction != App.Vector(0, 0, 0):
            plane = WorkingPlane.Plane()
            plane.alignToPointAndAxis(App.Vector(0, 0, 0), direction)

    if utils.get_type(obj) in ("Dimension", "LinearDimension"):
        p1 = _get_proj(obj.Start, plane=plane)
        p2 = _get_proj(obj.End, plane=plane)
        p3 = _get_proj(obj.Dimline, plane=plane)
        result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n"
        result += "10\n"+str(p3.x)+"\n20\n"+str(p3.y)+"\n30\n"+str(p3.z)+"\n"
        result += "13\n"+str(p1.x)+"\n23\n"+str(p1.y)+"\n33\n"+str(p1.z)+"\n"
        result += "14\n"+str(p2.x)+"\n24\n"+str(p2.y)+"\n34\n"+str(p2.z)+"\n"

    elif utils.get_type(obj) == "Annotation":
        # Only for App::Annotation
        p = _get_proj(obj.Position, plane=plane)
        count = 0
        for t in obj.LabeLtext:
            result += "0\nTEXT\n8\n0\n62\n0\n"
            result += "10\n"
            result += str(p.x) + "\n20\n"
            result += str(p.y + count) + "\n30\n"
            result += str(p.z) + "\n"
            result += "40\n1\n"
            result += "1\n" + str(t) + "\n"
            result += "7\nSTANDARD\n"
            count += 1

    elif hasattr(obj, 'Shape'):
        # TODO do this the Draft way, for ex. using polylines and rectangles
        if not direction:
            direction = App.Vector(0, 0, -1)

        if DraftVecUtils.isNull(direction):
            direction = App.Vector(0, 0, -1)

        try:
            d = TechDraw.projectToDXF(obj.Shape, direction)
        except Exception:
            # TODO: trap only specific exception.
            # Impossible to generate DXF from Shape? Which exception is throw?
            _wrn("get_dxf: "
                 "unable to project '{}' to {}".format(obj.Label, direction))
        else:
            result += d
    else:
        _wrn("get_dxf: unsupported object, '{}'".format(obj.Label))

    return result
Ejemplo n.º 56
0
    def drawArc(self):
        """Actually draw the arc object."""
        rot, sup, pts, fil = self.getStrings()
        if self.closedCircle:
            try:
                # The command to run is built as a series of text strings
                # to be committed through the `draftutils.todo.ToDo` class.
                if utils.getParam("UsePartPrimitives", False):
                    # Insert a Part::Primitive object
                    _base = DraftVecUtils.toString(self.center)
                    _cmd = 'FreeCAD.ActiveDocument.'
                    _cmd += 'addObject("Part::Circle", "Circle")'
                    _cmd_list = [
                        'circle = ' + _cmd, 'circle.Radius = ' + str(self.rad),
                        'pl = FreeCAD.Placement()', 'pl.Rotation.Q = ' + rot,
                        'pl.Base = ' + _base, 'circle.Placement = pl',
                        'Draft.autogroup(circle)',
                        'FreeCAD.ActiveDocument.recompute()'
                    ]
                    self.commit(translate("draft", "Create Circle (Part)"),
                                _cmd_list)
                else:
                    # Insert a Draft circle
                    Gui.addModule("Draft")
                    _base = DraftVecUtils.toString(self.center)
                    _cmd = 'Draft.makeCircle'
                    _cmd += '('
                    _cmd += 'radius=' + str(self.rad) + ', '
                    _cmd += 'placement=pl, '
                    _cmd += 'face=' + fil + ', '
                    _cmd += 'support=' + sup
                    _cmd += ')'
                    _cmd_list = [
                        'pl=FreeCAD.Placement()', 'pl.Rotation.Q=' + rot,
                        'pl.Base=' + _base, 'circle = ' + _cmd,
                        'Draft.autogroup(circle)',
                        'FreeCAD.ActiveDocument.recompute()'
                    ]
                    self.commit(translate("draft", "Create Circle"), _cmd_list)
            except Exception:
                _err("Draft: error delaying commit")
        else:
            # Not a closed circle, therefore a circular arc
            sta = math.degrees(self.firstangle)
            end = math.degrees(self.firstangle + self.angle)
            if end < sta:
                sta, end = end, sta
            while True:
                if sta > 360:
                    sta = sta - 360
                elif end > 360:
                    end = end - 360
                else:
                    break
            try:
                Gui.addModule("Draft")
                if utils.getParam("UsePartPrimitives", False):
                    # Insert a Part::Primitive object
                    _base = DraftVecUtils.toString(self.center)
                    _cmd = 'FreeCAD.ActiveDocument.'
                    _cmd += 'addObject("Part::Circle", "Circle")'
                    _cmd_list = [
                        'circle = ' + _cmd, 'circle.Radius = ' + str(self.rad),
                        'circle.Angle0 = ' + str(sta),
                        'circle.Angle1 = ' + str(end),
                        'pl = FreeCAD.Placement()', 'pl.Rotation.Q = ' + rot,
                        'pl.Base = ' + _base, 'circle.Placement = pl',
                        'Draft.autogroup(circle)',
                        'FreeCAD.ActiveDocument.recompute()'
                    ]
                    self.commit(translate("draft", "Create Arc (Part)"),
                                _cmd_list)
                else:
                    # Insert a Draft circle
                    _base = DraftVecUtils.toString(self.center)
                    _cmd = 'Draft.makeCircle'
                    _cmd += '('
                    _cmd += 'radius=' + str(self.rad) + ', '
                    _cmd += 'placement=pl, '
                    _cmd += 'face=' + fil + ', '
                    _cmd += 'startangle=' + str(sta) + ', '
                    _cmd += 'endangle=' + str(end) + ', '
                    _cmd += 'support=' + sup
                    _cmd += ')'
                    _cmd_list = [
                        'pl = FreeCAD.Placement()', 'pl.Rotation.Q = ' + rot,
                        'pl.Base = ' + _base, 'circle = ' + _cmd,
                        'Draft.autogroup(circle)',
                        'FreeCAD.ActiveDocument.recompute()'
                    ]
                    self.commit(translate("draft", "Create Arc"), _cmd_list)
            except Exception:
                _err("Draft: error delaying commit")

        # Finalize full circle or cirular arc
        self.finish(cont=True)
Ejemplo n.º 57
0
    def action(self, arg):
        """Handle the 3D scene events.

        This is installed as an EventCallback in the Inventor view.

        Parameters
        ----------
        arg: dict
            Dictionary with strings that indicates the type of event received
            from the 3D view.
        """
        import DraftGeomUtils
        plane = App.DraftWorkingPlane

        if arg["Type"] == "SoKeyboardEvent":
            if arg["Key"] == "ESCAPE":
                self.finish()
        elif arg["Type"] == "SoLocation2Event":  # mouse movement detection
            self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg)
            # this is to make sure radius is what you see on screen
            if self.center and DraftVecUtils.dist(self.point, self.center) > 0:
                viewdelta = DraftVecUtils.project(self.point.sub(self.center),
                                                  plane.axis)
                if not DraftVecUtils.isNull(viewdelta):
                    self.point = self.point.add(viewdelta.negative())
            if self.step == 0:  # choose center
                if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                    if not self.altdown:
                        self.altdown = True
                        self.ui.switchUi(True)
                    else:
                        if self.altdown:
                            self.altdown = False
                            self.ui.switchUi(False)
            elif self.step == 1:  # choose radius
                if len(self.tangents) == 2:
                    cir = DraftGeomUtils.circleFrom2tan1pt(
                        self.tangents[0], self.tangents[1], self.point)
                    _c = DraftGeomUtils.findClosestCircle(self.point, cir)
                    self.center = _c.Center
                    self.arctrack.setCenter(self.center)
                elif self.tangents and self.tanpoints:
                    cir = DraftGeomUtils.circleFrom1tan2pt(
                        self.tangents[0], self.tanpoints[0], self.point)
                    _c = DraftGeomUtils.findClosestCircle(self.point, cir)
                    self.center = _c.Center
                    self.arctrack.setCenter(self.center)
                if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                    if not self.altdown:
                        self.altdown = True
                    if info:
                        ob = self.doc.getObject(info['Object'])
                        num = int(info['Component'].lstrip('Edge')) - 1
                        ed = ob.Shape.Edges[num]
                        if len(self.tangents) == 2:
                            cir = DraftGeomUtils.circleFrom3tan(
                                self.tangents[0], self.tangents[1], ed)
                            cl = DraftGeomUtils.findClosestCircle(
                                self.point, cir)
                            self.center = cl.Center
                            self.rad = cl.Radius
                            self.arctrack.setCenter(self.center)
                        else:
                            self.rad = self.center.add(
                                DraftGeomUtils.findDistance(
                                    self.center, ed).sub(self.center)).Length
                    else:
                        self.rad = DraftVecUtils.dist(self.point, self.center)
                else:
                    if self.altdown:
                        self.altdown = False
                    self.rad = DraftVecUtils.dist(self.point, self.center)
                self.ui.setRadiusValue(self.rad, "Length")
                self.arctrack.setRadius(self.rad)
                self.linetrack.p1(self.center)
                self.linetrack.p2(self.point)
                self.linetrack.on()
            elif (self.step == 2):  # choose first angle
                currentrad = DraftVecUtils.dist(self.point, self.center)
                if currentrad != 0:
                    angle = DraftVecUtils.angle(plane.u,
                                                self.point.sub(self.center),
                                                plane.axis)
                else:
                    angle = 0
                self.linetrack.p2(
                    DraftVecUtils.scaleTo(self.point.sub(self.center),
                                          self.rad).add(self.center))
                self.ui.setRadiusValue(math.degrees(angle), unit="Angle")
                self.firstangle = angle
            else:
                # choose second angle
                currentrad = DraftVecUtils.dist(self.point, self.center)
                if currentrad != 0:
                    angle = DraftVecUtils.angle(plane.u,
                                                self.point.sub(self.center),
                                                plane.axis)
                else:
                    angle = 0
                self.linetrack.p2(
                    DraftVecUtils.scaleTo(self.point.sub(self.center),
                                          self.rad).add(self.center))
                self.updateAngle(angle)
                self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle")
                self.arctrack.setApertureAngle(self.angle)

            gui_tool_utils.redraw3DView()

        elif arg["Type"] == "SoMouseButtonEvent":  # mouse click
            if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1":
                if self.point:
                    if self.step == 0:  # choose center
                        if not self.support:
                            gui_tool_utils.getSupport(arg)
                            (self.point, ctrlPoint,
                             info) = gui_tool_utils.getPoint(self, arg)
                        if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                            snapped = self.view.getObjectInfo(
                                (arg["Position"][0], arg["Position"][1]))
                            if snapped:
                                ob = self.doc.getObject(snapped['Object'])
                                num = int(
                                    snapped['Component'].lstrip('Edge')) - 1
                                ed = ob.Shape.Edges[num]
                                self.tangents.append(ed)
                                if len(self.tangents) == 2:
                                    self.arctrack.on()
                                    self.ui.radiusUi()
                                    self.step = 1
                                    self.ui.setNextFocus()
                                    self.linetrack.on()
                                    _msg(translate("draft", "Pick radius"))
                        else:
                            if len(self.tangents) == 1:
                                self.tanpoints.append(self.point)
                            else:
                                self.center = self.point
                                self.node = [self.point]
                                self.arctrack.setCenter(self.center)
                                self.linetrack.p1(self.center)
                                self.linetrack.p2(
                                    self.view.getPoint(arg["Position"][0],
                                                       arg["Position"][1]))
                            self.arctrack.on()
                            self.ui.radiusUi()
                            self.step = 1
                            self.ui.setNextFocus()
                            self.linetrack.on()
                            _msg(translate("draft", "Pick radius"))
                            if self.planetrack:
                                self.planetrack.set(self.point)
                    elif self.step == 1:  # choose radius
                        if self.closedCircle:
                            self.drawArc()
                        else:
                            self.ui.labelRadius.setText(
                                translate("draft", "Start angle"))
                            self.ui.radiusValue.setToolTip(
                                translate("draft", "Start angle"))
                            self.ui.radiusValue.setText(
                                U.Quantity(0, U.Angle).UserString)
                            self.linetrack.p1(self.center)
                            self.linetrack.on()
                            self.step = 2
                            _msg(translate("draft", "Pick start angle"))
                    elif self.step == 2:  # choose first angle
                        self.ui.labelRadius.setText(
                            translate("draft", "Aperture angle"))
                        self.ui.radiusValue.setToolTip(
                            translate("draft", "Aperture angle"))
                        self.step = 3
                        # scale center->point vector for proper display
                        # u = DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad) obsolete?
                        self.arctrack.setStartAngle(self.firstangle)
                        _msg(translate("draft", "Pick aperture"))
                    else:  # choose second angle
                        self.step = 4
                        self.drawArc()
Ejemplo n.º 58
0
def findDistance(point, edge, strict=False):
    """Return a vector from the point to its closest point on the edge.

    If `strict` is `True`, the vector will be returned
    only if its endpoint lies on the `edge`.
    Edge can also be a list of 2 points.
    """
    if isinstance(point, App.Vector):
        if isinstance(edge, list):
            segment = edge[1].sub(edge[0])
            chord = edge[0].sub(point)
            norm = segment.cross(chord)
            perp = segment.cross(norm)
            dist = DraftVecUtils.project(chord, perp)

            if not dist:
                return None

            newpoint = point.add(dist)

            if dist.Length == 0:
                return None

            if strict:
                s1 = newpoint.sub(edge[0])
                s2 = newpoint.sub(edge[1])
                if (s1.Length <= segment.Length
                        and s2.Length <= segment.Length):
                    return dist
                else:
                    return None
            else:
                return dist

        elif geomType(edge) == "Line":
            segment = vec(edge)
            chord = edge.Vertexes[0].Point.sub(point)
            norm = segment.cross(chord)
            perp = segment.cross(norm)
            dist = DraftVecUtils.project(chord, perp)

            if not dist:
                return None

            newpoint = point.add(dist)

            if (dist.Length == 0):
                return None

            if strict:
                s1 = newpoint.sub(edge.Vertexes[0].Point)
                s2 = newpoint.sub(edge.Vertexes[-1].Point)
                if (s1.Length <= segment.Length
                        and s2.Length <= segment.Length):
                    return dist
                else:
                    return None
            else:
                return dist

        elif geomType(edge) == "Circle":
            ve1 = edge.Vertexes[0].Point
            if len(edge.Vertexes) > 1:
                ve2 = edge.Vertexes[-1].Point
            else:
                ve2 = None
            center = edge.Curve.Center
            segment = center.sub(point)

            if segment.Length == 0:
                return None

            ratio = (segment.Length - edge.Curve.Radius) / segment.Length
            dist = segment.multiply(ratio)
            newpoint = App.Vector.add(point, dist)

            if dist.Length == 0:
                return None

            if strict and ve2:
                ang1 = DraftVecUtils.angle(ve1.sub(center))
                ang2 = DraftVecUtils.angle(ve2.sub(center))
                angpt = DraftVecUtils.angle(newpoint.sub(center))
                if ((angpt <= ang2 and angpt >= ang1)
                        or (angpt <= ang1 and angpt >= ang2)):
                    return dist
                else:
                    return None
            else:
                return dist

        elif (geomType(edge) == "BSplineCurve"
              or geomType(edge) == "BezierCurve"):
            try:
                pr = edge.Curve.parameter(point)
                np = edge.Curve.value(pr)
                dist = np.sub(point)
            except Part.OCCError:
                print(
                    "DraftGeomUtils: Unable to get curve parameter "
                    "for point ", point)
                return None
            else:
                return dist
        else:
            print("DraftGeomUtils: Couldn't project point")
            return None
    else:
        print("DraftGeomUtils: Couldn't project point")
        return None
Ejemplo n.º 59
0
    def execute(self, obj):
        "creates the panel shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        # base tests
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if not obj.Base.Mesh.isSolid():
                    return
        else:
            if obj.Length.Value:
                length = obj.Length.Value
            else:
                return
            if obj.Width.Value:
                width = obj.Width.Value
            else:
                return
        if obj.Thickness.Value:
            thickness = obj.Thickness.Value
        else:
            if not obj.Base:
                return
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if not obj.Base.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if obj.Base:
            p = FreeCAD.Placement(obj.Base.Placement)
            normal = p.Rotation.multVec(Vector(0, 0, 1))
            normal = normal.multiply(thickness)
            base = obj.Base.Shape.copy()
            if base.Solids:
                pass
            elif base.Faces:
                self.BaseProfile = base
                self.ExtrusionVector = normal
                base = base.extrude(normal)
            elif base.Wires:
                closed = True
                for w in base.Wires:
                    if not w.isClosed():
                        closed = False
                if closed:
                    base = ArchCommands.makeFace(base.Wires)
                    self.BaseProfile = base
                    self.ExtrusionVector = normal
                    base = base.extrude(normal)
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if obj.Base.Mesh.isSolid():
                    if obj.Base.Mesh.countComponents() == 1:
                        sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                        if sh.isClosed() and sh.isValid() and sh.Solids:
                            base = sh
        else:
            normal = Vector(0, 0, 1).multiply(thickness)
            self.ExtrusionVector = normal
            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.makePolygon([v1, v2, v3, v4, v1])
            base = Part.Face(base)
            self.BaseProfile = base
            base = base.extrude(self.ExtrusionVector)

        if base and (obj.Sheets > 1) and normal and thickness:
            bases = [base]
            for i in range(1, obj.Sheets):
                n = FreeCAD.Vector(normal).normalize().multiply(i * thickness)
                b = base.copy()
                b.translate(n)
                bases.append(b)
            base = Part.makeCompound(bases)

        if base and normal and hasattr(obj, "Offset"):
            if obj.Offset.Value:
                v = DraftVecUtils.scaleTo(normal, obj.Offset.Value)
                base.translate(v)

        # process subshapes
        base = self.processSubShapes(obj, base, pl)

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            translate("Arch", "Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Ejemplo n.º 60
0
 def tostr(val):
     return str(round(val, DraftVecUtils.precision()))