Exemplo n.º 1
0
    def projectPointOld(self, p, direction=None):
        """Project a point onto the plane. OBSOLETE.

        Parameters
        ----------
        p : Base::Vector3
            The point to project.
        direction : Base::Vector3, optional
            The unit vector that indicates the direction of projection.

            It defaults to `None`, which then uses the `plane.axis` (normal)
            value, meaning that the point is projected perpendicularly
            to the plane.

        Returns
        -------
        Base::Vector3
            The projected point,
            or the original point if the angle between the `direction`
            and the `plane.axis` is 90 degrees.
        """
        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)
Exemplo n.º 2
0
    def alignToPointAndAxis_SVG(self, point, axis, offset):
        # based on cases table
        self.doc = FreeCAD.ActiveDocument
        self.axis = axis
        self.axis.normalize()
        ref_vec = Vector(0.0, 1.0, 0.0)

        if ((abs(axis.x) > abs(axis.y)) and (abs(axis.y) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "Case new"

        elif ((abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x))):
            ref_vec = Vector(1.0, 0.0, 0.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "Y>Z, View Y"

        elif ((abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "ehem. XY, Case XY"

        elif ((abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y))):
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "X>Z, View X"

        elif ((abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x))):
            ref_vec = Vector(1.0, 0., 0.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "Y>X, Case YZ"

        else:
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis)
            #projcase = "else"

        #spat_vec = self.u.cross(self.v)
        #spat_res = spat_vec.dot(axis)
        #FreeCAD.Console.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")

        offsetVector = Vector(axis)
        offsetVector.multiply(offset)
        self.position = point.add(offsetVector)
        self.weak = False
Exemplo n.º 3
0
    def alignToPointAndAxis_SVG(self, point, axis, offset):
        # based on cases table
        self.doc = FreeCAD.ActiveDocument
        self.axis = axis;
        self.axis.normalize()
        ref_vec = Vector(0.0, 1.0, 0.0)

        if ((abs(axis.x) > abs(axis.y)) and (abs(axis.y) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "Case new"
        
        elif ((abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x))):
            ref_vec = Vector(1.0, 0.0, 0.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "Y>Z, View Y"

        elif ((abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "ehem. XY, Case XY"

        elif ((abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y))):
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "X>Z, View X"

        elif ((abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x))):
            ref_vec = Vector(1.0, 0., 0.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "Y>X, Case YZ"

        else:
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            #projcase = "else"

        #spat_vec = self.u.cross(self.v)
        #spat_res = spat_vec.dot(axis)
        #FreeCAD.Console.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")
        
        offsetVector = Vector(axis); offsetVector.multiply(offset)
        self.position = point.add(offsetVector)
        self.weak = False
Exemplo n.º 4
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)
Exemplo n.º 5
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)
Exemplo n.º 6
0
    def alignToPointAndAxis(self, point, axis, offset=0, upvec=None):
        """Align the working plane to a point and an axis (vector).

        Set `v` as the cross product of `axis` with `(1, 0, 0)` or `+X`,
        and `u` as `v` rotated -90 degrees around the `axis`.
        Also set `weak` to `False`.

        Parameters
        ----------
        point : Base::Vector3
            The new `position` of the plane, adjusted by
            the `offset`.
        axis : Base::Vector3
            A vector whose unit vector will be used as the new `axis`
            of the plane.
            If it is very close to the `X` or `-X` axes,
            it will use this axis exactly, and will adjust `u` and `v`
            to `+Y` and `+Z`, or `-Y` and `+Z`, respectively.
        offset : float, optional
            Defaults to zero. A value which will be used to offset
            the plane in the direction of its `axis`.
        upvec : Base::Vector3, optional
            Defaults to `None`.
            If it exists, its unit vector will be used as `v`,
            and will set `u` as the cross product of `v` with `axis`.
        """
        self.doc = FreeCAD.ActiveDocument
        self.axis = axis
        self.axis.normalize()
        if axis.getAngle(Vector(1, 0, 0)) < 0.00001:
            self.axis = Vector(1, 0, 0)
            self.u = Vector(0, 1, 0)
            self.v = Vector(0, 0, 1)
        elif axis.getAngle(Vector(-1, 0, 0)) < 0.00001:
            self.axis = Vector(-1, 0, 0)
            self.u = Vector(0, -1, 0)
            self.v = Vector(0, 0, 1)
        elif upvec:
            self.v = upvec
            self.v.normalize()
            self.u = self.v.cross(self.axis)
        else:
            self.v = axis.cross(Vector(1, 0, 0))
            self.v.normalize()
            self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis)
        offsetVector = Vector(axis)
        offsetVector.multiply(offset)
        self.position = point.add(offsetVector)
        self.weak = False
Exemplo n.º 7
0
    def GetOrthoVector(self, line, distance, side=''):
        """
        Return the orthogonal vector pointing toward the indicated side at the
        provided position.  Defaults to left-hand side
        """

        _dir = 1.0

        _side = side.lower()

        if _side in ['r', 'rt', 'right']:
            _dir = -1.0

        start = line.Start
        end = line.End

        if (start is None) or (end is None):
            return None, None

        _delta = end.sub(start).normalize()
        _left = Vector(-_delta.y, _delta.x, 0.0)

        _coord = start.add(_delta.multiply(distance))

        return _coord, _left.multiply(_dir)
Exemplo n.º 8
0
def get_ortho_vector(line_dict, distance, side=''):
    """
    Return the orthogonal vector pointing toward the indicated side at the
    provided position.  Defaults to left-hand side
    """

    _dir = 1.0

    _side = side.lower()

    if _side in ['r', 'rt', 'right']:
        _dir = -1.0

    start = line_dict['Start']
    end = line_dict['End']

    if (start is None) or (end is None):
        return None, None

    _delta = end.sub(start).normalize()
    _left = Vector(-_delta.y, _delta.x, 0.0)

    _coord = get_coordinate(line_dict['Start'], line_dict['BearingIn'],
                            distance)

    return _coord, _left.multiply(_dir)
Exemplo n.º 9
0
 def Activated(self):
     sel = FreeCADGui.Selection.getSelection()
     if not sel:
         FreeCAD.Console.PrintMessage("Error: no meshes selected\n")
         return
     for obj in FreeCADGui.Selection.getSelection():
         if "Mesh" not in obj.PropertiesList:
             FreeCAD.Console.PrintMessage(
                 "Error: " + obj.Name +
                 " is not an object of type 'Mesh::Feature'\n")
             continue
         # export facets
         arrows = []
         condName = obj.Label.replace(" ", "_")
         for facet in obj.Mesh.Facets:
             center = Vector(0.0, 0.0, 0.0)
             avgSideLen = 0.0
             for j, point in enumerate(facet.Points):
                 # 'point' is a tuple, transform in vector
                 center = center + Vector(point)
                 # get side length
                 side = Vector(facet.Points[(j + 1) % 3]) - Vector(point)
                 avgSideLen += side.Length
                 # calculate the reference point
                 # (there should be a better way to divide a vector by a scalar..)
             center.multiply(1.0 / len(facet.Points))
             # and now move along the normal, proportional to the average facet dimension
             scaledNormal = Vector(facet.Normal)
             scaledNormal.multiply(avgSideLen / len(facet.Points))
             refpoint = center + scaledNormal
             arrows.append(self.make_arrow__(center, refpoint))
         # add the vector normals visualization to the view
         # Note: could also use Part.show(normals) but in this case we could
         # not give the (permanent) name to the object, only change the label afterwards
         if len(arrows) > 40:
             step = len(arrows) / float(40)
             arrows = [arrows[int(x * step)] for x in range(40)]
         normals = Part.makeCompound(arrows)
         normalobj = FreeCAD.ActiveDocument.addObject(
             "Part::Feature", obj.Name + "_normals")
         normalobj.Shape = normals
 def alignToPointAndAxis(self, point, axis, offset, upvec=None):
     self.doc = FreeCAD.ActiveDocument
     self.axis = axis;
     self.axis.normalize()
     if (DraftVecUtils.equals(axis, Vector(1,0,0))):
         self.u = Vector(0,1,0)
         self.v = Vector(0,0,1)
     elif (DraftVecUtils.equals(axis, Vector(-1,0,0))):
         self.u = Vector(0,-1,0)
         self.v = Vector(0,0,1)
     elif upvec:
         self.v = upvec
         self.v.normalize()
         self.u = self.v.cross(self.axis)
     else:
         self.v = axis.cross(Vector(1,0,0))
         self.v.normalize()
         self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis)
     offsetVector = Vector(axis); offsetVector.multiply(offset)
     self.position = point.add(offsetVector)
     self.weak = False
Exemplo n.º 11
0
 def alignToPointAndAxis(self, point, axis, offset=0, upvec=None):
     self.doc = FreeCAD.ActiveDocument
     self.axis = axis;
     self.axis.normalize()
     if (DraftVecUtils.equals(axis, Vector(1,0,0))):
         self.u = Vector(0,1,0)
         self.v = Vector(0,0,1)
     elif (DraftVecUtils.equals(axis, Vector(-1,0,0))):
         self.u = Vector(0,-1,0)
         self.v = Vector(0,0,1)
     elif upvec:
         self.v = upvec
         self.v.normalize()
         self.u = self.v.cross(self.axis)
     else:
         self.v = axis.cross(Vector(1,0,0))
         self.v.normalize()
         self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis)
     offsetVector = Vector(axis); offsetVector.multiply(offset)
     self.position = point.add(offsetVector)
     self.weak = False
Exemplo n.º 12
0
    def makePortShape(self,n1,n2):
        ''' Compute a port shape given:

            'n1': start node position (FreeCAD.Vector)
            'n2': end node position (FreeCAD.Vector)
    '''
        # do not accept coincident nodes
        if (n2-n1).Length < EMFHPORT_LENTOL:
            return None
        line = Part.makeLine(n1, n2)
        # calculate arrow head base
        direction = n1 - n2
        length = direction.Length
        base = Vector(direction)
        base.normalize()
        base.multiply(length * 0.8)
        base = n2 + base
        # radius2 is calculated for a fixed arrow head angle tan(15deg)=0.27
        cone = Part.makeCone(0.2 * length * 0.27, 0.0, 0.2 * length, base, direction, 360)
        # add the compound representing the arrow
        arrow = Part.makeCompound([line, cone])
        return arrow   
Exemplo n.º 13
0
    def mouse_event(self, arg):
        """
        SoLocation2Event callback
        """

        #force refresh the view matrix if dragging
        self.mouse.update(arg, ViewState().view.getCursorPos())

        if MouseState().shiftDown:

            _dist = MouseState().vector.Length

            if not _dist:
                return

            _vec = Vector(MouseState().vector).normalize()

            MouseState().set_mouse_position(MouseState().last_coord.add(
                _vec.multiply(_dist * 0.10)))
Exemplo n.º 14
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         if not isinstance(data[0],list):
             # multifuses not considered here
             return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     if obj.Normal == Vector(0,0,0):
         normal = Vector(0,0,1)
     else:
         normal = Vector(obj.Normal)
     base = None
     placement = None
     basewires = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Face > 0:
                     if len(obj.Base.Shape.Faces) >= obj.Face:
                         face = obj.Base.Shape.Faces[obj.Face-1]
                         # this wall is based on a specific face of its base object
                         normal = face.normalAt(0,0)
                         if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                             normal.multiply(width)
                             base = face.extrude(normal)
                             if obj.Align == "Center":
                                 base.translate(normal.negative().multiply(0.5))
                             elif obj.Align == "Right":
                                 base.translate(normal.negative())
                         else:
                             normal.multiply(height)
                             base = face.extrude(normal)
                         base,placement = self.rebase(base)
                         return (base,normal,placement)
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                 elif obj.Base.Shape.Wires:
                     basewires = obj.Base.Shape.Wires
                 elif len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 if basewires and width:
                     baseface = None
                     for wire in basewires:
                         e = wire.Edges[0]
                         if isinstance(e.Curve,Part.Circle):
                             dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                         else:
                             dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                         if not DraftVecUtils.isNull(dvec):
                             dvec.normalize()
                         sh = None
                         if obj.Align == "Left":
                             dvec.multiply(width)
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Right":
                             dvec.multiply(width)
                             dvec = dvec.negative()
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Center":
                             dvec.multiply(width/2)
                             w1 = DraftGeomUtils.offsetWire(wire,dvec)
                             dvec = dvec.negative()
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             sh = DraftGeomUtils.bind(w1,w2)
                         if sh:
                             sh.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(sh)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                     if baseface:
                         base,placement = self.rebase(baseface)
     else:
         l2 = length/2 or 0.5
         w2 = width/2 or 0.5
         v1 = Vector(-l2,-w2,0)
         v2 = Vector(l2,-w2,0)
         v3 = Vector(l2,w2,0)
         v4 = Vector(-l2,w2,0)
         base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         placement = FreeCAD.Placement()
     if base and placement:
         extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Exemplo n.º 15
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/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 = 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)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Exemplo n.º 16
0
def makeSegShape(n1, n2, width, height, ww):
    ''' Compute a segment shape given:

        'n1': start node position (Vector)
        'n2': end node position (Vector)
        'width': segment width
        'height': segment height
        'ww': cross-section direction (along width)
        
        Returns the created Shape
'''
    # do not accept coincident nodes
    if (n2 - n1).Length < EMFHSEGMENT_LENTOL:
        return None
    # vector along length
    wl = n2 - n1
    # calculate the vector along the height
    wh = (ww.cross(wl))
    # if cross-section is not defined, by default the width vector
    # is assumed to lie in x-y plane perpendicular to the length.
    # If the length direction is parallel to the z-axis, then
    # the width is assumed along the x-axis.
    # The same is done if 'ww' has been defined parallel to 'wl'
    if ww.Length < EMFHSEGMENT_LENTOL or wh.Length < EMFHSEGMENT_LENTOL:
        # if length parallel to the z-axis (note that getAngle() always returns a value
        # between 0 and 180)
        angle = wl.getAngle(Vector(0, 0, 1)) * FreeCAD.Units.Radian
        if angle < EMFHSEGMENT_PARTOL or angle > 180 - EMFHSEGMENT_PARTOL:
            ww = Vector(1, 0, 0)
        else:
            ww = (wl.cross(Vector(0, 0, 1))).normalize()
        # and re-calculate 'wh' since we changed 'ww'
        wh = (ww.cross(wl))
    # normalize the freshly calculated 'wh'
    wh.normalize()
    # copy ww as the multiply() method changes the vector on which is called
    wwHalf = Vector(ww)
    # must normalize. We don't want to touch 'ww', as this is user's defined
    wwHalf.normalize()
    wwHalf.multiply(width / 2)
    # copy wh as the multiply() method changes the vector on which is called
    whHalf = Vector(wh)
    whHalf.multiply(height / 2)
    # calculate the vertexes
    v11 = n1 - wwHalf - whHalf
    v12 = n1 + wwHalf - whHalf
    v13 = n1 + wwHalf + whHalf
    v14 = n1 - wwHalf + whHalf
    v21 = n2 - wwHalf - whHalf
    v22 = n2 + wwHalf - whHalf
    v23 = n2 + wwHalf + whHalf
    v24 = n2 - wwHalf + whHalf
    # now make faces
    # front
    poly = Part.makePolygon([v11, v12, v13, v14, v11])
    face1 = Part.Face(poly)
    # back
    poly = Part.makePolygon([v21, v24, v23, v22, v21])
    face2 = Part.Face(poly)
    # left
    poly = Part.makePolygon([v11, v14, v24, v21, v11])
    face3 = Part.Face(poly)
    # right
    poly = Part.makePolygon([v12, v22, v23, v13, v12])
    face4 = Part.Face(poly)
    # top
    poly = Part.makePolygon([v14, v13, v23, v24, v14])
    face5 = Part.Face(poly)
    # bottom
    poly = Part.makePolygon([v11, v21, v22, v12, v11])
    face6 = Part.Face(poly)
    # create a shell. Does not need to be solid.
    segShell = Part.makeShell([face1, face2, face3, face4, face5, face6])
    return segShell
Exemplo n.º 17
0
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""

        if hasattr(obj,"IfcRole"):
            role = obj.IfcRole
        else:
            role = obj.Role
        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
        normal = None
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        base = None
        placement = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                            normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                            normal = placement.inverse().Rotation.multVec(normal)
                    elif obj.Base.Shape.Wires:
                        baseface = None
                        if hasattr(obj,"FaceMaker"):
                            if obj.FaceMaker != "None":
                                try:
                                    baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                                except:
                                    FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                    return None
                                if len(baseface.Faces) > 1:
                                    baseface = baseface.Faces[0]
                                normal = baseface.normalAt(0,0)
                        if not baseface:
                            for w in obj.Base.Shape.Wires:
                                if not w.isClosed():
                                    p0 = w.OrderedVertexes[0].Point
                                    p1 = w.OrderedVertexes[-1].Point
                                    if p0 != p1:
                                        e = Part.Line(p0,p1).toShape()
                                        w.add(e)
                                w.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(w)
                                if baseface:
                                    baseface = baseface.fuse(f)
                                else:
                                    baseface = f
                                    normal = f.normalAt(0,0)
                        base,placement = self.rebase(baseface)
                        normal = placement.inverse().Rotation.multVec(normal)
                    elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                        # closed edge
                        w = Part.Wire(obj.Base.Shape.Edges[0])
                        baseface = Part.Face(w)
                        base,placement = self.rebase(baseface)
        elif length and width and height:
            if (length > height) and (role != "Slab"):
                h2 = height/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(0,-w2,-h2)
                v4 = Vector(0,-w2,h2)
                v3 = Vector(0,w2,h2)
                v2 = Vector(0,w2,-h2)
            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)
            import Part
            baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            base,placement = self.rebase(baseface)
        if base and placement:
            if obj.Normal.Length:
                normal = Vector(obj.Normal)
                normal = placement.inverse().Rotation.multVec(normal)
            if not normal:
                normal = Vector(0,0,1)
            if not normal.Length:
                normal = Vector(0,0,1)
            extrusion = normal
            if (length > height) and (role != "Slab"):
                if length:
                    extrusion = normal.multiply(length)
            else:
                if height:
                    extrusion = normal.multiply(height)
            return (base,extrusion,placement)
        return None
Exemplo n.º 18
0
    def execute(self, obj):
        "creates the structure shape"

        import Part, DraftGeomUtils

        # getting default values
        length = 1
        width = 1
        height = 1
        if hasattr(obj, "Length"):
            if obj.Length.Value:
                length = obj.Length.Value
        if hasattr(obj, "Width"):
            if obj.Width.Value:
                width = obj.Width.Value
        if hasattr(obj, "Height"):
            if obj.Height.Value:
                height = obj.Height.Value
            else:
                for p in obj.InList:
                    if Draft.getType(p) == "Floor":
                        if p.Height.Value:
                            height = p.Height.Value

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if hasattr(obj, "Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(
                                obj.Base.Shape.copy())
                        except:
                            FreeCAD.Console.PrintError(
                                translate(
                                    "Arch",
                                    "Error: The base shape couldn't be extruded along this tool object"
                                ))
                            return
                if not base:
                    if obj.Normal == Vector(0, 0, 0):
                        p = FreeCAD.Placement(obj.Base.Placement)
                        normal = p.Rotation.multVec(Vector(0, 0, 1))
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        self.BaseProfile = base
                        self.ExtrusionVector = normal
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            base = Part.Face(base.Wires[0])
                            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:
            if obj.Normal == Vector(0, 0, 0):
                if length > height:
                    normal = Vector(1, 0, 0).multiply(length)
                else:
                    normal = Vector(0, 0, 1).multiply(height)
            else:
                normal = Vector(obj.Normal).multiply(height)
            self.ExtrusionVector = normal
            if length > height:
                h2 = height / 2 or 0.5
                w2 = width / 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 = 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)

        base = self.processSubShapes(obj, base, pl)

        if base:
            # applying axes
            pts = self.getAxisPoints(obj)
            apl = self.getAxisPlacement(obj)
            if pts:
                fsh = []
                for i in range(len(pts)):
                    if hasattr(obj, "Exclude"):
                        if i in obj.Exclude:
                            continue
                    sh = base.copy()
                    if apl:
                        sh.Placement.Rotation = apl.Rotation
                    sh.translate(pts[i])
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)

            # finalizing
            else:
                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
Exemplo n.º 19
0
    def execute(self,obj):
        "creates the structure shape"
        
        import Part, DraftGeomUtils
        
        # getting default values
        length = 1
        width = 1
        height = 1
        if hasattr(obj,"Length"):
            if obj.Length.Value:
                length = obj.Length.Value
        if hasattr(obj,"Width"):
            if obj.Width.Value:
                width = obj.Width.Value
        if hasattr(obj,"Height"):
            if obj.Height.Value:
                height = obj.Height.Value
            else:
                for p in obj.InList:
                    if Draft.getType(p) == "Floor":
                        if p.Height.Value:
                            height = p.Height.Value

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if hasattr(obj,"Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(obj.Base.Shape.copy())
                        except:
                            FreeCAD.Console.PrintError(translate("Arch","Error: The base shape couldn't be extruded along this tool object"))
                            return
                if not base:
                    if obj.Normal == Vector(0,0,0):
                        p = FreeCAD.Placement(obj.Base.Placement)
                        normal = p.Rotation.multVec(Vector(0,0,1))
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        self.BaseProfile = base
                        self.ExtrusionVector = normal
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            base = Part.Face(base.Wires[0])
                            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:
            if obj.Normal == Vector(0,0,0):
                if length > height:
                    normal = Vector(1,0,0).multiply(length)
                else:
                    normal = Vector(0,0,1).multiply(height)
            else:
                normal = Vector(obj.Normal).multiply(height)
            self.ExtrusionVector = normal
            if length > height:
                h2 = height/2 or 0.5
                w2 = width/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 = 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)
            
        base = self.processSubShapes(obj,base,pl)
            
        if base:
            # applying axes
            pts = self.getAxisPoints(obj)
            apl = self.getAxisPlacement(obj)
            if pts:
                fsh = []
                for i in range(len(pts)):
                    if hasattr(obj,"Exclude"):
                        if i in obj.Exclude:
                            continue
                    sh = base.copy()
                    if apl:
                        sh.Placement.Rotation = apl.Rotation
                    sh.translate(pts[i])
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)

            # finalizing
            else:
                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
Exemplo n.º 20
0
    def execute(self,obj):
        "creates the structure shape"

        import Part, DraftGeomUtils
        
        if self.clone(obj):
            return

        normal,length,width,height = self.getDefaultValues(obj)

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if not obj.Base.Shape.isValid():
                    if not obj.Base.Shape.Solids:
                        # let pass invalid objects if they have solids...
                        return
                if hasattr(obj,"Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(obj.Base.Shape.copy())
                        except Part.OCCError:
                            FreeCAD.Console.PrintError(translate("Arch","Error: The base shape couldn't be extruded along this tool object"))
                            return
                if not base:
                    if not height:
                        return
                    if obj.Normal == Vector(0,0,0):
                        p = FreeCAD.Placement(obj.Base.Placement)
                        normal = p.Rotation.multVec(normal)
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            try:
                                base = Part.Face(base.Wires[0])
                                base = base.extrude(normal)
                            except Part.OCCError:
                                FreeCAD.Console.PrintError(obj.Label+" : "+str(translate("Arch","Unable to extrude the base shape\n")))
                                return

            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 and (not sh.isNull()):
                            base = sh
                        else:
                            FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
                            obj.Base.ViewObject.show()
        else:
            base = self.getProfiles(obj)
            if base:
                if length > height:
                    normal = normal.multiply(length)
                else:
                    normal = normal.multiply(height)
                base = Part.Face(base[0])
                base = base.extrude(normal)

        base = self.processSubShapes(obj,base,pl)
        self.applyShape(obj,base,pl)
Exemplo n.º 21
0
    def createGeometry(self, obj):
        import Part, DraftGeomUtils

        # getting default values
        height = width = length = 1
        if hasattr(obj, "Length"):
            if obj.Length:
                length = obj.Length
        if hasattr(obj, "Width"):
            if obj.Width:
                width = obj.Width
        if hasattr(obj, "Height"):
            if obj.Height:
                height = obj.Height

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Normal == Vector(0, 0, 0):
                    p = FreeCAD.Placement(obj.Base.Placement)
                    normal = p.Rotation.multVec(Vector(0, 0, 1))
                else:
                    normal = Vector(obj.Normal)
                normal = normal.multiply(height)
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1):
                    if base.Wires[0].isClosed():
                        base = Part.Face(base.Wires[0])
                        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:
            if obj.Normal == Vector(0, 0, 0):
                normal = Vector(0, 0, 1)
            else:
                normal = Vector(obj.Normal)
            normal = normal.multiply(height)
            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)
            base = base.extrude(normal)

        base = self.processSubShapes(obj, base)

        if base:
            # applying axes
            pts = self.getAxisPoints(obj)
            apl = self.getAxisPlacement(obj)
            if pts:
                fsh = []
                for i in range(len(pts)):
                    if hasattr(obj, "Exclude"):
                        if i in obj.Exclude:
                            continue
                    sh = base.copy()
                    if apl:
                        sh.Placement.Rotation = apl.Rotation
                    sh.translate(pts[i])
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)

            # finalizing

            else:
                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(
                                    str(
                                        translate(
                                            "Arch",
                                            "Couldn't compute the wall shape"))
                                )
                                return
                            base = base.removeSplitter()
                            obj.Shape = base
                if not DraftGeomUtils.isNull(pl):
                    obj.Placement = pl
Exemplo n.º 22
0
    def createGeometry(self, obj):

        import Part
        from draftlibs import fcgeo

        flat = False
        if hasattr(obj.ViewObject, "DisplayMode"):
            flat = (obj.ViewObject.DisplayMode == "Flat 2D")

        def getbase(wire):
            "returns a full shape from a base wire"
            dvec = fcgeo.vec(wire.Edges[0]).cross(normal)
            dvec.normalize()
            if obj.Align == "Left":
                dvec = dvec.multiply(obj.Width)
                w2 = fcgeo.offsetWire(wire, dvec)
                sh = fcgeo.bind(wire, w2)
            elif obj.Align == "Right":
                dvec = dvec.multiply(obj.Width)
                dvec = fcvec.neg(dvec)
                w2 = fcgeo.offsetWire(wire, dvec)
                sh = fcgeo.bind(wire, w2)
            elif obj.Align == "Center":
                dvec = dvec.multiply(obj.Width / 2)
                w1 = fcgeo.offsetWire(wire, dvec)
                dvec = fcvec.neg(dvec)
                w2 = fcgeo.offsetWire(wire, dvec)
                sh = fcgeo.bind(w1, w2)
            # fixing self-intersections
            sh.fix(0.1, 0, 1)
            if height and (not flat):
                norm = Vector(normal).multiply(height)
                sh = sh.extrude(norm)
            return sh

        pl = obj.Placement

        # getting default values
        height = normal = None
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0, 0, 0):
            normal = Vector(0, 0, 1)
        else:
            normal = Vector(obj.Normal)

        # computing shape
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    if height:
                        norm = normal.multiply(height)
                        base = base.extrude(norm)
                elif base.Wires:
                    temp = None
                    for wire in obj.Base.Shape.Wires:
                        sh = getbase(wire)
                        if temp:
                            temp = temp.oldFuse(sh)
                        else:
                            temp = sh
                    base = temp
        else:
            if obj.Length == 0:
                return
            v1 = Vector(0, 0, 0)
            v2 = Vector(obj.Length, 0, 0)
            w = Part.Wire(Part.Line(v1, v2).toShape())
            base = getbase(w)

        for app in obj.Additions:
            base = base.oldFuse(app.Shape)
            app.ViewObject.hide()  #to be removed
        for hole in obj.Subtractions:
            if Draft.getType(hole) == "Window":
                # window
                if hole.Base and obj.Width:
                    f = self.getSubVolume(hole.Base, obj.Width)
                    base = base.cut(f)
            elif Draft.isClone(hole, "Window"):
                if hole.Objects[0].Base and obj.Width:
                    f = self.getSubVolume(hole.Objects[0].Base, obj.Width,
                                          hole.Placement.Base)
                    base = base.cut(f)
            elif hasattr(obj, "Shape"):
                base = base.cut(hole.Shape)
                hole.ViewObject.hide()  # to be removed
        obj.Shape = base
        if not fcgeo.isNull(pl):
            obj.Placement = pl
Exemplo n.º 23
0
    def getExtrusionData(self,obj):

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

                    if self.basewires and width:
                        if (len(self.basewires) == 1) and layers:
                            self.basewires = [self.basewires[0] for l in layers]
                        layeroffset = 0
                        baseface = None
                        for i,wire in enumerate(self.basewires):
                            e = wire.Edges[0]
                            if isinstance(e.Curve,Part.Circle):
                                dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                            else:
                                dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                            if not DraftVecUtils.isNull(dvec):
                                dvec.normalize()
                            sh = None
                            if obj.Align == "Left":
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Right":
                                dvec = dvec.negative()
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Center":
                                if layers:
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w1 = DraftGeomUtils.offsetWire(wire,d1)
                                    layeroffset += layers[i]
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w2 = DraftGeomUtils.offsetWire(wire,d1)
                                else:
                                    dvec.multiply(width/2)
                                    w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                    dvec = dvec.negative()
                                    w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                sh = DraftGeomUtils.bind(w1,w2)
                            if sh:
                                sh.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(sh)
                                if baseface:
                                    if layers:
                                        baseface.append(f)
                                    else:
                                        baseface = baseface.fuse(f)
                                        # baseface = baseface.removeSplitter()
                                        s = DraftGeomUtils.removeSplitter(baseface)
                                        if s:
                                            baseface = s
                                else:
                                    if layers:
                                        baseface = [f]
                                    else:
                                        baseface = f
                        if baseface:
                            base,placement = self.rebase(baseface)
        else:
            if layers:
                totalwidth = sum(layers)
                offset = 0
                base = []
                for l in layers:
                    l2 = length/2 or 0.5
                    w1 = -totalwidth/2 + offset
                    w2 = w1 + l
                    v1 = Vector(-l2,w1,0)
                    v2 = Vector(l2,w1,0)
                    v3 = Vector(l2,w2,0)
                    v4 = Vector(-l2,w2,0)
                    base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])))
                    offset += l
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
                base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            placement = FreeCAD.Placement()
        if base and placement:
            extrusion = normal.multiply(height)
            return (base,extrusion,placement)
        return None
Exemplo n.º 24
0
 def projectPoint(self, p, direction=None):
     '''project point onto plane, default direction is orthogonal'''
     if not direction: direction = self.axis
     t = Vector(direction)
     t.multiply(self.offsetToPoint(p, direction))
     return p.add(t)
Exemplo n.º 25
0
def export_mesh(filename,
                meshobj=None,
                isDiel=False,
                showNormals=False,
                folder=DEF_FOLDER):
    '''Export mesh in FasterCap format as conductor or dielectric interface
    
    'filename' is the name of the export file
    'meshobj' must be a Mesh::Feature object
    'isDiel' specifies if the mesh is a dielectric, so the function will add 
        a reference point to each panel to indicate which is the external side (outside)
    'showNormals' will add a compound object composed by a set of arrows showing the 
        normal direction for each panel
    'folder' is the folder in which 'filename' will be saved
    
    Example:
    mymeshGui = Gui.ActiveDocument.Mesh
    mymeshObj = mymeshGui.Object
    export_mesh("mymesh.txt", meshobj=mymeshObj, folder="C:/temp")
'''

    # if no valid mesh was passed
    if meshobj == None:
        return
    elif meshobj.TypeId != "Mesh::Feature":
        FreeCAD.Console.PrintMessage(
            "Error: 'meshobj' is not an object of type 'Mesh::Feature'")
        return

    if not os.path.isdir(folder):
        os.mkdir(folder)

    with open(folder + os.sep + filename, 'w') as fid:
        # write the preamble
        if isDiel == True:
            fid.write("0 dielectric definition file for mesh '" +
                      meshobj.Label)
        else:
            fid.write("0 conductor definition file for mesh '" + meshobj.Label)
        fid.write("' created using FreeCAD's ElectroMagnetic workbench\n")
        fid.write(
            "* see http://www.freecad.org and http://www.fastfieldsolvers.com\n"
        )
        fid.write("\n")
        # export facets
        arrows = []
        condName = meshobj.Label.replace(" ", "_")
        for facet in meshobj.Mesh.Facets:
            if len(facet.Points) == 3:
                fid.write("T " + condName)
            elif len(facet.Points) == 4:
                fid.write("Q " + condName)
            else:
                FreeCAD.Console.PrintMessage(
                    "Unforeseen number of mesh facet points: " +
                    len(facet.Points) + ", skipping facet")
                continue
            center = Vector(0.0, 0.0, 0.0)
            avgSideLen = 0.0
            for j, point in enumerate(facet.Points):
                fid.write(" ")
                for i in range(3):
                    fid.write(" " + str(point[i]))
                if isDiel == True or showNormals == True:
                    # 'point' is a tuple, transform in vector
                    center = center + Vector(point)
                    # get side length
                    side = Vector(facet.Points[(j + 1) % 3]) - Vector(point)
                    avgSideLen += side.Length
            if isDiel == True or showNormals == True:
                # calculate the reference point
                # (there should be a better way to divide a vector by a scalar..)
                center.multiply(1.0 / len(facet.Points))
                # and now move along the normal, proportional to the average facet dimension
                scaledNormal = Vector(facet.Normal)
                scaledNormal.multiply(avgSideLen / len(facet.Points))
                refpoint = center + scaledNormal
                if isDiel == True:
                    fid.write(" ")
                    for i in range(3):
                        fid.write(" " + str(refpoint[i]))
            fid.write("\n")
            if showNormals == True:
                arrows.append(make_arrow(center, refpoint))

        if showNormals == True:
            # add the vector normals visualization to the view
            # Note: could also use Part.show(normals) but in this case we could
            # not give the (permanent) name to the object, only change the label afterwards
            normals = Part.makeCompound(arrows)
            normalobj = FreeCAD.ActiveDocument.addObject(
                "Part::Feature", "Normals")
            normalobj.Shape = normals

    fid.closed
Exemplo n.º 26
0
def export_faces(filename,
                 isDiel=False,
                 name="",
                 showNormals=False,
                 forceMesh=False,
                 folder=DEF_FOLDER):
    '''Export faces in FasterCap format as conductor or dielectric interface
    
    The function operates on the selection. The selection can be a face, a compound or a solid.
    'filename' is the name of the export file
    'isDiel' specifies if the mesh is a dielectric, so the function will add 
        a reference point to each panel to indicate which is the external side (outside)
    'name' is the name of the conductor created in the file. If not specified, defaults
        to the label of the first element in the selection set
    'forceMesh' force the meshing of all faces, even if they could be exported non-meshed
        (triangular or quadrilateral faces).
    'showNormals' will add a compound object composed by a set of arrows showing the 
        normal direction for each panel
    'folder' is the folder in which 'filename' will be saved
    
    Example:
    export_faces("mymesh.txt", folder="C:/temp")
'''
    # get selection
    sel = FreeCADGui.Selection.getSelection()
    # if no valid selection was passed
    if sel == None:
        return

    if name == "":
        condName = sel[0].Label.replace(" ", "_")
    else:
        condName = name

    # scan objects in selection and extract all faces
    faces = []
    facets = []
    for obj in sel:
        if obj.TypeId == "Mesh::Feature":
            facets.extend(obj.Mesh.Facets)
        else:
            if obj.Shape.ShapeType == "Face":
                faces.append(obj.Shape)
            elif obj.Shape.ShapeType == "Compound" or obj.Shape.ShapeType == "Solid":
                faces.extend(obj.Shape.Faces)
    # scan faces and find out which faces have more than 4 vertexes
    # TBD warning: should mesh also curve faces
    if forceMesh == False:
        facesComplex = [x for x in faces if len(x.Vertexes) >= 5]
        facesSimple = [x for x in faces if len(x.Vertexes) < 5]
    else:
        facesComplex = faces
        facesSimple = []
    # mesh complex faces
    doc = FreeCAD.ActiveDocument
    for face in facesComplex:
        mesh = doc.addObject("Mesh::Feature", "Mesh")
        mesh.Mesh = MeshPart.meshFromShape(Shape=face,
                                           Fineness=0,
                                           SecondOrder=0,
                                           Optimize=1,
                                           AllowQuad=0)
        facets.extend(mesh.Mesh.Facets)
    # now we have faces and facets. Uniform all
    panels = []
    for face in facesSimple:
        sortEdges = Part.__sortEdges__(face.Edges)
        # Point of a Vertex is a Vector, as well as Face.normalAt()
        points = [x.firstVertex().Point for x in sortEdges]
        panels.append([points, face.normalAt(0, 0)])
    for facet in facets:
        points = [Vector(x) for x in facet.Points]
        panels.append([points, Vector(facet.Normal)])

    if not os.path.isdir(folder):
        os.mkdir(folder)

    with open(folder + os.sep + filename, 'w') as fid:
        # write the preamble
        if isDiel == True:
            fid.write(
                "0 dielectric definition file for the following objects\n")
        else:
            fid.write(
                "0 conductor definition file for the following objects\n")
        for obj in sel:
            fid.write("* - " + obj.Label + "\n")
        fid.write("* created using FreeCAD's ElectroMagnetic workbench\n")
        fid.write(
            "* see http://www.freecad.org and http://www.fastfieldsolvers.com\n\n"
        )

        arrows = []
        # export faces
        for panel in panels:
            pointsNum = len(panel[0])
            if pointsNum == 3:
                fid.write("T " + condName)
            elif pointsNum == 4:
                fid.write("Q " + condName)
            else:
                FreeCAD.Console.PrintMessage(
                    "Unforeseen number of panel vertexes: " + pointsNum +
                    ", skipping panel")
                continue
            center = Vector(0.0, 0.0, 0.0)
            avgSideLen = 0.0
            for j, vertex in enumerate(panel[0]):
                fid.write(" ")
                for i in range(3):
                    fid.write(" " + str(vertex[i]))
                if isDiel == True or showNormals == True:
                    # 'point' is a tuple, transform in vector
                    center = center + vertex
                    # get side length
                    side = panel[0][(j + 1) % 3] - vertex
                    avgSideLen += side.Length
            if isDiel == True or showNormals == True:
                # calculate the reference point
                # (there should be a better way to divide a vector by a scalar..)
                center.multiply(1.0 / pointsNum)
                # and now move along the normal, proportional to the average facet dimension
                scaledNormal = panel[1]
                scaledNormal.multiply(avgSideLen / pointsNum)
                refpoint = center + scaledNormal
                if isDiel == True:
                    fid.write(" ")
                    for i in range(3):
                        fid.write(" " + str(refpoint[i]))
            fid.write("\n")
            if showNormals == True:
                arrows.append(make_arrow(center, refpoint))

    fid.closed

    if showNormals == True:
        # add the vector normals visualization to the view
        # Note: could also use Part.show(normals) but in this case we could
        # not give the (permanent) name to the object, only change the label afterwards
        normals = Part.makeCompound(arrows)
        normalobj = FreeCAD.ActiveDocument.addObject("Part::Feature",
                                                     "Normals")
        normalobj.Shape = normals
Exemplo n.º 27
0
    def createGeometry(self,obj):
        import Part, DraftGeomUtils
        
        # getting default values
        height = width = length = 1
        if hasattr(obj,"Length"):
            if obj.Length:
                length = obj.Length
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        if hasattr(obj,"Height"):
            if obj.Height:
                height = obj.Height

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Normal == Vector(0,0,0):
                    p = FreeCAD.Placement(obj.Base.Placement)
                    normal = p.Rotation.multVec(Vector(0,0,1))
                else:
                    normal = Vector(obj.Normal)
                normal = normal.multiply(height)
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1):
                    if base.Wires[0].isClosed():
                        base = Part.Face(base.Wires[0])
                        base = base.extrude(normal)                
        else:
            if obj.Normal == Vector(0,0,0):
                normal = Vector(0,0,1)
            else:
                normal = Vector(obj.Normal)
            normal = normal.multiply(height)
            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)
            base = base.extrude(normal)
            
        if base:
            # applying adds and subs
            if not base.isNull():
                for app in obj.Additions:
                    if hasattr(app,"Shape"):
                        if not app.Shape.isNull():
                            base = base.fuse(app.Shape)
                            app.ViewObject.hide() # to be removed
                for hole in obj.Subtractions:
                    if hasattr(hole,"Shape"):
                        if not hole.Shape.isNull():
                            base = base.cut(hole.Shape)
                            hole.ViewObject.hide() # to be removed

            # applying axes
            pts = self.getAxisPoints(obj)
            apl = self.getAxisPlacement(obj)
            if pts:
                fsh = []
                for i in range(len(pts)):
                    if hasattr(obj,"Exclude"):
                        if i in obj.Exclude:
                            continue
                    sh = base.copy()
                    if apl:
                        sh.Placement.Rotation = apl.Rotation
                    sh.translate(pts[i])
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)

            # finalizing
            else:
                if base:
                    if not base.isNull():
                        base = base.removeSplitter()
                        obj.Shape = base
                if not DraftGeomUtils.isNull(pl):
                    obj.Placement = pl
Exemplo n.º 28
0
    def createGeometry(self, obj):
        "builds the wall shape"

        if not obj.Base:
            return

        import Part, DraftGeomUtils

        flat = False
        if hasattr(obj.ViewObject, "DisplayMode"):
            flat = (obj.ViewObject.DisplayMode == "Flat 2D")

        width = 1.0
        if hasattr(obj, "Width"):
            if obj.Width:
                width = obj.Width

        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

        pl = obj.Placement

        # getting default values
        height = normal = None
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0, 0, 0):
            normal = Vector(0, 0, 1)
        else:
            normal = Vector(obj.Normal)

        # computing shape
        base = None
        if obj.Base.isDerivedFrom("Part::Feature"):
            if not obj.Base.Shape.isNull():
                if obj.Base.Shape.isValid():
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces and (not obj.ForceWire):
                        if height:
                            norm = normal.multiply(height)
                            base = base.extrude(norm)
                    elif base.Wires:
                        temp = None
                        for wire in obj.Base.Shape.Wires:
                            sh = getbase(wire)
                            if temp:
                                temp = temp.fuse(sh)
                            else:
                                temp = sh
                        base = temp
                    elif base.Edges:
                        wire = Part.Wire(base.Edges)
                        sh = getbase(wire)
                        if sh:
                            base = sh
                    else:
                        base = None
                        FreeCAD.Console.PrintError(
                            str(translate("Arch",
                                          "Error: Invalid base object")))

        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 and (
                            not sh.isNull()):
                        base = sh
                    else:
                        FreeCAD.Console.PrintWarning(
                            str(
                                translate("Arch",
                                          "This mesh is an invalid solid")))
                        obj.Base.ViewObject.show()

        if base:

            for app in obj.Additions:
                if Draft.getType(app) == "Window":
                    # window
                    if app.Base and obj.Width:
                        f = self.getSubVolume(app.Base, width)
                        if f:
                            base = base.cut(f)
                elif Draft.isClone(app, "Window"):
                    if app.Objects[0].Base and width:
                        f = self.getSubVolume(app.Objects[0].Base, width,
                                              app.Placement)
                        if f:
                            base = base.cut(f)
                elif app.isDerivedFrom("Part::Feature"):
                    if app.Shape:
                        if not app.Shape.isNull():
                            base = base.fuse(app.Shape)
                            app.ViewObject.hide()  #to be removed
            for hole in obj.Subtractions:
                if Draft.getType(hole) == "Window":
                    # window
                    if hole.Base and obj.Width:
                        f = self.getSubVolume(hole.Base, width)
                        if f:
                            base = base.cut(f)
                elif Draft.isClone(hole, "Window"):
                    if hole.Objects[0].Base and width:
                        f = self.getSubVolume(hole.Objects[0].Base, width,
                                              hole.Placement)
                        if f:
                            base = base.cut(f)
                elif hole.isDerivedFrom("Part::Feature"):
                    if hole.Shape:
                        if not hole.Shape.isNull():
                            base = base.cut(hole.Shape)
                            hole.ViewObject.hide()  # to be removed

            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            str(
                                translate("Arch",
                                          "Couldn't compute the wall shape")))
                        return
                    try:
                        base = base.removeSplitter()
                    except:
                        FreeCAD.Console.PrintError(
                            str(
                                translate(
                                    "Arch",
                                    "Error removing splitter from wall shape"))
                        )
                    obj.Shape = base
                    if not DraftGeomUtils.isNull(pl):
                        obj.Placement = pl
Exemplo n.º 29
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.Shape.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if hasattr(obj, "Normal"):
            if obj.Normal.Length > 0:
                normal = Vector(obj.Normal)
                normal.normalize()
                normal.multiply(thickness)
        baseprofile = None
        if obj.Base:
            base = obj.Base.Shape.copy()
            if not base.Solids:
                p = FreeCAD.Placement(obj.Base.Placement)
                if base.Faces:
                    baseprofile = base
                    if not normal:
                        normal = baseprofile.Faces[0].normalAt(
                            0, 0).multiply(thickness)
                    base = base.extrude(normal)
                elif base.Wires:
                    fm = False
                    if hasattr(obj, "FaceMaker"):
                        if obj.FaceMaker != "None":
                            try:
                                base = Part.makeFace(
                                    base.Wires,
                                    "Part::FaceMaker" + str(obj.FaceMaker))
                                fm = True
                            except:
                                FreeCAD.Console.PrintError(
                                    translate("Arch",
                                              "Facemaker returned an error") +
                                    "\n")
                                return
                    if not fm:
                        closed = True
                        for w in base.Wires:
                            if not w.isClosed():
                                closed = False
                        if closed:
                            baseprofile = ArchCommands.makeFace(base.Wires)
                            if not normal:
                                normal = baseprofile.normalAt(
                                    0, 0).multiply(thickness)
                            base = baseprofile.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:
            if not normal:
                normal = Vector(0, 0, 1).multiply(thickness)
            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])
            baseprofile = Part.Face(base)
            base = baseprofile.extrude(normal)

        if hasattr(obj, "Area"):
            if baseprofile:
                obj.Area = baseprofile.Area

        if hasattr(obj, "WaveLength"):
            if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value:
                # corrugated element
                bb = baseprofile.BoundBox
                bb.enlarge(bb.DiagonalLength)
                p1 = Vector(bb.getPoint(0).x, bb.getPoint(0).y, bb.Center.z)
                if obj.WaveType == "Curved":
                    p2 = p1.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    p3 = p2.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    e1 = Part.Arc(p1, p2, p3).toShape()
                    p4 = p3.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    p5 = p4.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    e2 = Part.Arc(p3, p4, p5).toShape()
                else:
                    if obj.WaveHeight.Value < obj.WaveLength.Value:
                        p2 = p1.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p4 = p3.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3, p4])
                        p5 = p4.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        p6 = p5.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p7 = p6.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p4, p5, p6, p7])
                    else:
                        p2 = p1.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3])
                        p4 = p3.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        p5 = p4.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p3, p4, p5])
                edges = [e1, e2]
                for i in range(int(bb.XLength / (obj.WaveLength.Value * 2))):
                    e1 = e1.copy()
                    e1.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    e2 = e2.copy()
                    e2.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    edges.extend([e1, e2])
                basewire = Part.Wire(edges)
                baseface = basewire.extrude(Vector(0, bb.YLength, 0))
                base = baseface.extrude(Vector(0, 0, thickness))
                rot = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), normal)
                base.rotate(bb.Center, rot.Axis, math.degrees(rot.Angle))
                if obj.WaveDirection.Value:
                    base.rotate(bb.Center, normal, obj.WaveDirection.Value)
                n1 = normal.negative().normalize().multiply(
                    obj.WaveHeight.Value * 2)
                self.vol = baseprofile.copy()
                self.vol.translate(n1)
                self.vol = self.vol.extrude(n1.negative().multiply(2))
                base = self.vol.common(base)
                base = base.removeSplitter()
                if not base:
                    FreeCAD.Console.PrintError(
                        transpate("Arch", "Error computing shape of ") +
                        obj.Label + "\n")
                    return False

        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
Exemplo n.º 30
0
def export_mesh(filename,
                meshobj=None,
                isDiel=False,
                folder=DEF_FOLDER,
                groupName=None):

    # check input in caller

    # add qui extension
    filename = filename + ".qui"

    if not os.path.isdir(folder):
        os.mkdir(folder)

    with open(os.path.join(folder, filename), 'w') as fid:
        if isDiel == True:
            fid.write("0 dielectric definition file for mesh '" +
                      meshobj.Label)
        else:
            fid.write("0 conductor definition file for mesh '" + meshobj.Label)
        fid.write(
            "' created using FreeCAD's Electromagnetic workbench script\n")
        fid.write("\n")

        # export faces
        # for dielectric, right now, assumes that any old normal surface vector can be chosen
        # as the reference vector, should be more mathematically rigorous than that
        refvectors = []
        if groupName is None:
            condName = meshobj.Label.replace(" ", "_")
        else:
            condName = groupName.replace(" ", "_")
        for facet in meshobj.Mesh.Facets:
            if len(facet.Points) == 3:
                fid.write("T " + condName)
            elif len(facet.Points) == 4:
                fid.write("Q " + condName)
            else:
                FreeCAD.Console.PrintError(
                    "Error: Unforseen number of mesh facet points: " +
                    len(facet.Points) + ", skipping facet\n")
                continue
            center = Vector(0.0, 0.0, 0.0)
            avgSideLen = 0.0
            for j, point in enumerate(facet.Points):
                fid.write(" ")
                fid.write(" ".join(map(str, point)))
                if isDiel == True:
                    for i in range(3):
                        center = center + Vector(point)
                        side = Vector(
                            facet.Points[(j + 1) % 3]) - Vector(point)
                        avgSideLen += side.Length
                    center.multiply(1.0 / len(facet.Points))
                    scaledNormal = Vector(facet.Normal)
                    scaledNormal.multiply(avgSideLen / len(facet.Points))
                    refpoint = center + scaledNormal
                    refvectors.append((refpoint.x, refpoint.y, refpoint.z))
            fid.write("\n")
        fid.close

        if isDiel == True:
            return random.choice(refvectors)
        else:
            return None
Exemplo n.º 31
0
    def getExtrusionData(self,obj):

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

                    if self.basewires and width:
                        if (len(self.basewires) == 1) and layers:
                            self.basewires = [self.basewires[0] for l in layers]
                        layeroffset = 0
                        baseface = None
                        for i,wire in enumerate(self.basewires):
                            e = wire.Edges[0]
                            if isinstance(e.Curve,Part.Circle):
                                dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                            else:
                                dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                            if not DraftVecUtils.isNull(dvec):
                                dvec.normalize()
                            sh = None
                            if obj.Align == "Left":
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Right":
                                dvec = dvec.negative()
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Center":
                                if layers:
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w1 = DraftGeomUtils.offsetWire(wire,d1)
                                    layeroffset += layers[i]
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w2 = DraftGeomUtils.offsetWire(wire,d1)
                                else:
                                    dvec.multiply(width/2)
                                    w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                    dvec = dvec.negative()
                                    w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                sh = DraftGeomUtils.bind(w1,w2)
                            if sh:
                                sh.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(sh)
                                if baseface:
                                    if layers:
                                        baseface.append(f)
                                    else:
                                        baseface = baseface.fuse(f)
                                        # baseface = baseface.removeSplitter()
                                        s = DraftGeomUtils.removeSplitter(baseface)
                                        if s:
                                            baseface = s
                                else:
                                    if layers:
                                        baseface = [f]
                                    else:
                                        baseface = f
                        if baseface:
                            base,placement = self.rebase(baseface)
        else:
            if layers:
                totalwidth = sum(layers)
                offset = 0
                base = []
                for l in layers:
                    l2 = length/2 or 0.5
                    w1 = -totalwidth/2 + offset
                    w2 = w1 + l
                    v1 = Vector(-l2,w1,0)
                    v2 = Vector(l2,w1,0)
                    v3 = Vector(l2,w2,0)
                    v4 = Vector(-l2,w2,0)
                    base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])))
                    offset += l
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
                base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            placement = FreeCAD.Placement()
        if base and placement:
            extrusion = normal.multiply(height)
            if placement.Rotation.Angle > 0:
                extrusion = placement.inverse().Rotation.multVec(extrusion)
            return (base,extrusion,placement)
        return None
Exemplo n.º 32
0
    def createGeometry(self,obj):
        import Part
        from draftlibs import fcgeo
        # getting default values
        height = normal = None
        if obj.Length:
            length = obj.Length
        else:
            length = 1
        width = 1
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)

        # creating shape
        pl = obj.Placement
        norm = normal.multiply(height)
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1) and base.Wires[0].isClosed():
                    base = Part.Face(base.Wires[0])
                    base = base.extrude(normal)                
        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.makePolygon([v1,v2,v3,v4,v1])
            base = Part.Face(base)
            base = base.extrude(normal)
        for app in obj.Additions:
            base = base.oldFuse(app.Shape)
            app.ViewObject.hide() # to be removed
        for hole in obj.Subtractions:
            cut = False
            if hasattr(hole,"Proxy"):
                if hasattr(hole.Proxy,"Subvolume"):
                    if hole.Proxy.Subvolume:
                        print "cutting subvolume",hole.Proxy.Subvolume
                        base = base.cut(hole.Proxy.Subvolume)
                        cut = True
            if not cut:
                if hasattr(obj,"Shape"):
                    base = base.cut(hole.Shape)
                    hole.ViewObject.hide() # to be removed
        if base:
            pts = self.getAxisPoints(obj)
            if pts:
                fsh = []
                for p in pts:
                    sh = base.copy()
                    sh.translate(p)
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)
            else:
                obj.Shape = base
            if not fcgeo.isNull(pl): obj.Placement = pl
Exemplo n.º 33
0
    def createGeometry(self,obj):
        import Part, DraftGeomUtils
        
        # getting default values
        height = width = length = 1
        if hasattr(obj,"Length"):
            if obj.Length:
                length = obj.Length
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        if hasattr(obj,"Height"):
            if obj.Height:
                height = obj.Height

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Normal == Vector(0,0,0):
                    p = FreeCAD.Placement(obj.Base.Placement)
                    normal = p.Rotation.multVec(Vector(0,0,1))
                else:
                    normal = Vector(obj.Normal)
                normal = normal.multiply(height)
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1):
                    if base.Wires[0].isClosed():
                        base = Part.Face(base.Wires[0])
                        base = base.extrude(normal)                
        else:
            if obj.Normal == Vector(0,0,0):
                normal = Vector(0,0,1)
            else:
                normal = Vector(obj.Normal)
            normal = normal.multiply(height)
            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)
            base = base.extrude(normal)
            
        if base:
            # applying adds and subs
            if not base.isNull():
                for app in obj.Additions:
                    if hasattr(app,"Shape"):
                        if not app.Shape.isNull():
                            base = base.fuse(app.Shape)
                            app.ViewObject.hide() # to be removed
                for hole in obj.Subtractions:
                    if hasattr(hole,"Shape"):
                        if not hole.Shape.isNull():
                            base = base.cut(hole.Shape)
                            hole.ViewObject.hide() # to be removed
            pts = self.getAxisPoints(obj)
            if pts:
                fsh = []
                for p in pts:
                    sh = base.copy()
                    sh.translate(p)
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)
            else:
                if base:
                    if not base.isNull():
                        base = base.removeSplitter()
                        obj.Shape = base
            if not DraftGeomUtils.isNull(pl):
                obj.Placement = pl
Exemplo n.º 34
0
	def projectPoint(self, p, direction=None):
		'''project point onto plane, default direction is orthogonal'''
		if not direction: direction = self.axis
		t = Vector(direction)
		t.multiply(self.offsetToPoint(p, direction))
		return p.add(t)
Exemplo n.º 35
0
    def createGeometry(self,obj):
        "builds the wall shape"

        if not obj.Base:
            return

        import Part, DraftGeomUtils

        flat = False
        if hasattr(obj.ViewObject,"DisplayMode"):
            flat = (obj.ViewObject.DisplayMode == "Flat 2D")

        width = 1.0
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        
        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
        
        pl = obj.Placement

        # getting default values
        height = normal = None
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)

        # computing shape
        base = None
        if obj.Base.isDerivedFrom("Part::Feature"):
            if not obj.Base.Shape.isNull():
                if obj.Base.Shape.isValid():
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces and (not obj.ForceWire):
                        if height:
                            norm = normal.multiply(height)
                            base = base.extrude(norm)
                    elif base.Wires:
                        temp = None
                        for wire in obj.Base.Shape.Wires:
                            sh = getbase(wire)
                            if temp:
                                temp = temp.fuse(sh)
                            else:
                                temp = sh
                        base = temp
                    elif base.Edges:
                        wire = Part.Wire(base.Edges)
                        sh = getbase(wire)
                        if sh:
                            base = sh
                    else:
                        base = None
                        FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object")))
                    
        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 and (not sh.isNull()):
                        base = sh
                    else:
                        FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
                        obj.Base.ViewObject.show()

        if base:

            for app in obj.Additions:
                if Draft.getType(app) == "Window":
                    # window
                    if app.Base and obj.Width:
                        f = self.getSubVolume(app.Base,width)
                        if f:
                            base = base.cut(f)
                elif Draft.isClone(app,"Window"):
                    if app.Objects[0].Base and width:
                        f = self.getSubVolume(app.Objects[0].Base,width,app.Placement)
                        if f:
                            base = base.cut(f)
                elif app.isDerivedFrom("Part::Feature"):
                    if app.Shape:
                        if not app.Shape.isNull():
                            base = base.fuse(app.Shape)
                            app.ViewObject.hide() #to be removed
            for hole in obj.Subtractions:
                if Draft.getType(hole) == "Window":
                    # window
                    if hole.Base and obj.Width:
                        f = self.getSubVolume(hole.Base,width)
                        if f:
                            base = base.cut(f)
                elif Draft.isClone(hole,"Window"):
                    if hole.Objects[0].Base and width:
                        f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement)
                        if f:
                            base = base.cut(f)                   
                elif hole.isDerivedFrom("Part::Feature"):
                    if hole.Shape:
                        if not hole.Shape.isNull():
                            base = base.cut(hole.Shape)
                            hole.ViewObject.hide() # to be removed

            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(str(translate("Arch","Couldn't compute the wall shape")))
                        return
                    try:
                        base = base.removeSplitter()
                    except:
                        FreeCAD.Console.PrintError(str(translate("Arch","Error removing splitter from wall shape")))
                    obj.Shape = base
                    if not DraftGeomUtils.isNull(pl):
                        obj.Placement = pl
Exemplo n.º 36
0
    def createGeometry(self, obj):
        import Part
        from draftlibs import fcgeo
        # getting default values
        height = normal = None
        if obj.Length:
            length = obj.Length
        else:
            length = 1
        if obj.Width:
            width = obj.Width
        else:
            width = 1
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0, 0, 0):
            normal = Vector(0, 0, 1)
        else:
            normal = Vector(obj.Normal)

        # creating shape
        pl = obj.Placement
        norm = normal.multiply(height)
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1) and base.Wires[0].isClosed():
                    base = Part.Face(base.Wires[0])
                    base = base.extrude(normal)
        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.makePolygon([v1, v2, v3, v4, v1])
            base = Part.Face(base)
            base = base.extrude(normal)
        for app in obj.Additions:
            base = base.oldFuse(app.Shape)
            app.ViewObject.hide()  # to be removed
        for hole in obj.Subtractions:
            cut = False
            if hasattr(hole, "Proxy"):
                if hasattr(hole.Proxy, "Subvolume"):
                    if hole.Proxy.Subvolume:
                        print "cutting subvolume", hole.Proxy.Subvolume
                        base = base.cut(hole.Proxy.Subvolume)
                        cut = True
            if not cut:
                if hasattr(obj, "Shape"):
                    base = base.cut(hole.Shape)
                    hole.ViewObject.hide()  # to be removed
        if base:
            pts = self.getAxisPoints(obj)
            if pts:
                fsh = []
                for p in pts:
                    sh = base.copy()
                    sh.translate(p)
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)
            else:
                obj.Shape = base
            if not fcgeo.isNull(pl): obj.Placement = pl
Exemplo n.º 37
0
    def alignToPointAndAxis_SVG(self, point, axis, offset=0):
        """Align the working plane to a point and an axis (vector).

        It aligns `u` and `v` based on the magnitude of the components
        of `axis`.
        Also set `weak` to `False`.

        Parameters
        ----------
        point : Base::Vector3
            The new `position` of the plane, adjusted by
            the `offset`.
        axis : Base::Vector3
            A vector whose unit vector will be used as the new `axis`
            of the plane.
            The magnitudes of the `x`, `y`, `z` components of the axis
            determine the orientation of `u` and `v` of the plane.
        offset : float, optional
            Defaults to zero. A value which will be used to offset
            the plane in the direction of its `axis`.

        Cases
        -----
        The `u` and `v` are always calculated the same

            * `u` is the cross product of the positive or negative of `axis`
              with a `reference vector`.
              ::
                  u = [+1|-1] axis.cross(ref_vec)
            * `v` is `u` rotated 90 degrees around `axis`.

        Whether the `axis` is positive or negative, and which reference
        vector is used, depends on the absolute values of the `x`, `y`, `z`
        components of the `axis` unit vector.

         #. If `x > y`, and `y > z`
             The reference vector is +Z
             ::
                 u = -1 axis.cross(+Z)
         #. If `y > z`, and `z >= x`
             The reference vector is +X.
             ::
                 u = -1 axis.cross(+X)
         #. If `y >= x`, and `x > z`
             The reference vector is +Z.
             ::
                 u = +1 axis.cross(+Z)
         #. If `x > z`, and `z >= y`
             The reference vector is +Y.
             ::
                 u = +1 axis.cross(+Y)
         #. If `z >= y`, and `y > x`
             The reference vector is +X.
             ::
                 u = +1 axis.cross(+X)
         #. otherwise
             The reference vector is +Y.
             ::
                 u = -1 axis.cross(+Y)
        """
        self.doc = FreeCAD.ActiveDocument
        self.axis = axis
        self.axis.normalize()
        ref_vec = Vector(0.0, 1.0, 0.0)

        if ((abs(axis.x) > abs(axis.y)) and (abs(axis.y) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "Case new"

        elif ((abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x))):
            ref_vec = Vector(1.0, 0.0, 0.0)
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "Y>Z, View Y"

        elif ((abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z))):
            ref_vec = Vector(0.0, 0., 1.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "ehem. XY, Case XY"

        elif ((abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y))):
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "X>Z, View X"

        elif ((abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x))):
            ref_vec = Vector(1.0, 0., 0.0)
            self.u = axis.cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "Y>X, Case YZ"

        else:
            self.u = axis.negative().cross(ref_vec)
            self.u.normalize()
            self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
            # projcase = "else"

        # spat_vec = self.u.cross(self.v)
        # spat_res = spat_vec.dot(axis)
        # FCC.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")

        offsetVector = Vector(axis)
        offsetVector.multiply(offset)
        self.position = point.add(offsetVector)
        self.weak = False
Exemplo n.º 38
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.Shape.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if hasattr(obj,"Normal"):
            if obj.Normal.Length > 0:
                normal = Vector(obj.Normal)
                normal.normalize()
                normal.multiply(thickness)
        baseprofile = None
        if obj.Base:
            base = obj.Base.Shape.copy()
            if not base.Solids:
                p = FreeCAD.Placement(obj.Base.Placement)
                if base.Faces:
                    baseprofile = base
                    if not normal:
                        normal = baseprofile.Faces[0].normalAt(0,0).multiply(thickness)
                    base = base.extrude(normal)
                elif base.Wires:
                    fm = False
                    if hasattr(obj,"FaceMaker"):
                        if obj.FaceMaker != "None":
                            try:
                                base = Part.makeFace(base.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                                fm = True
                            except:
                                FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                return
                    if not fm:
                        closed = True
                        for w in base.Wires:
                            if not w.isClosed():
                                closed = False
                        if closed:
                            baseprofile = ArchCommands.makeFace(base.Wires)
                            if not normal:
                                normal = baseprofile.normalAt(0,0).multiply(thickness)
                            base = baseprofile.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:
            if not normal:
                normal = Vector(0,0,1).multiply(thickness)
            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])
            baseprofile = Part.Face(base)
            base = baseprofile.extrude(normal)
            
        if hasattr(obj,"Area"):
            if baseprofile:
                obj.Area = baseprofile.Area
            
        if hasattr(obj,"WaveLength"):
            if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value:
                # corrugated element
                bb = baseprofile.BoundBox
                bb.enlarge(bb.DiagonalLength)
                p1 = Vector(bb.getPoint(0).x,bb.getPoint(0).y,bb.Center.z)
                if obj.WaveType == "Curved":
                    p2 = p1.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                    p3 = p2.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                    e1 = Part.Arc(p1,p2,p3).toShape()
                    p4 = p3.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                    p5 = p4.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                    e2 = Part.Arc(p3,p4,p5).toShape()
                else:
                    if obj.WaveHeight.Value < obj.WaveLength.Value:
                        p2 = p1.add(Vector(obj.WaveHeight.Value,0,obj.WaveHeight.Value))
                        p3 = p2.add(Vector(obj.WaveLength.Value-2*obj.WaveHeight.Value,0,0))
                        p4 = p3.add(Vector(obj.WaveHeight.Value,0,-obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1,p2,p3,p4])
                        p5 = p4.add(Vector(obj.WaveHeight.Value,0,-obj.WaveHeight.Value))
                        p6 = p5.add(Vector(obj.WaveLength.Value-2*obj.WaveHeight.Value,0,0))
                        p7 = p6.add(Vector(obj.WaveHeight.Value,0,obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p4,p5,p6,p7])
                    else:
                        p2 = p1.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                        p3 = p2.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1,p2,p3])
                        p4 = p3.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                        p5 = p4.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p3,p4,p5])
                edges = [e1,e2]
                for i in range(int(bb.XLength/(obj.WaveLength.Value*2))):
                    e1 = e1.copy()
                    e1.translate(Vector(obj.WaveLength.Value*2,0,0))
                    e2 = e2.copy()
                    e2.translate(Vector(obj.WaveLength.Value*2,0,0))
                    edges.extend([e1,e2])
                basewire = Part.Wire(edges)
                baseface = basewire.extrude(Vector(0,bb.YLength,0))
                base = baseface.extrude(Vector(0,0,thickness))
                rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),normal)
                base.rotate(bb.Center,rot.Axis,math.degrees(rot.Angle))
                if obj.WaveDirection.Value:
                    base.rotate(bb.Center,normal,obj.WaveDirection.Value)
                n1 = normal.negative().normalize().multiply(obj.WaveHeight.Value*2)
                self.vol = baseprofile.copy()
                self.vol.translate(n1)
                self.vol = self.vol.extrude(n1.negative().multiply(2))
                base = self.vol.common(base)
                base = base.removeSplitter()
                if not base:
                    FreeCAD.Console.PrintError(transpate("Arch","Error computing shape of ")+obj.Label+"\n")
                    return False

        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
Exemplo n.º 39
0
    def execute(self, obj):
        "creates the structure shape"

        import Part, DraftGeomUtils

        if self.clone(obj):
            return

        normal, length, width, height = self.getDefaultValues(obj)

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if not obj.Base.Shape.isValid():
                    if not obj.Base.Shape.Solids:
                        # let pass invalid objects if they have solids...
                        return
                if hasattr(obj, "Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(
                                obj.Base.Shape.copy())
                        except Part.OCCError:
                            FreeCAD.Console.PrintError(
                                translate(
                                    "Arch",
                                    "Error: The base shape couldn't be extruded along this tool object"
                                ))
                            return
                if not base:
                    if not height:
                        return
                    if obj.Normal == Vector(0, 0, 0):
                        if len(obj.Base.Shape.Faces) > 0:
                            normal = obj.Base.Shape.Faces[0].normalAt(.5, .5)
                        else:
                            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
                            if not normal:
                                normal = FreeCAD.Vector(0, 0, 1)
                            #p = FreeCAD.Placement(obj.Base.Placement)
                            #normal = p.Rotation.multVec(normal)
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            try:
                                base = Part.Face(base.Wires[0])
                                base = base.extrude(normal)
                            except Part.OCCError:
                                FreeCAD.Console.PrintError(
                                    obj.Label + " : " + str(
                                        translate(
                                            "Arch",
                                            "Unable to extrude the base shape\n"
                                        )))
                                return

            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 and (
                                not sh.isNull()):
                            base = sh
                        else:
                            FreeCAD.Console.PrintWarning(
                                str(
                                    translate(
                                        "Arch",
                                        "This mesh is an invalid solid")))
                            obj.Base.ViewObject.show()
        else:
            base = self.getProfiles(obj)
            if base:
                if length > height:
                    normal = normal.multiply(length)
                else:
                    normal = normal.multiply(height)
                base = Part.Face(base[0])
                base = base.extrude(normal)

        base = self.processSubShapes(obj, base, pl)
        self.applyShape(obj, base, pl)
Exemplo n.º 40
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
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/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 = 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)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Exemplo n.º 41
0
    def createGeometry(self,obj):
        import Part, DraftGeomUtils
        
        # getting default values
        height = width = length = 1
        if hasattr(obj,"Length"):
            if obj.Length:
                length = obj.Length
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        if hasattr(obj,"Height"):
            if obj.Height:
                height = obj.Height

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Normal == Vector(0,0,0):
                    p = FreeCAD.Placement(obj.Base.Placement)
                    normal = p.Rotation.multVec(Vector(0,0,1))
                else:
                    normal = Vector(obj.Normal)
                normal = normal.multiply(height)
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    base = base.extrude(normal)
                elif (len(base.Wires) == 1):
                    if base.Wires[0].isClosed():
                        base = Part.Face(base.Wires[0])
                        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:
            if obj.Normal == Vector(0,0,0):
                normal = Vector(0,0,1)
            else:
                normal = Vector(obj.Normal)
            normal = normal.multiply(height)
            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)
            base = base.extrude(normal)
            
        base = self.processSubShapes(obj,base)
            
        if base:
            # applying axes
            pts = self.getAxisPoints(obj)
            apl = self.getAxisPlacement(obj)
            if pts:
                fsh = []
                for i in range(len(pts)):
                    if hasattr(obj,"Exclude"):
                        if i in obj.Exclude:
                            continue
                    sh = base.copy()
                    if apl:
                        sh.Placement.Rotation = apl.Rotation
                    sh.translate(pts[i])
                    fsh.append(sh)
                    obj.Shape = Part.makeCompound(fsh)

            # finalizing
            
            else:
                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(str(translate("Arch","Couldn't compute the wall shape")))
                                return
                            base = base.removeSplitter()
                            obj.Shape = base
                if not DraftGeomUtils.isNull(pl):
                    obj.Placement = pl
Exemplo n.º 42
0
    def createGeometry(self,obj):
        "builds the wall shape"

        if not obj.Base:
            return

        import Part
        from draftlibs import fcgeo

        flat = False
        if hasattr(obj.ViewObject,"DisplayMode"):
            flat = (obj.ViewObject.DisplayMode == "Flat 2D")

        width = 1.0
        if hasattr(obj,"Width"):
            if obj.Width:
                width = obj.Width
        
        def getbase(wire):
            "returns a full shape from a base wire"
            dvec = fcgeo.vec(wire.Edges[0]).cross(normal)
            dvec.normalize()
            if obj.Align == "Left":
                dvec = dvec.multiply(width)
                w2 = fcgeo.offsetWire(wire,dvec)
                w1 = Part.Wire(fcgeo.sortEdges(wire.Edges))
                sh = fcgeo.bind(w1,w2)
            elif obj.Align == "Right":
                dvec = dvec.multiply(width)
                dvec = fcvec.neg(dvec)
                w2 = fcgeo.offsetWire(wire,dvec)
                w1 = Part.Wire(fcgeo.sortEdges(wire.Edges))
                sh = fcgeo.bind(w1,w2)
            elif obj.Align == "Center":
                dvec = dvec.multiply(width/2)
                w1 = fcgeo.offsetWire(wire,dvec)
                dvec = fcvec.neg(dvec)
                w2 = fcgeo.offsetWire(wire,dvec)
                sh = fcgeo.bind(w1,w2)
            # fixing self-intersections
            sh.fix(0.1,0,1)
            if height and (not flat):
                norm = Vector(normal).multiply(height)
                sh = sh.extrude(norm)
            return sh
        
        pl = obj.Placement

        # getting default values
        height = normal = None
        if obj.Height:
            height = obj.Height
        else:
            for p in obj.InList:
                if Draft.getType(p) == "Floor":
                    height = p.Height
        if not height: height = 1
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)

        # computing shape
        base = None
        if obj.Base.isDerivedFrom("Part::Feature"):
            if not obj.Base.Shape.isNull():
                base = obj.Base.Shape.copy()
                if base.Solids:
                    pass
                elif base.Faces:
                    if height:
                        norm = normal.multiply(height)
                        base = base.extrude(norm)
                elif base.Wires:
                    temp = None
                    for wire in obj.Base.Shape.Wires:
                        sh = getbase(wire)
                        if temp:
                            temp = temp.fuse(sh)
                        else:
                            temp = sh
                    base = temp
                    base = base.removeSplitter()

        for app in obj.Additions:
            base = base.oldFuse(app.Shape)
            app.ViewObject.hide() #to be removed
        for hole in obj.Subtractions:
            if Draft.getType(hole) == "Window":
                # window
                if hole.Base and obj.Width:
                    f = self.getSubVolume(hole.Base,width)
                    base = base.cut(f)
            elif Draft.isClone(hole,"Window"):
                if hole.Objects[0].Base and width:
                    f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement.Base)
                    base = base.cut(f)                   
            elif hasattr(hole,"Shape"):
                if not hole.Shape.isNull():
                    base = base.cut(hole.Shape)
                    hole.ViewObject.hide() # to be removed

        if base:
            obj.Shape = base
        if not fcgeo.isNull(pl):
            obj.Placement = pl