Example #1
0
def sub_gimbal_freecad_construction(c, ai_bottom_angle, ai_top_angle):
  """ generate the the freecad-object gimbal
  """
  # intermediate parameters
  z1 = c['base_thickness'] + c['bell_face_height'] + c['leg_length']
  z2 = c['inter_axle_length']
  # make the freecad-objects from bell_bagel_assembly and cross_cube
  i_bba = bell_bagel_assembly.bba()
  i_bba.apply_external_constraint(c)
  fc_bb_bottom = i_bba.get_fc_obj_3dconf('bell_bagel_assembly_conf1')
  fc_bb_top = fc_bb_bottom.copy()
  i_cross_cube = cross_cube.cross_cube()
  i_cross_cube.apply_external_constraint(cross_cube_constraint(c))
  fc_cc = i_cross_cube.get_fc_obj_3dconf('cross_cube_assembly_with_rods_and_axles')
  # place
  fc_bb_bottom.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),90)
  fc_bb_top.rotate(Base.Vector(0,0,z1),Base.Vector(0,1,0),180)
  fc_bb_top.translate(Base.Vector(0,0,z2))
  fc_cc.translate(Base.Vector(-1*c['cube_width']/2.0, -1*c['cube_width']/2.0, z1-(c['top_thickness'] + c['height_margin'] + c['axle_diameter']/2.0)))
  fc_cc.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),90)
  # apply the rotation
  fc_bb_top.rotate(Base.Vector(0,0,z1+z2),Base.Vector(0,1,0),ai_top_angle*180/math.pi)
  fc_top = Part.makeCompound([fc_bb_top, fc_cc])
  fc_top.rotate(Base.Vector(0,0,z1),Base.Vector(1,0,0),ai_bottom_angle*180/math.pi)
  r_fc_gimbal = Part.makeCompound([fc_bb_bottom, fc_top])
  return(r_fc_gimbal)
Example #2
0
 def execute(self,selfobj):
     tip = selfobj.Tip
     if len(tip) == 0:
         tip = selfobj.Group
     shapes = []
     for obj in tip:
         if hasattr(obj, 'Shape'):
             shapes.append(obj.Shape)
         else:
             App.Console.PrintWarning(u"Object {obj} has no shape, skipped for making a compound.\n".format(obj= obj.Label))
     result_shape = Part.Shape()
     opmode = selfobj.Operation
     if opmode == 'None':
         pass
     elif opmode == 'Compound':
         result_shape = Part.makeCompound(shapes)
     elif opmode == 'Fusion':
         if len(shapes)>1:
             result_shape = shapes[0].multiFuse(shapes[1:])
         else:
             result_shape = Part.makeCompound(shapes)
     elif opmode == 'Common':
         if len(shapes)>0:
             result_shape = shapes[0]
             for sh in shapes[1:]:
                 result_shape = result_shape.common(sh)
         else:
             result_shape = Part.Shape()
     else:
         raise ValueError("Operation mode {opmode} is not implemented".format(opmode= opmode))
             
     selfobj.Shape = result_shape
Example #3
0
    def derivedExecute(self,obj):
        # cache stuff
        base = obj.Base.Shape
        
        tool = obj.Tool.Shape
        if tool.ShapeType != 'Compound':
            tool = Part.makeCompound([tool])
        if obj.FlattenToolHierarchy:
            toolChildren = LCE.AllLeaves(tool)
        else:
            toolChildren = tool.childShapes()
        
        # validity logic
        if not latticeBaseFeature.isObjectLattice(obj.Tool):
            latticeExecuter.warning(obj, 'Tool is not a lattice object. Results may be unexpected.\n')
        outputIsLattice = latticeBaseFeature.isObjectLattice(obj.Base)
        
        plmMatcher = App.Placement() #extra placement, that makes first item to preserve its original placement
        if obj.KeepBaseFirstItemPos:
            plmMatcher = toolChildren[0].Placement.inverse()
        
        # Pre-collect base placement list, if base is a lattice. For speed.
        if outputIsLattice:
            baseLeaves = LCE.AllLeaves(base)
            basePlms = []
            for leaf in baseLeaves:
                basePlms.append(plmMatcher.multiply(leaf.Placement))
            baseLeaves = None #free memory
        
        # initialize output containers and loop variables
        outputShapes = [] #output list of shapes
        outputPlms = [] #list of placements
        
        # the essence
        for toolChild in toolChildren:
            #cache some stuff
            toolPlm = toolChild.Placement

            if outputIsLattice:
                for basePlm in basePlms:
                    outputPlms.append(toolPlm.multiply(basePlm))
            else:
                outputShape = base.copy()
                outputShape.Placement = toolPlm.multiply(plmMatcher.multiply(outputShape.Placement))
                outputShapes.append(outputShape)
            
        if outputIsLattice:
            return outputPlms
        else:
            obj.Shape = Part.makeCompound(outputShapes)
            return None
Example #4
0
def compoundFromAssembly(root, flatten, exclude, recursive = True, visit_set = None):
    if visit_set is None:
        visit_set = set()
    
    #recursion guard
    if root in visit_set:
        raise ValueError("Circular dependency")
    visit_set.add(root)
    
    if hasattr(root, 'Shape'):
        return root.Shape
    else:
        children = Containers.getDirectChildren(root)
        shapes = []
        for child in children:
            if child in exclude:
                continue
            if child.isDerivedFrom('App::Origin'):
                continue #otherwise, origins create empty compounds - undesirable.
            if hasattr(child, 'Shape'):
                shapes.append(child.Shape)
            elif Containers.isContainer(child) and recursive:
                cmp = compoundFromAssembly(child, flatten, exclude, recursive, visit_set)
                if flatten:
                    shapes.extend(cmp.childShapes())
                else:
                    shapes.append(cmp)
        transform = root.Placement if hasattr(root, 'Placement') else None
        ret = Part.makeCompound(shapes)
        if transform is not None:
            ret.Placement = transform
        return ret
def updateTrajectoryLines():
    EAFolder = FreeCAD.ActiveDocument.ExplodedAssembly.Group
    # remove all the previous trajectory lines
    for traj in EAFolder:
        for lines in traj.Group:
            FreeCAD.ActiveDocument.removeObject(lines.Name)

    # re-draw all trajectories
    for traj in EAFolder:
        lines_compound = []
        objects = []
        for name in traj.names:
            objects.append(FreeCAD.ActiveDocument.getObject(name))

        inc_D = traj.Distance
        dir_vectors = []
        rot_centers = []
        for s in xrange(len(objects)):
            dir_vectors.append(FreeCAD.Vector(tuple(traj.dir_vectors[s])))
            rot_centers.append(FreeCAD.Vector(tuple(traj.rot_centers[s])))

        for n in xrange(len(objects)):
            pa = rot_centers[n]# objects[n].Placement.Base
            pb = rot_centers[n] + dir_vectors[n]*inc_D
            lines_compound.append(Part.makeLine(pa, pb))

        l_obj = FreeCAD.ActiveDocument.addObject('Part::Feature','trajectory_line')
        l_obj.Shape = Part.makeCompound(lines_compound)
        l_obj.ViewObject.DrawStyle = "Dashed"
        l_obj.ViewObject.LineWidth = 1.0
        traj.addObject(l_obj)

    FreeCAD.Gui.updateGui()
    def execute(self,obj):

        # gather all the child shapes into a compound
        shapes = self.getShapes(obj)
        if shapes:
            import Part
            obj.Shape = Part.makeCompound(shapes)
Example #7
0
 def execute(self, fp):
     try:
         if fp.Border == None or fp.Holes == None:
             return
         
         if fp.Thickness.Value <= 0:
             fp.Thickness.Value = 0.1
             return
         
         try:
             self.oldHeight = fp.Shape.BoundBox.ZMax
         except:
             self.oldHeight = 0
         # holes
         borderOutline = OpenSCAD2Dgeom.edgestofaces(fp.Border.Shape.Wires)
         
         holes = []
         for i in fp.Holes.Shape.Wires:
             holes.append(Part.Face(i))
         
         if len(holes):
             face = borderOutline.cut(Part.makeCompound(holes))
         else:
             face = borderOutline
         #
         fp.Shape = face.extrude(FreeCAD.Base.Vector(0, 0, fp.Thickness.Value))
     except:
         pass
Example #8
0
 def computeShape(self, obj):
     """ Computes simulation involved shapes.
     @param obj Created Part::FeaturePython object.
     @return Shape
     """
     print("[ShipSimulation] Computing mesh shape...")
     nx     = obj.FS_Nx
     ny     = obj.FS_Ny
     mesh   = FSMesh(obj)
     planes = []
     # Create planes
     Percentage = 0
     Count = 0
     print("0%")
     for i in range(1,nx-1):
         for j in range(1,ny-1):
             Count = Count+1
             done = int(round(100 * Count / ((nx-2)*(ny-2))))
             if done != Percentage:
                 Percentage = done
                 print("%i%%" % (done))
             v0 = (mesh[i][j].pos + mesh[i-1][j].pos + mesh[i][j-1].pos + mesh[i-1][j-1].pos).multiply(0.25)
             v1 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j-1].pos + mesh[i+1][j-1].pos).multiply(0.25)
             v2 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j+1].pos + mesh[i+1][j+1].pos).multiply(0.25)
             v3 = (mesh[i][j].pos + mesh[i-1][j].pos + mesh[i][j+1].pos + mesh[i-1][j+1].pos).multiply(0.25)
             p  = Part.makePolygon([v0,v1,v2,v3,v0])
             planes.append(Part.makeFilledFace(p.Edges))
     # Join into a compound
     return Part.makeCompound(planes)
Example #9
0
def guessDepths(objshape, subs=None):
    """
    takes an object shape and optional list of subobjects and returns a depth_params
    object with suggested height/depth values.

    objshape = Part::Shape.
    subs = list of subobjects from objshape
    """

    bb = objshape.BoundBox  # parent boundbox
    clearance = bb.ZMax + 5.0
    safe = bb.ZMax
    start = bb.ZMax
    final = bb.ZMin

    if subs is not None:
        subobj = Part.makeCompound(subs)
        fbb = subobj.BoundBox  # feature boundbox
        start = fbb.ZMax

        if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax:  # top face
            final = fbb.ZMin
        elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax:  # vertical face, full cut
            final = fbb.ZMin
        elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin:  # internal vertical wall
            final = fbb.ZMin
        elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin:  # face/shelf
            final = fbb.ZMin

    return depth_params(clearance, safe, start, 1.0, 0.0, final, user_depths=None, equalstep=False)
def makeBase(l,z,lpol,zpol,lone,zone,zero):

	lines=[]
	f=np.sqrt(len2(lpol,zero))
	e=np.sqrt(len2(lone,zero))
	dist=e*f*l/((l-1)*e+f)
	pa=pointat(zero,lpol,dist)
	print (l,z,dist,pa)

#	lines.append(Part.makeLine(vec(zpol),vec(pa)))	
#	lines.append(Part.makeCircle(10000,vec(pa)))

	f=np.sqrt(len2(zpol,zero))
	e=np.sqrt(len2(zone,zero))
	dist=e*f*z/((z-1)*e+f)
	pb=pointat(zero,zpol,dist)
	print (l,z,dist,pb)

#	lines.append(Part.makeLine(vec(lpol),vec(pb)))	
#	lines.append(Part.makeCircle(10000,vec(pb)))
	pc=schnittpunkt(lpol,pb,zpol,pa)
	print (pa,pb,pc)
	lines.append(Part.makeCircle(15000,vec(pc)))
	comp=Part.makeCompound(lines)
#	Part.show(comp)

	return pc
Example #11
0
    def execute(self, fp):
        """Detects the entity recomputations.

        Keyword arguments:
        fp -- Part::FeaturePython object affected.
        """
        fp.Shape = Part.makeCompound(fp.Shape.Solids)
Example #12
0
    def updateData(self,obj,prop):

        if prop == "Shape":
            if hasattr(self,"centerline"):
                if self.centerline:
                    self.centerlinegroup.removeChild(self.centerline)
            if hasattr(obj.Proxy,"wires"):
                if obj.Proxy.wires:
                    from pivy import coin
                    import re,Part
                    self.centerline = coin.SoSeparator()
                    comp = Part.makeCompound(obj.Proxy.wires)
                    pts = re.findall("point \[(.*?)\]",comp.writeInventor().replace("\n",""))
                    pts = [p.split(",") for p in pts]
                    for pt in pts:
                        ps = coin.SoSeparator()
                        plist = []
                        for p in pt:
                            c = []
                            for pstr in p.split(" "):
                                if pstr:
                                    c.append(float(pstr))
                            plist.append(c)
                        coords = coin.SoCoordinate3()
                        coords.point.setValues(plist)
                        ps.addChild(coords)
                        ls = coin.SoLineSet()
                        ls.numVertices = -1
                        ps.addChild(ls)
                        self.centerline.addChild(ps)
                    self.centerlinegroup.addChild(self.centerline)
        ArchComponent.ViewProviderComponent.updateData(self,obj,prop)
Example #13
0
    def areaOpOnChanged(self, obj, prop):
        '''areaOpOnChanged(obj, prop) ... facing specific depths calculation.'''
        PathLog.track(prop)
        if prop == "StepOver" and obj.StepOver == 0:
            obj.StepOver = 1

        # default depths calculation not correct for facing
        if prop == "Base":
            job = PathUtils.findParentJob(obj)
            obj.OpStartDepth = job.Stock.Shape.BoundBox.ZMax

            if len(obj.Base) >= 1:
                print('processing')
                sublist = []
                for i in obj.Base:
                    o = i[0]
                    for s in i[1]:
                        sublist.append(o.Shape.getElement(s))

            # If the operation has a geometry identified the Finaldepth
            # is the top of the bboundbox which includes all features.
            # Otherwise, top of part.

                obj.OpFinalDepth = Part.makeCompound(sublist).BoundBox.ZMax
            else:
                obj.OpFinalDepth = job.Base.Shape.BoundBox.ZMax
Example #14
0
    def __init__(self, obj, shapes, ship):
        """ Transform a generic object to a ship instance.

        Keyword arguments:
        obj -- Part::FeaturePython created object which should be transformed
        in a weight instance.
        shapes -- Set of solid shapes which will compound the tank.
        ship -- Ship where the tank is allocated.
        """
        # Add an unique property to identify the Weight instances
        tooltip = str(
            QtGui.QApplication.translate(
                "ship_tank",
                "True if it is a valid tank instance, False otherwise",
                None,
                QtGui.QApplication.UnicodeUTF8,
            )
        )
        obj.addProperty("App::PropertyBool", "IsTank", "Tank", tooltip).IsTank = True
        # Add the volume property (The volume of fluid will be set by each
        # loading condition)
        tooltip = str(
            QtGui.QApplication.translate("ship_tank", "Volume of fluid [m^3]", None, QtGui.QApplication.UnicodeUTF8)
        )
        obj.addProperty("App::PropertyFloat", "Vol", "Tank", tooltip).Vol = 0.0
        # Add the density property (The volume of fluid will be set by each
        # loading condition)
        tooltip = str(
            QtGui.QApplication.translate("ship_tank", "Density [kg / m^3]", None, QtGui.QApplication.UnicodeUTF8)
        )
        obj.addProperty("App::PropertyFloat", "Dens", "Tank", tooltip).Dens = 0.0
        # Set the subshapes
        obj.Shape = Part.makeCompound(shapes)

        obj.Proxy = self
Example #15
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return top face'''
        # Facing is done either against base objects
        if obj.Base:
            PathLog.debug("obj.Base: {}".format(obj.Base))
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                    else:
                        PathLog.debug('The base subobject is not a face')
                        return
            planeshape = Part.makeCompound(faces)
            PathLog.debug("Working on a collection of faces {}".format(faces))

        # If no base object, do planing of top surface of entire model
        else:
            planeshape = self.baseobject.Shape
            PathLog.debug("Working on a shape {}".format(self.baseobject.Name))

        # Find the correct shape depending on Boundary shape.
        PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape))
        bb = planeshape.BoundBox
        if obj.BoundaryShape == 'Boundbox':
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(0, 0, 1))
            env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams)
        elif obj.BoundaryShape == 'Stock':
            stock = PathUtils.findParentJob(obj).Stock.Shape
            env = stock
        else:
            env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams)

        return [(env, False)]
Example #16
0
def export_xyz_to_dxf(ai_solid, ai_size_x, ai_size_y, ai_size_z, ai_xy_slice_list, ai_xz_slice_list, ai_yz_slice_list, ai_output_file):
  """ Cut a FreeCAD Part Object in many slices in the three directions X, Y and Z and put all those slices in a DXF file
  """
  # calculate the space between two drawings
  l_space = max(ai_size_x/5.0, ai_size_y/5.0, ai_size_z/5.0)
  #
  vec_z_unit = Base.Vector(0,0,1)
  #
  l_slice_list = []
  l_pos_y = 0
  for lo in ['xy','xz','yz']:
    #l_solid = ai_solid
    l_solid = ai_solid.copy()
    l_depth_list = []
    l_shift_x = 0
    l_gauge_max = 0
    if(lo=='xy'):
      l_solid.rotate(Base.Vector(ai_size_x/2.0, ai_size_y/2.0, ai_size_z/2.0), Base.Vector(0,0,1), 0)
      l_solid.translate(Base.Vector(0,0,0)) # place the module corner at origin (0,0,0)
      l_solid.translate(Base.Vector(0,2*ai_size_z+7*l_space,0))
      l_pos_y = 2*ai_size_z+6*l_space
      l_depth_list = ai_xy_slice_list
      l_shift_x = ai_size_x
      l_gauge_max = ai_size_z
    elif(lo=='xz'):
      l_solid.rotate(Base.Vector(ai_size_x/2.0, ai_size_y/2.0, ai_size_z/2.0), Base.Vector(1,0,0), -90)
      l_solid.translate(Base.Vector((ai_size_x-ai_size_x)/2.0, (ai_size_z-ai_size_y)/2.0, (ai_size_y-ai_size_z)/2.0)) # place the module corner at origin (0,0,0)
      l_solid.translate(Base.Vector(0,1*ai_size_z+4*l_space,0))
      l_pos_y = 1*ai_size_z+3*l_space
      l_depth_list = ai_xz_slice_list
      l_shift_x = ai_size_x
      l_gauge_max = ai_size_y
    elif(lo=='yz'):
      l_solid.rotate(Base.Vector(ai_size_x/2.0, ai_size_y/2.0, ai_size_z/2.0), Base.Vector(0,0,1), -90)
      l_solid.rotate(Base.Vector(ai_size_x/2.0, ai_size_y/2.0, ai_size_z/2.0), Base.Vector(1,0,0), -90)
      l_solid.translate(Base.Vector((ai_size_y-ai_size_x)/2.0, (ai_size_z-ai_size_y)/2.0, (ai_size_x-ai_size_z)/2.0)) # place the module corner at origin (0,0,0)
      l_solid.translate(Base.Vector(0,l_space,0))
      l_pos_y = 0*ai_size_z+0*l_space
      l_depth_list = ai_yz_slice_list
      l_shift_x = ai_size_y
      l_gauge_max = ai_size_x
    l_pos_x = 0
    for l_depth in l_depth_list:
      #print("dbg163: l_shift_x l_space l_gauge_max l_depth l_pos_x l_pos_y", l_shift_x, l_space, l_gauge_max, l_depth, l_pos_x, l_pos_y)
      l_slice_list.extend(draw_gauge(l_shift_x, l_space/2.0, l_gauge_max, l_depth, l_pos_x, l_pos_y))
      l_pos_x += l_shift_x+2*l_space
      ll_depth = l_depth
      if(lo=='xz'):
        ll_depth = ai_size_y-l_depth
      #print("dbg168: ll_depth:", ll_depth)
      l_slice_list.extend(l_solid.slice(vec_z_unit, ll_depth))
      l_solid.translate(Base.Vector(l_shift_x+2*l_space,0,0))
  l_slice = Part.makeCompound(l_slice_list)
  # temporary commented because of OpenCascade bug
  #r_dxf = Drawing.projectToDXF(l_slice, vec_z_unit)
  ##r_dxf = Drawing.projectToDXF(ai_solid, ai_vector)
  #fh_output = open(ai_output_file, 'w')
  #fh_output.write(r_dxf)
  #fh_output.close()
  return(1)
Example #17
0
 def createGeometry(self,obj):
     import Part
     pl = obj.Placement
     if obj.Components:
         shapes = []
         if obj.JoinMode:
             walls = []
             structs = []
             for c in obj.Components:
                 if Draft.getType(c) == "Wall":
                     walls.append(c.Shape)
                 elif Draft.getType(c) == "Structure":
                     structs.append(c.Shape)
                 else:
                     shapes.append(c.Shape)
             for group in [walls,structs]:
                 if group:
                     sh = group.pop(0).copy()
                     for subsh in group:
                         sh = sh.oldFuse(subsh)
                     shapes.append(sh)
         else:
             for c in obj.Components:
                 shapes.append(c.Shape)
         if shapes:
             obj.Shape = Part.makeCompound(shapes)
         obj.Placement = pl
Example #18
0
def connect(list_of_shapes, tolerance = 0.0):
    """connect(list_of_shapes, tolerance = 0.0): connects solids (walled objects), shells and 
    wires by throwing off small parts that result when splitting them at intersections. 
    
    Compounds in list_of_shapes are automatically exploded, so self-intersecting compounds 
    are valid for connect."""
    
    # explode all compounds before GFA.
    new_list_of_shapes = []
    for sh in list_of_shapes:
        new_list_of_shapes.extend( compoundLeaves(sh) )
    list_of_shapes = new_list_of_shapes
    
    #test if shapes are compatible for connecting
    dim = ShapeMerge.dimensionOfShapes(list_of_shapes)
    if dim == 0:
        raise TypeError("Cannot connect vertices!")
        
    if len(list_of_shapes) < 2:
        return Part.makeCompound(list_of_shapes)
        
    if not generalFuseIsAvailable(): #fallback to legacy
        result = list_of_shapes[0]
        for i in range(1, len(list_of_shapes)):
            result = connect_legacy(result, list_of_shapes[i], tolerance)
        return result
    
    pieces, map = list_of_shapes[0].generalFuse(list_of_shapes[1:], tolerance)
    ao = GeneralFuseResult(list_of_shapes, (pieces, map))
    ao.splitAggregates()
    #print len(ao.pieces)," pieces total"
    
    keepers = []
    all_danglers = [] # debug
                
    #add all biggest dangling pieces
    for src in ao.source_shapes:
        danglers = [piece for piece in ao.piecesFromSource(src) if len(ao.sourcesOfPiece(piece)) == 1]
        all_danglers.extend(danglers)
        largest = shapeOfMaxSize(danglers)
        if largest is not None:
            keepers.append(largest)

    touch_test_list = Part.Compound(keepers)
    #add all intersection pieces that touch danglers, triple intersection pieces that touch duals, and so on
    for ii in range(2, ao.largestOverlapCount()+1):
        list_ii_pieces = [piece for piece in ao.pieces if len(ao.sourcesOfPiece(piece)) == ii]
        keepers_2_add = []
        for piece in list_ii_pieces: 
            if ShapeMerge.isConnected(piece, touch_test_list):
                keepers_2_add.append(piece)
        if len(keepers_2_add) == 0:
            break
        keepers.extend(keepers_2_add)
        touch_test_list = Part.Compound(keepers_2_add)
        
    
    #merge, and we are done!
    #print len(keepers)," pieces to keep"
    return ShapeMerge.mergeShapes(keepers)
Example #19
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        if obj.Base:
            PathLog.debug("base items exist.  Processing...")
            removalshapes = []
            for b in obj.Base:
                PathLog.debug("Base item: {}".format(b))
                for sub in b[1]:
                    if "Face" in sub:
                        shape = Part.makeCompound([getattr(b[0].Shape, sub)])
                    else:
                        edges = [getattr(b[0].Shape, sub) for sub in b[1]]
                        shape = Part.makeFace(edges, 'Part::FaceMakerSimple')

                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=shape, depthparams=self.depthparams)
                    obj.removalshape = env.cut(self.baseobject.Shape)
                    removalshapes.append((obj.removalshape, False))
        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")

            env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=None, depthparams=self.depthparams)
            obj.removalshape = env.cut(self.baseobject.Shape)
            removalshapes = [(obj.removalshape, False)]
        return removalshapes
Example #20
0
def main(filename,canny1=100,canny2=200,rho=1,theta=1, threshold=10, minLineLength =25, maxLineGap =10,
			showimage=False,showimagewithlines=False,newDocument=True):
# def main(f):
	f=filename
	im = cv2.imread(f)
	gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
	edges = cv2.Canny(gray,canny1,canny2)

	xsize=len(im[0])
	ysize=len(im)

#image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])
	lines = cv2.HoughLinesP(edges,1,np.pi/180*theta,threshold, minLineLength = minLineLength, maxLineGap = maxLineGap)
#	lines = cv2.HoughLinesP(edges,1,np.pi/180,10, minLineLength = 25, maxLineGap = 10)
	#lines = cv2.HoughLinesP(edges,1,np.pi/2,2)[0]

	k=0
	fclines=[]

	for l in lines:
		k += 1
		[[x1,y1,x2,y2]] = l       
		fl=fclinev2(x1,-y1,x2,-y2)
		fclines.append(fl)
		#print (x1,y1,x2,y2)
		a=cv2.line(im,(x1,y1),(x2,y2),(0,255,255),2)

	c=Part.makeCompound(fclines)
	c.Placement.Base=FreeCAD.Vector(-xsize/2*scaler,ysize/2*scaler,0)
	if newDocument:
		d=App.newDocument("HoughLines")
#		App.setActiveDocument("Unnamed1")
#		App.ActiveDocument=d
#		Gui.ActiveDocument=Gui.getDocument("Unnamed1")
		
	Part.show(c)

	cv2.imwrite('/tmp/out.png',im)

	import Image, ImageGui
	#ImageGui.open(unicode("/tmp/out.png","utf-8"))

	if showimage:
		fimg=App.activeDocument().addObject('Image::ImagePlane','Image 2')
		fimg.Label=f
		fimg.ImageFile = f
		fimg.XSize = xsize*scaler
		fimg.YSize = ysize*scaler
		fimg.Placement.Base.z=-5

	if showimagewithlines:
		fimg=App.activeDocument().addObject('Image::ImagePlane','Image with Houghlines')
		fimg.ImageFile = '/tmp/out.png'
		fimg.XSize = xsize*scaler
		fimg.YSize = ysize*scaler
		fimg.Placement.Base.z=-10
		FreeCADGui.SendMsgToActiveView("ViewFit")

	print ("lines:",k)
Example #21
0
    def execute(self,obj):
        "builds the wall shape"
        
        if self.clone(obj):
            return

        import Part, DraftGeomUtils
        base = None
        pl = obj.Placement
        extdata = self.getExtrusionData(obj)
        if extdata:
            base = extdata[0]
            extv = extdata[2].Rotation.multVec(extdata[1])
            if isinstance(base,list):
                shps = []
                for b in base:
                    b.Placement = extdata[2].multiply(b.Placement)
                    b = b.extrude(extv)
                    shps.append(b)
                base = Part.makeCompound(shps)
            else:
                base.Placement = extdata[2].multiply(base.Placement)
                base = base.extrude(extv)
        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
                elif obj.Base.Shape.Solids:
                    base = obj.Base.Shape.copy()
            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(translate("Arch","This mesh is an invalid solid")+"\n")
                            obj.Base.ViewObject.show()
        if not base:
            FreeCAD.Console.PrintError(translate("Arch","Error: Invalid base object")+"\n")
            return

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

        # set the length property
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Edges:
                    if not obj.Base.Shape.Faces:
                        if hasattr(obj.Base.Shape,"Length"):
                            l = obj.Base.Shape.Length
                            if obj.Length.Value != l:
                                obj.Length = l
    def __init__(self, obj, shapes, ship):
        """ Transform a generic object to a ship instance.

        Position arguments:
        obj -- Part::FeaturePython created object which should be transformed
        in a weight instance.
        shapes -- Set of shapes which will compound the weight element.
        ship -- Ship where the weight is allocated.
        """
        # Add an unique property to identify the Weight instances
        tooltip = str(QtGui.QApplication.translate(
            "ship_weight",
            "True if it is a valid weight instance, False otherwise",
            None))
        obj.addProperty("App::PropertyBool",
                        "IsWeight",
                        "Weight",
                        tooltip).IsWeight = True
        # Add the mass property for puntual weights
        tooltip = str(QtGui.QApplication.translate(
            "ship_weight",
            "Mass [kg]",
            None))
        obj.addProperty("App::PropertyFloat",
                        "Mass",
                        "Weight",
                        tooltip).Mass = 0.0
        # Add the density property for linear elements
        tooltip = str(QtGui.QApplication.translate(
            "ship_weight",
            "Linear density [kg / m]",
            None))
        obj.addProperty("App::PropertyFloat",
                        "LineDens",
                        "Weight",
                        tooltip).LineDens = 0.0
        # Add the area density property for surface elements
        tooltip = str(QtGui.QApplication.translate(
            "ship_weight",
            "Area density [kg / m^2]",
            None))
        obj.addProperty("App::PropertyFloat",
                        "AreaDens",
                        "Weight",
                        tooltip).AreaDens = 0.0
        # Add the density property for volumetric elements
        tooltip = str(QtGui.QApplication.translate(
            "ship_weight",
            "Density [kg / m^3]",
            None))
        obj.addProperty("App::PropertyFloat",
                        "Dens",
                        "Weight",
                        tooltip).Dens = 0.0
        # Set the subshapes
        obj.Shape = Part.makeCompound(shapes)

        obj.Proxy = self
Example #23
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        if obj.UseComp:
            self.commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
        else:
            self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))

        shapes = []

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            holes = []
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]
                    else:
                        FreeCAD.Console.PrintWarning("found a base object which is not a face.  Can't continue.")
                        return

            for wire in holes:
                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                drillable = PathUtils.isDrillable(self.baseobject.Shape, wire)
                if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                    shapes.append((env, True))

            if len(faces) > 0:
                profileshape = Part.makeCompound(faces)

            if obj.processPerimeter:
                env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=profileshape, depthparams=self.depthparams)
                shapes.append((env, False))

        else:  # Try to build targets from the job base
            if hasattr(self.baseobject, "Proxy"):
                if isinstance(self.baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                    if obj.processCircles or obj.processHoles:
                        for shape in self.baseobject.Proxy.getHoles(self.baseobject, transform=True):
                            for wire in shape.Wires:
                                drillable = PathUtils.isDrillable(self.baseobject.Proxy, wire)
                                if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                    shapes.append((env, True))

                    if obj.processPerimeter:
                        for shape in self.baseobject.Proxy.getOutlines(self.baseobject, transform=True):
                            for wire in shape.Wires:
                                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                shapes.append((env, False))

        PathLog.debug("%d shapes" % len(shapes))
        return shapes
Example #24
0
    def __init__(self, obj, solids):
        """ Transform a generic object to a ship instance.

        Keyword arguments:
        obj -- Part::FeaturePython created object which should be transformed
        in a ship instance.
        solids -- Set of solids which will compound the ship hull.
        """
        # Add an unique property to identify the Ship instances
        tooltip = str(QtGui.QApplication.translate(
            "Ship",
            "True if it is a valid ship instance, False otherwise",
            None,
            QtGui.QApplication.UnicodeUTF8))
        obj.addProperty("App::PropertyBool",
                        "IsShip",
                        "Ship",
                        tooltip).IsShip = True
        # Add the main dimensions
        tooltip = str(QtGui.QApplication.translate(
            "Ship",
            "Ship length [m]",
            None,
            QtGui.QApplication.UnicodeUTF8))
        obj.addProperty("App::PropertyLength",
                        "Length",
                        "Ship",
                        tooltip).Length = 0.0
        tooltip = str(QtGui.QApplication.translate(
            "Ship",
            "Ship breadth [m]",
            None,
            QtGui.QApplication.UnicodeUTF8))
        obj.addProperty("App::PropertyLength",
                        "Breadth",
                        "Ship",
                        tooltip).Breadth = 0.0
        tooltip = str(QtGui.QApplication.translate(
            "Ship",
            "Ship draft [m]",
            None,
            QtGui.QApplication.UnicodeUTF8))
        obj.addProperty("App::PropertyLength",
                        "Draft",
                        "Ship",
                        tooltip).Draft = 0.0
        # Add the subshapes
        obj.Shape = Part.makeCompound(solids)
        tooltip = str(QtGui.QApplication.translate(
            "Ship",
            "Set of external faces of the ship hull",
            None,
            QtGui.QApplication.UnicodeUTF8))
        obj.addProperty("Part::PropertyPartShape",
                        "ExternalFaces",
                        "Ship",
                        tooltip)
        obj.Proxy = self
def mergeWires(list_of_edges_wires, flag_single = False, split_connections = []):
    edges = []
    for sh in list_of_edges_wires:
        edges.extend(sh.Edges)
    if flag_single:
        return Part.Wire(edges)
    else:
        groups = splitIntoGroupsBySharing(edges, lambda(sh): sh.Vertexes, split_connections)
        return Part.makeCompound([Part.Wire(Part.getSortedClusters(group)[0]) for group in groups])
def mergeShells(list_of_faces_shells, flag_single = False, split_connections = []):
    faces = []
    for sh in list_of_faces_shells:
        faces.extend(sh.Faces)
    if flag_single:
        return Part.makeShell(faces)
    else:
        groups = splitIntoGroupsBySharing(faces, lambda(sh): sh.Edges, split_connections)
        return Part.makeCompound([Part.Shell(group) for group in groups])
Example #27
0
def getShapeFromMesh(mesh,fast=True,tolerance=0.001,flat=False,cut=True):
    import Part, MeshPart, DraftGeomUtils
    if mesh.isSolid() and (mesh.countComponents() == 1) and fast:
        # use the best method
        faces = []
        for f in mesh.Facets:
            p=f.Points+[f.Points[0]]
            pts = []
            for pp in p:
                pts.append(FreeCAD.Vector(pp[0],pp[1],pp[2]))
            try:
                f = Part.Face(Part.makePolygon(pts))
            except:
                pass
            else:
                faces.append(f)
        shell = Part.makeShell(faces)
        solid = Part.Solid(shell)
        solid = solid.removeSplitter()
        return solid

    faces = []
    segments = mesh.getPlanarSegments(tolerance)
    #print len(segments)
    for i in segments:
        if len(i) > 0:
            wires = MeshPart.wireFromSegment(mesh, i)
            if wires:
                if flat:
                    nwires = []
                    for w in wires:
                        nwires.append(DraftGeomUtils.flattenWire(w))
                    wires = nwires
                try:
                    faces.append(makeFace(wires,method=int(cut)+1))
                except:
                    return None
    try:
        se = Part.makeShell(faces)
        se = se.removeSplitter()
        if flat:
            return se
    except Part.OCCError:
        try:
            cp = Part.makeCompound(faces)
        except Part.OCCError:
            return None
        else:
            return cp
    else:
        try:
            solid = Part.Solid(se)
        except Part.OCCError:
            return se
        else:
            return solid
Example #28
0
 def execute(self, obj):
     if 'tGlue' in self.Type:
         z = getPCBheight()[1] + 0.04
         h = obj.Height.Value
         
         if h <= 0:
             h = 0.01
     else:  # bottomSide
         z = -0.04
         h = -obj.Height.Value
         
         if h >= 0:
             h = -0.01
     #
     obiekty = []
     #
     for i in obj.Base.Geometry:
         if i.__class__.__name__ == 'GeomLineSegment':
             x1 = i.StartPoint.x
             y1 = i.StartPoint.y
             x2 = i.EndPoint.x
             y2 = i.EndPoint.y
             #
             obiekty.append(self.createLine(x1, y1, x2, y2, obj.Width.Value))
         elif i.__class__.__name__ == 'GeomCircle':
             x = i.Center.x
             y = i.Center.y
             r = i.Radius
             #
             obiekty.append(self.createCircle(x, y, r, obj.Width.Value))
         elif i.__class__.__name__ == 'GeomArcOfCircle':
             curve = degrees(i.LastParameter - i.FirstParameter)
             xs = i.Center.x
             ys = i.Center.y
             r = i.Radius
             
             math = mathFunctions()
             p1 = [math.cosinus(degrees(i.FirstParameter)) * r, math.sinus(degrees(i.FirstParameter)) * r]
             p1 = [p1[0] + xs, p1[1] + ys]
             p2 = math.obrocPunkt2(p1, [xs, ys], curve)
             #
             obiekty.append(self.createArc(p1, p2, curve, obj.Width.Value))
     #
     #path = obiekty[0]
     #for i in range(1, len(obiekty)):
         #path = path.fuse(obiekty[i])
     #path = path.removeSplitter()
     path = Part.makeCompound(obiekty)
     # cut to board shape
     if self.cutToBoard:
         path = cutToBoardShape(path)
     ###################################################
     if obj.Flat == False:
         path = path.extrude(FreeCAD.Base.Vector(0, 0, h))
     path.Placement.Base.z = z
     obj.Shape = path
Example #29
0
def export_to_svg(ai_solid, ai_vector, ai_depth, ai_output_file):
  """ create a SVG of a slice of FreeCAD Part Object. The generated SVG is incomplete. SVG header must be added to it to be opened by Inkscape
  """
  l_slice = Part.makeCompound(ai_solid.slice(ai_vector, ai_depth)) # slice the plank in the ai_vector plan at a the height ai_depth
  r_dxf = Drawing.projectToSVG(l_slice, ai_vector) # it generates a snippet of svg not directly usable by Inkscape. It needs the svg head and document markers.
  #r_dxf = Drawing.projectToSVG(ai_solid, ai_vector) # works also :)
  fh_output = open(ai_output_file, 'w')
  fh_output.write(r_dxf)
  fh_output.close()
  return(1)
Example #30
0
def export_to_dxf(ai_solid, ai_vector, ai_depth, ai_output_file):
  """ create a DXF of a slice of FreeCAD Part Object
  """
  l_slice = Part.makeCompound(ai_solid.slice(ai_vector, ai_depth)) # slice the plank in the ai_vector plan at a the height ai_depth
  r_dxf = Drawing.projectToDXF(l_slice, ai_vector)
  #r_dxf = Drawing.projectToDXF(ai_solid, ai_vector) # works also :)
  fh_output = open(ai_output_file, 'w')
  fh_output.write(r_dxf)
  fh_output.close()
  return(1)
Example #31
0
    def execute(self, obj):
        "builds the wall shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils
        base = None
        pl = obj.Placement
        extdata = self.getExtrusionData(obj)
        if extdata:
            base = extdata[0]
            extv = extdata[2].Rotation.multVec(extdata[1])
            if isinstance(base, list):
                shps = []
                for b in base:
                    b.Placement = extdata[2].multiply(b.Placement)
                    b = b.extrude(extv)
                    shps.append(b)
                base = Part.makeCompound(shps)
            else:
                base.Placement = extdata[2].multiply(base.Placement)
                base = base.extrude(extv)
        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
                elif obj.Base.Shape.Solids:
                    base = obj.Base.Shape.copy()
            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(
                                translate("Arch",
                                          "This mesh is an invalid solid") +
                                "\n")
                            obj.Base.ViewObject.show()
        if not base:
            FreeCAD.Console.PrintError(
                translate("Arch", "Error: Invalid base object") + "\n")
            return

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

        # set the length property
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Edges:
                    if not obj.Base.Shape.Faces:
                        if hasattr(obj.Base.Shape, "Length"):
                            l = obj.Base.Shape.Length
                            if obj.Length.Value != l:
                                obj.Length = l
Example #32
0
    def execute(self,obj):
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    if obj.BasePoint == 0 :
                        basepoint = profile.CenterOfMass
                    else :
                        # TODO add mid point of edges and make an ordered list point, mid point , ...
                        basepoint = profile.Vertexes[obj.BasePoint - 1].Point
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Example #33
0
def getSVG(section,
           renderMode="Wireframe",
           allOn=False,
           showHidden=False,
           scale=1,
           rotation=0,
           linewidth=1,
           lineColor=(0.0, 0.0, 0.0),
           fontsize=1,
           showFill=False,
           fillColor=(0.8, 0.8, 0.8),
           techdraw=False):
    """getSVG(section, [renderMode, allOn, showHidden, scale, rotation,
              linewidth, lineColor, fontsize, showFill, fillColor, techdraw]):

    returns an SVG fragment from an Arch section plane. If
    allOn is True, all cut objects are shown, regardless if they are visible or not.
    renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If
    showHidden is True, the hidden geometry above the section plane is shown in dashed line.
    If showFill is True, the cut areas get filled with a pattern.
    lineColor -- Color of lines for the renderMode "Wireframe".
    fillColor -- If showFill is True and renderMode is "Wireframe",
                 the cut areas are filled with fillColor.
    """

    if not section.Objects:
        return ""
    import Part, DraftGeomUtils
    p = FreeCAD.Placement(section.Placement)
    direction = p.Rotation.multVec(FreeCAD.Vector(0, 0, 1))
    objs = Draft.getGroupContents(section.Objects, walls=True, addgroups=True)
    if not allOn:
        objs = Draft.removeHidden(objs)
    # separate spaces and Draft objects
    spaces = []
    nonspaces = []
    drafts = []
    windows = []
    cutface = None
    for o in objs:
        if Draft.getType(o) == "Space":
            spaces.append(o)
        elif Draft.getType(o) in ["Dimension", "Annotation"]:
            drafts.append(o)
        elif o.isDerivedFrom("Part::Part2DObject"):
            drafts.append(o)
        else:
            nonspaces.append(o)
        if Draft.getType(o) == "Window":
            windows.append(o)
    objs = nonspaces

    archUserParameters = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch")
    scaledLineWidth = linewidth / scale
    svgLineWidth = str(scaledLineWidth) + 'px'
    st = archUserParameters.GetFloat("CutLineThickness", 2)
    svgCutLineWidth = str(scaledLineWidth * st) + 'px'
    yt = archUserParameters.GetFloat("SymbolLineThickness", 0.6)
    svgSymbolLineWidth = str(linewidth * yt)
    hiddenPattern = archUserParameters.GetString("archHiddenPattern", "30,10")
    svgHiddenPattern = hiddenPattern.replace(" ", "")
    fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
    fillpattern += ' x="0" y="0" width="10" height="10">'
    fillpattern += '<g>'
    fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>'
    svg = ''

    # generating SVG
    if renderMode in ["Solid", 1]:
        # render using the Arch Vector Renderer
        import ArchVRM, WorkingPlane
        wp = WorkingPlane.plane()
        wp.setFromPlacement(section.Placement)
        #wp.inverse()
        render = ArchVRM.Renderer()
        render.setWorkingPlane(wp)
        render.addObjects(objs)
        if showHidden:
            render.cut(section.Shape, showHidden)
        else:
            render.cut(section.Shape)
        svg += '<g transform="scale(1,-1)">\n'
        svg += render.getViewSVG(linewidth=svgLineWidth)
        svg += fillpattern
        svg += render.getSectionSVG(linewidth=svgCutLineWidth,
                                    fillpattern="sectionfill")
        if showHidden:
            svg += render.getHiddenSVG(linewidth=svgLineWidth)
        svg += '</g>\n'
        # print(render.info())

    else:
        # render using the Drawing module
        import Drawing, Part
        shapes, hshapes, sshapes, cutface, cutvolume, invcutvolume = getCutShapes(
            objs, section, showHidden)
        if shapes:
            baseshape = Part.makeCompound(shapes)
            style = {
                'stroke': Draft.getrgb(lineColor),
                'stroke-width': svgLineWidth
            }
            svg += Drawing.projectToSVG(baseshape,
                                        direction,
                                        hStyle=style,
                                        h0Style=style,
                                        h1Style=style,
                                        vStyle=style,
                                        v0Style=style,
                                        v1Style=style)
        if hshapes:
            hshapes = Part.makeCompound(hshapes)
            style = {
                'stroke': Draft.getrgb(lineColor),
                'stroke-width': svgLineWidth,
                'stroke-dasharray': svgHiddenPattern
            }
            svg += Drawing.projectToSVG(hshapes,
                                        direction,
                                        hStyle=style,
                                        h0Style=style,
                                        h1Style=style,
                                        vStyle=style,
                                        v0Style=style,
                                        v1Style=style)
        if sshapes:
            if showFill:
                #svg += fillpattern
                svg += '<g transform="rotate(180)">\n'
                for s in sshapes:
                    if s.Edges:
                        #svg += Draft.getSVG(s,direction=direction.negative(),linewidth=0,fillstyle="sectionfill",color=(0,0,0))
                        # temporarily disabling fill patterns
                        svg += Draft.getSVG(s,
                                            direction=direction.negative(),
                                            linewidth=0,
                                            fillstyle=Draft.getrgb(fillColor),
                                            color=lineColor)
                svg += "</g>\n"
            sshapes = Part.makeCompound(sshapes)
            style = {
                'stroke': Draft.getrgb(lineColor),
                'stroke-width': svgCutLineWidth
            }
            svg += Drawing.projectToSVG(sshapes,
                                        direction,
                                        hStyle=style,
                                        h0Style=style,
                                        h1Style=style,
                                        vStyle=style,
                                        v0Style=style,
                                        v1Style=style)

    if drafts:
        if not techdraw:
            svg += '<g transform="scale(1,-1)">'
        for d in drafts:
            svg += Draft.getSVG(d,
                                scale=scale,
                                linewidth=svgSymbolLineWidth,
                                fontsize=fontsize,
                                direction=direction,
                                color=lineColor,
                                techdraw=techdraw,
                                rotation=rotation)
        if not techdraw:
            svg += '</g>'

    # filter out spaces not cut by the section plane
    if cutface and spaces:
        spaces = [
            s for s in spaces if s.Shape.BoundBox.intersect(cutface.BoundBox)
        ]
    if spaces:
        if not techdraw:
            svg += '<g transform="scale(1,-1)">'
        for s in spaces:
            svg += Draft.getSVG(s,
                                scale=scale,
                                linewidth=svgSymbolLineWidth,
                                fontsize=fontsize,
                                direction=direction,
                                color=lineColor,
                                techdraw=techdraw,
                                rotation=rotation)
        if not techdraw:
            svg += '</g>'

    # add additional edge symbols from windows
    cutwindows = []
    if cutface and windows:
        cutwindows = [
            w.Name for w in windows
            if w.Shape.BoundBox.intersect(cutface.BoundBox)
        ]
    if windows:
        sh = []
        for w in windows:
            if not hasattr(w.Proxy, "sshapes"):
                w.Proxy.execute(w)
            if hasattr(w.Proxy, "sshapes"):
                if w.Proxy.sshapes and (w.Name in cutwindows):
                    c = Part.makeCompound(w.Proxy.sshapes)
                    c.Placement = w.Placement
                    sh.append(c)
            # buggy for now...
            #if hasattr(w.Proxy,"vshapes"):
            #    if w.Proxy.vshapes:
            #        c = Part.makeCompound(w.Proxy.vshapes)
            #        c.Placement = w.Placement
            #        sh.append(c)
        if sh:
            if not techdraw:
                svg += '<g transform="scale(1,-1)">'
            for s in sh:
                svg += Draft.getSVG(s,
                                    scale=scale,
                                    linewidth=svgSymbolLineWidth,
                                    fontsize=fontsize,
                                    fillstyle="none",
                                    direction=direction,
                                    color=lineColor,
                                    techdraw=techdraw,
                                    rotation=rotation)
            if not techdraw:
                svg += '</g>'

    return svg
Example #34
0
    def makeStraightLanding(self, obj, edge, numberofsteps=None):

        "builds a landing from a straight edge"

        # general data
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps
        import Part, DraftGeomUtils
        v = DraftGeomUtils.vec(edge)
        vLength = Vector(v.x, v.y, 0)
        vWidth = vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0, 0, 1)),
                                                obj.Width.Value)
        vBase = edge.Vertexes[0].Point
        vNose = DraftVecUtils.scaleTo(vLength, -abs(obj.Nosing.Value))
        h = obj.Height.Value
        l = obj.Length.Value
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                l = obj.Base.Shape.Length
                if obj.Base.Shape.BoundBox.ZLength:
                    h = obj.Base.Shape.BoundBox.ZLength
        fLength = float(l - obj.Width.Value) / (numberofsteps - 2)
        fHeight = float(h) / numberofsteps
        a = math.atan(fHeight / fLength)
        print "landing data:", fLength, ":", fHeight

        # step
        p1 = self.align(vBase, obj.Align, vWidth)
        p1 = p1.add(vNose).add(Vector(0, 0, -abs(obj.TreadThickness.Value)))
        p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
        p3 = p2.add(vWidth)
        p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
        step = Part.Face(Part.makePolygon([p1, p2, p3, p4, p1]))
        if obj.TreadThickness.Value:
            step = step.extrude(Vector(0, 0, abs(obj.TreadThickness.Value)))
            self.steps.append(step)
        else:
            self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        p7 = None
        p1 = p1.add(DraftVecUtils.neg(vNose))
        p2 = p1.add(Vector(0, 0, -fHeight)).add(
            Vector(0, 0, -obj.StructureThickness.Value / math.cos(a)))
        resheight = p1.sub(p2).Length - obj.StructureThickness.Value
        reslength = resheight / math.tan(a)
        p3 = p2.add(DraftVecUtils.scaleTo(vLength, reslength)).add(
            Vector(0, 0, resheight))
        p6 = p1.add(vLength)
        if obj.TreadThickness.Value:
            p7 = p6.add(Vector(0, 0, obj.TreadThickness.Value))

        reslength = fLength + (
            obj.StructureThickness.Value / math.sin(a) -
            (fHeight - obj.TreadThickness.Value) / math.tan(a))
        if p7:
            p5 = p7.add(DraftVecUtils.scaleTo(vLength, reslength))
        else:
            p5 = p6.add(DraftVecUtils.scaleTo(vLength, reslength))
        resheight = obj.StructureThickness.Value + obj.TreadThickness.Value
        reslength = resheight / math.tan(a)
        p4 = p5.add(DraftVecUtils.scaleTo(vLength, -reslength)).add(
            Vector(0, 0, -resheight))
        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:
                if p7:
                    struct = Part.Face(
                        Part.makePolygon([p1, p2, p3, p4, p5, p7, p6, p1]))
                else:
                    struct = Part.Face(
                        Part.makePolygon([p1, p2, p3, p4, p5, p6, p1]))
                evec = vWidth
                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,
                                                 obj.StructureOffset.Value)
                    struct.translate(mvec)
                    evec = DraftVecUtils.scaleTo(
                        evec, evec.Length - (2 * mvec.Length))
                struct = struct.extrude(evec)
        elif obj.Structure in ["One stringer", "Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                p1b = p1.add(Vector(0, 0, -fHeight))
                reslength = fHeight / math.tan(a)
                p1c = p1.add(DraftVecUtils.scaleTo(vLength, reslength))
                p5b = None
                p5c = None
                if obj.TreadThickness.Value:
                    reslength = obj.StructureThickness.Value / math.sin(a)
                    p5b = p5.add(DraftVecUtils.scaleTo(vLength, -reslength))
                    reslength = obj.TreadThickness.Value / math.tan(a)
                    p5c = p5b.add(DraftVecUtils.scaleTo(
                        vLength, -reslength)).add(
                            Vector(0, 0, -obj.TreadThickness.Value))
                    pol = Part.Face(
                        Part.makePolygon(
                            [p1c, p1b, p2, p3, p4, p5, p5b, p5c, p1c]))
                else:
                    pol = Part.Face(
                        Part.makePolygon([p1c, p1b, p2, p3, p4, p5, p1c]))
                evec = DraftVecUtils.scaleTo(vWidth, obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,
                                                     obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(
                            vWidth,
                            (vWidth.Length / 2) - obj.StringerWidth.Value / 2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,
                                                     obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1, s2])
        if struct:
            self.structures.append(struct)
Example #35
0
    def makeStraightStairs(self, obj, edge, numberofsteps=None):

        "builds a simple, straight staircase from a straight edge"

        # general data
        import Part, DraftGeomUtils
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps
        v = DraftGeomUtils.vec(edge)
        vLength = DraftVecUtils.scaleTo(
            v,
            float(edge.Length) / (numberofsteps - 1))
        vLength = Vector(vLength.x, vLength.y, 0)
        if round(v.z, Draft.precision()) != 0:
            h = v.z
        else:
            h = obj.Height.Value
        vHeight = Vector(0, 0, float(h) / numberofsteps)
        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0, 0, 1)),
                                       obj.Width.Value)
        vBase = edge.Vertexes[0].Point
        vNose = DraftVecUtils.scaleTo(vLength, -abs(obj.Nosing.Value))
        a = math.atan(vHeight.Length / vLength.Length)
        #print "stair data:",vLength.Length,":",vHeight.Length

        # steps
        for i in range(numberofsteps - 1):
            p1 = vBase.add((Vector(vLength).multiply(i)).add(
                Vector(vHeight).multiply(i + 1)))
            p1 = self.align(p1, obj.Align, vWidth)
            p1 = p1.add(vNose).add(Vector(0, 0,
                                          -abs(obj.TreadThickness.Value)))
            p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
            p3 = p2.add(vWidth)
            p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
            step = Part.Face(Part.makePolygon([p1, p2, p3, p4, p1]))
            if obj.TreadThickness.Value:
                step = step.extrude(Vector(0, 0,
                                           abs(obj.TreadThickness.Value)))
                self.steps.append(step)
            else:
                self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:
                for i in range(numberofsteps - 1):
                    if not lProfile:
                        lProfile.append(vBase)
                    last = lProfile[-1]
                    if len(lProfile) == 1:
                        last = last.add(
                            Vector(0, 0, -abs(obj.TreadThickness.Value)))
                    lProfile.append(last.add(vHeight))
                    lProfile.append(lProfile[-1].add(vLength))
                resHeight1 = obj.StructureThickness.Value / math.cos(a)
                lProfile.append(lProfile[-1].add(Vector(0, 0, -resHeight1)))
                resHeight2 = ((numberofsteps - 1) * vHeight.Length) - (
                    resHeight1 + obj.TreadThickness.Value)
                resLength = (vLength.Length / vHeight.Length) * resHeight2
                h = DraftVecUtils.scaleTo(vLength, -resLength)
                lProfile.append(lProfile[-1].add(Vector(h.x, h.y,
                                                        -resHeight2)))
                lProfile.append(vBase)
                #print lProfile
                pol = Part.makePolygon(lProfile)
                struct = Part.Face(pol)
                evec = vWidth
                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,
                                                 obj.StructureOffset.Value)
                    struct.translate(mvec)
                    evec = DraftVecUtils.scaleTo(
                        evec, evec.Length - (2 * mvec.Length))
                struct = struct.extrude(evec)
        elif obj.Structure in ["One stringer", "Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                hyp = math.sqrt(vHeight.Length**2 + vLength.Length**2)
                l1 = Vector(vLength).multiply(numberofsteps - 1)
                h1 = Vector(vHeight).multiply(numberofsteps - 1).add(
                    Vector(0, 0, -abs(obj.TreadThickness.Value)))
                p1 = vBase.add(l1).add(h1)
                p1 = self.align(p1, obj.Align, vWidth)
                lProfile.append(p1)
                h2 = (obj.StructureThickness.Value / vLength.Length) * hyp
                lProfile.append(lProfile[-1].add(Vector(0, 0, -abs(h2))))
                h3 = lProfile[-1].z - vBase.z
                l3 = (h3 / vHeight.Length) * vLength.Length
                v3 = DraftVecUtils.scaleTo(vLength, -l3)
                lProfile.append(lProfile[-1].add(Vector(0, 0,
                                                        -abs(h3))).add(v3))
                l4 = (obj.StructureThickness.Value / vHeight.Length) * hyp
                v4 = DraftVecUtils.scaleTo(vLength, -l4)
                lProfile.append(lProfile[-1].add(v4))
                lProfile.append(lProfile[0])
                #print lProfile
                pol = Part.makePolygon(lProfile)
                pol = Part.Face(pol)
                evec = DraftVecUtils.scaleTo(vWidth, obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,
                                                     obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(
                            vWidth,
                            (vWidth.Length / 2) - obj.StringerWidth.Value / 2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,
                                                     obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1, s2])
        if struct:
            self.structures.append(struct)
Example #36
0
    def execute(self,obj):

        import Part,DraftGeomUtils,math
        pl = obj.Placement
        w = self.getWire(obj)
        if not w:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the base path")+"\n")
            return
        if obj.OffsetStart.Value:
            e = w.Edges[0]
            v = e.Vertexes[-1].Point.sub(e.Vertexes[0].Point).normalize()
            v.multiply(obj.OffsetStart.Value)
            e = Part.LineSegment(e.Vertexes[0].Point.add(v),e.Vertexes[-1].Point).toShape()
            w = Part.Wire([e]+w.Edges[1:])
        if obj.OffsetEnd.Value:
            e = w.Edges[-1]
            v = e.Vertexes[0].Point.sub(e.Vertexes[-1].Point).normalize()
            v.multiply(obj.OffsetEnd.Value)
            e = Part.LineSegment(e.Vertexes[-1].Point.add(v),e.Vertexes[0].Point).toShape()
            w = Part.Wire(w.Edges[:-1]+[e])
        p = self.getProfile(obj)
        if not p:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the profile")+"\n")
            return
        # move and rotate the profile to the first point
        if hasattr(p,"CenterOfMass"):
            c = p.CenterOfMass
        else:
            c = p.BoundBox.Center
        delta = w.Vertexes[0].Point-c
        p.translate(delta)
        import Draft
        if Draft.getType(obj.Base) == "BezCurve":
            v1 = obj.Base.Placement.multVec(obj.Base.Points[1])-w.Vertexes[0].Point
        else:
            v1 = w.Vertexes[1].Point-w.Vertexes[0].Point
        v2 = DraftGeomUtils.getNormal(p)
        rot = FreeCAD.Rotation(v2,v1)
        p.rotate(w.Vertexes[0].Point,rot.Axis,math.degrees(rot.Angle))
        shapes = []
        try:
            if p.Faces:
                for f in p.Faces:
                    sh = w.makePipeShell([f.OuterWire],True,False,2)
                    for shw in f.Wires:
                        if shw.hashCode() != f.OuterWire.hashCode():
                            sh2 = w.makePipeShell([shw],True,False,2)
                            sh = sh.cut(sh2)
                    shapes.append(sh)
            elif p.Wires:
                for pw in p.Wires:
                    sh = w.makePipeShell([pw],True,False,2)
                    shapes.append(sh)
        except Exception:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the pipe")+"\n")
        else:
            if len(shapes) == 0:
                return
            elif len(shapes) == 1:
                sh = shapes[0]
            else:
                sh = Part.makeCompound(shapes)
            obj.Shape = sh
            if obj.Base:
                obj.Length = w.Length
            else:
                obj.Placement = pl
Example #37
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
Example #38
0
    def execute(self, obj):

        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        pl = obj.Placement

        # test properties
        if not obj.Base:
            FreeCAD.Console.PrintLog(obj.Label + ": no base\n")
            return
        if not hasattr(obj.Base, "Shape"):
            FreeCAD.Console.PrintLog(obj.Label + ": invalid base\n")
            return
        if obj.VerticalMullionProfile:
            if not hasattr(obj.VerticalMullionProfile, "Shape"):
                FreeCAD.Console.PrintLog(
                    obj.Label + ": invalid vertical mullion profile\n")
                return
        if obj.HorizontalMullionProfile:
            if not hasattr(obj.HorizontalMullionProfile, "Shape"):
                FreeCAD.Console.PrintLog(
                    obj.Label + ": invalid horizontal mullion profile\n")
                return
        if obj.DiagonalMullionProfile:
            if not hasattr(obj.DiagonalMullionProfile, "Shape"):
                FreeCAD.Console.PrintLog(
                    obj.Label + ": invalid diagonal mullion profile\n")
                return

        facets = []

        faces = []
        if obj.Base.Shape.Faces:
            faces = obj.Base.Shape.Faces
        elif obj.Height.Value and obj.VerticalDirection.Length:
            ext = FreeCAD.Vector(obj.VerticalDirection)
            ext.normalize()
            ext = ext.multiply(obj.Height.Value)
            faces = [edge.extrude(ext) for edge in obj.Base.Shape.Edges]
        if not faces:
            FreeCAD.Console.PrintLog(obj.Label +
                                     ": unable to build base faces\n")
            return

        # subdivide the faces into quads
        for face in faces:

            fp = face.ParameterRange

            # guessing horizontal/vertical directions
            vdir = obj.VerticalDirection
            if not vdir.Length:
                vdir = FreeCAD.Vector(0, 0, 1)
            vdir.normalize()
            basevector = face.valueAt(fp[1],
                                      fp[3]).sub(face.valueAt(fp[0], fp[2]))
            a = basevector.getAngle(vdir)
            if (a <= math.pi / 2 + ANGLETOLERANCE) and (
                    a >= math.pi / 2 - ANGLETOLERANCE):
                facedir = True
                vertsec = obj.VerticalSections
                horizsec = obj.HorizontalSections
            else:
                facedir = False
                vertsec = obj.HorizontalSections
                horizsec = obj.VerticalSections

            hstep = (fp[1] - fp[0])
            if vertsec:
                hstep = hstep / vertsec
            vstep = (fp[3] - fp[2])
            if horizsec:
                vstep = vstep / horizsec

            # construct facets
            for i in range(vertsec or 1):
                for j in range(horizsec or 1):
                    p0 = face.valueAt(fp[0] + i * hstep, fp[2] + j * vstep)
                    p1 = face.valueAt(fp[0] + (i + 1) * hstep,
                                      fp[2] + j * vstep)
                    p2 = face.valueAt(fp[0] + (i + 1) * hstep,
                                      fp[2] + (j + 1) * vstep)
                    p3 = face.valueAt(fp[0] + i * hstep,
                                      fp[2] + (j + 1) * vstep)
                    facet = Part.Face(Part.makePolygon([p0, p1, p2, p3, p0]))
                    facets.append(facet)

        if not facets:
            FreeCAD.Console.PrintLog(obj.Label +
                                     ": failed to subdivide shape\n")
            return

        baseshape = Part.makeShell(facets)

        # make edge/normal relation table
        edgetable = {}
        for face in baseshape.Faces:
            for edge in face.Edges:
                ec = edge.hashCode()
                if ec in edgetable:
                    edgetable[ec].append(face)
                else:
                    edgetable[ec] = [face]
        self.edgenormals = {}
        for ec, faces in edgetable.items():
            if len(faces) == 1:
                self.edgenormals[ec] = faces[0].normalAt(0, 0)
            else:
                n = faces[0].normalAt(0, 0).add(faces[1].normalAt(0, 0))
                if n.Length > 0.001:
                    n.normalize()
                else:
                    # adjacent faces have same normals
                    n = faces[0].normalAt(0, 0)
                self.edgenormals[ec] = n

        # sort edges between vertical/horizontal
        hedges = []
        vedges = []
        for edge in baseshape.Edges:
            v = edge.Vertexes[-1].Point.sub(edge.Vertexes[0].Point)
            a = v.getAngle(vdir)
            if (a <= math.pi / 2 + ANGLETOLERANCE) and (
                    a >= math.pi / 2 - ANGLETOLERANCE):
                hedges.append(edge)
            else:
                vedges.append(edge)

        # construct vertical mullions
        vmullions = []
        vprofile = self.getMullionProfile(obj, "Vertical")
        if vprofile and vertsec:
            for vedge in vedges:
                vn = self.edgenormals[vedge.hashCode()]
                if (vn.x != 0) or (vn.y != 0):
                    avn = FreeCAD.Vector(vn.x, vn.y, 0)
                    rot = FreeCAD.Rotation(FreeCAD.Vector(0, -1, 0), avn)
                else:
                    rot = FreeCAD.Rotation()
                if obj.VerticalMullionAlignment:
                    ev = vedge.Vertexes[-1].Point.sub(vedge.Vertexes[0].Point)
                    rot = FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0),
                                           ev).multiply(rot)
                vmullions.append(
                    self.makeMullion(vedge, vprofile, rot, obj.CenterProfiles))

        # construct horizontal mullions
        hmullions = []
        hprofile = self.getMullionProfile(obj, "Horizontal")
        if hprofile and horizsec:
            for hedge in hedges:
                rot = FreeCAD.Rotation(FreeCAD.Vector(0, 1, 0), -90)
                vn = self.edgenormals[hedge.hashCode()]
                if (vn.x != 0) or (vn.y != 0):
                    avn = FreeCAD.Vector(vn.x, vn.y, 0)
                    rot = FreeCAD.Rotation(FreeCAD.Vector(0, -1, 0),
                                           avn).multiply(rot)
                    if obj.HorizontalMullionAlignment:
                        rot = FreeCAD.Rotation(avn, vn).multiply(rot)
                hmullions.append(
                    self.makeMullion(hedge, hprofile, rot, obj.CenterProfiles))

        # construct panels
        panels = []
        dedges = []
        if obj.PanelThickness.Value:
            for face in baseshape.Faces:
                verts = [v.Point for v in face.OuterWire.OrderedVertexes]
                if len(verts) == 4:
                    if DraftGeomUtils.isPlanar(verts):
                        panel = self.makePanel(verts, obj.PanelThickness.Value)
                        panels.append(panel)
                    else:
                        verts1 = [verts[0], verts[1], verts[2]]
                        panel = self.makePanel(verts1,
                                               obj.PanelThickness.Value)
                        panels.append(panel)
                        verts2 = [verts[0], verts[2], verts[3]]
                        panel = self.makePanel(verts2,
                                               obj.PanelThickness.Value)
                        panels.append(panel)
                        dedges.append(Part.makeLine(verts[0], verts[2]))

        # construct diagonal mullions
        dmullions = []
        if dedges:
            n = (dedges[0].Vertexes[-1].Point.sub(dedges[0].Point))
            dprofile = self.getMullionProfile(obj, "Diagonal")
            if dprofile:
                for dedge in dedges:
                    rot = FreeCAD.Rotation(
                        FreeCAD.Vector(0, 0, 1),
                        dedge.Vertexes[-1].Point.sub(dedge.Vertexes[0].Point))
                    dmullions.append(
                        self.makeMullion(dedge, dprofile, rot,
                                         obj.CenterProfiles))

        # perform subtractions
        if obj.Refine:
            subvmullion = None
            subhmullion = None
            subdmullion = None
            if vmullions:
                subvmullion = vmullions[0].copy()
                for m in vmullions[1:]:
                    subvmullion = subvmullion.fuse(m)
            if hmullions:
                subhmullion = hmullions[0].copy()
                for m in hmullions[1:]:
                    subhmullion = subhmullion.fuse(m)
            if dmullions:
                subdmullion = dmullions[0].copy()
                for m in dmullions[1:]:
                    subdmullion = subdmullion.fuse(m)
            if subvmullion:
                hmullions = [m.cut(subvmullion) for m in hmullions]
                if subhmullion:
                    dmullions = [m.cut(subvmullion) for m in dmullions]
                    dmullions = [m.cut(subhmullion) for m in dmullions]
                    panels = [m.cut(subvmullion) for m in panels]
                    panels = [m.cut(subhmullion) for m in panels]
                    if subdmullion:
                        panels = [m.cut(subdmullion) for m in panels]

        # mount shape
        obj.VerticalMullionNumber = len(vmullions)
        obj.HorizontalMullionNumber = len(hmullions)
        obj.DiagonalMullionNumber = len(dmullions)
        obj.PanelNumber = len(panels)
        shape = Part.makeCompound(vmullions + hmullions + dmullions + panels)
        shape = self.processSubShapes(obj, shape, pl)
        self.applyShape(obj, shape, pl)
Example #39
0
    def execute(self, obj):
        """This method is run when the object is created or recomputed."""
        import Part

        if (obj.Length.Value == 0) or (obj.Height.Value == 0):
            obj.positionBySupport()
            return

        plm = obj.Placement

        shape = None

        if hasattr(obj, "Rows") and hasattr(obj, "Columns"):
            # TODO: verify if this is needed:
            if obj.Rows > 1:
                rows = obj.Rows
            else:
                rows = 1
            if obj.Columns > 1:
                columns = obj.Columns
            else:
                columns = 1
            # TODO: till here

            if (rows > 1) or (columns > 1):
                shapes = []
                l = obj.Length.Value / columns
                h = obj.Height.Value / rows
                for i in range(columns):
                    for j in range(rows):
                        p1 = App.Vector(i * l, j * h, 0)
                        p2 = App.Vector(p1.x + l, p1.y, p1.z)
                        p3 = App.Vector(p1.x + l, p1.y + h, p1.z)
                        p4 = App.Vector(p1.x, p1.y + h, p1.z)
                        p = Part.makePolygon([p1, p2, p3, p4, p1])
                        if "ChamferSize" in obj.PropertiesList:
                            if obj.ChamferSize.Value != 0:
                                w = DraftGeomUtils.filletWire(
                                    p, obj.ChamferSize.Value, chamfer=True)
                                if w:
                                    p = w
                        if "FilletRadius" in obj.PropertiesList:
                            if obj.FilletRadius.Value != 0:
                                w = DraftGeomUtils.filletWire(
                                    p, obj.FilletRadius.Value)
                                if w:
                                    p = w
                        if hasattr(obj, "MakeFace"):
                            if obj.MakeFace:
                                p = Part.Face(p)
                        shapes.append(p)
                if shapes:
                    shape = Part.makeCompound(shapes)

        if not shape:
            p1 = App.Vector(0, 0, 0)
            p2 = App.Vector(p1.x + obj.Length.Value, p1.y, p1.z)
            p3 = App.Vector(p1.x + obj.Length.Value, p1.y + obj.Height.Value,
                            p1.z)
            p4 = App.Vector(p1.x, p1.y + obj.Height.Value, p1.z)
            shape = Part.makePolygon([p1, p2, p3, p4, p1])
            if "ChamferSize" in obj.PropertiesList:
                if obj.ChamferSize.Value != 0:
                    w = DraftGeomUtils.filletWire(shape,
                                                  obj.ChamferSize.Value,
                                                  chamfer=True)
                    if w:
                        shape = w
            if "FilletRadius" in obj.PropertiesList:
                if obj.FilletRadius.Value != 0:
                    w = DraftGeomUtils.filletWire(shape,
                                                  obj.FilletRadius.Value)
                    if w:
                        shape = w
            if hasattr(obj, "MakeFace"):
                if obj.MakeFace:
                    shape = Part.Face(shape)
            else:
                shape = Part.Face(shape)

        obj.Shape = shape

        if hasattr(obj, "Area") and hasattr(shape, "Area"):
            obj.Area = shape.Area

        obj.Placement = plm

        obj.positionBySupport()
    def execute(self, obj):

        if self.clone(obj):
            return

        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].Shape:
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.InList[0]
        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print obj.Rounding
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        size = (ArchCommands.projectToVector(father.Shape.copy(), axis)).Length
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)  #.normalize()
                # don't normalize so the vector can also be used to determine the distance
                size = axis.Length
        #print axis
        #print size
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return

        # all tests ok!
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
        except Part.OCCError:
            print "Arch: error sweeping rebar profile along the base sketch"
            return
        # building final shape
        shapes = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis, size / 2)
            bar.translate(offset)
            shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis, interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        bar.translate(baseoffset)
                    shapes.append(bar)
                else:
                    bar = bar.copy()
                    bar.translate(vinterval)
                    shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
Example #41
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)

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

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

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

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

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

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

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

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

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Example #42
0
    def writeObject(self,obj,view):

        if not view.Source:
            return ""
        if obj.Renderer:
            try:
                renderer = importlib.import_module("renderers."+obj.Renderer)
            except ImportError:
                FreeCAD.Console.PrintError(translate("Render","Error importing renderer")+" "+str(obj.Renderer))
                return ""
            else:

                # get color and alpha
                mat = None
                color = None
                alpha = None
                if view.Material:
                    mat = view.Material
                else:
                    if "Material" in view.Source.PropertiesList:
                        if view.Source.Material:
                            mat = view.Source.Material
                if mat:
                    if "Material" in mat.PropertiesList:
                        if "DiffuseColor" in mat.Material:
                            color = mat.Material["DiffuseColor"].strip("(").strip(")").split(",")[:3]
                        if "Transparency" in mat.Material:
                            if float(mat.Material["Transparency"]) > 0:
                                alpha = 1.0-float(mat.Material["Transparency"])
                            else:
                                alpha = 1.0
                if view.Source.ViewObject:
                    if not color:
                        if hasattr(view.Source.ViewObject,"ShapeColor"):
                            color = view.Source.ViewObject.ShapeColor[:3]
                    if not alpha:
                        if hasattr(view.Source.ViewObject,"Transparency"):
                            if view.Source.ViewObject.Transparency > 0:
                                alpha = 1.0-(float(view.Source.ViewObject.Transparency)/100.0)
                if not color:
                    color = (1.0, 1.0, 1.0)
                if not alpha:
                    alpha = 1.0

                # get mesh
                import Draft
                import Part
                import MeshPart
                mesh = None
                if hasattr(view.Source,"Group"):
                    shps = [o.Shape for o in Draft.getGroupContents(view.Source) if hasattr(o,"Shape")]
                    mesh = MeshPart.meshFromShape(Shape=Part.makeCompound(shps),
                                               LinearDeflection=0.1,
                                               AngularDeflection=0.523599,
                                               Relative=False)
                elif view.Source.isDerivedFrom("Part::Feature"):
                    mesh = MeshPart.meshFromShape(Shape=view.Source.Shape,
                                               LinearDeflection=0.1,
                                               AngularDeflection=0.523599,
                                               Relative=False)
                elif view.Source.isDerivedFrom("Mesh::Feature"):
                    mesh = view.Source.Mesh
                if not mesh:
                    return ""

                return renderer.writeObject(view,mesh,color,alpha)
Example #43
0
	def execute(self, fp):
		""" Called when a recomputation is needed. 
		@param fp Part::FeaturePython object.
		"""
		fp.Shape = Part.makeCompound(fp.Shape.Solids)
Example #44
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
Example #45
0
def find_poloidal_upper_and_lower_faces(front_face, back_face, envelope,
                                        envelope_front_face_id,
                                        envelope_back_face_id):

    list_of_edges_to_fillet = []
    list_of_edge_to_fillet_ids = []
    list_of_edge_to_fillet_lengths = []

    for counter, edge in enumerate(front_face.Edges):
        if round(edge.Vertexes[0].Point.z - edge.Vertexes[1].Point.z) == 0:
            list_of_edges_to_fillet.append(edge)
            list_of_edge_to_fillet_ids.append(counter)
            list_of_edge_to_fillet_lengths.append(edge.Length)

    for counter, edge in enumerate(back_face.Edges):
        if round(edge.Vertexes[0].Point.z - edge.Vertexes[1].Point.z) == 0:
            list_of_edges_to_fillet.append(edge)
            list_of_edge_to_fillet_ids.append(counter)
            list_of_edge_to_fillet_lengths.append(edge.Length)

    faces_with_vectors_not_pointing_in_y = []

    for i, face in enumerate(envelope.Faces):
        if i != envelope_front_face_id and i != envelope_back_face_id:
            #print(face.normalAt(0, 0))
            if abs(face.normalAt(0, 0).y) < max(abs(face.normalAt(0, 0).x),
                                                abs(face.normalAt(0, 0).z)):
                faces_with_vectors_not_pointing_in_y.append(face)

    if len(faces_with_vectors_not_pointing_in_y) == 2:
        if faces_with_vectors_not_pointing_in_y[
                0].CenterOfMass.z > faces_with_vectors_not_pointing_in_y[
                    1].CenterOfMass.z:

            return faces_with_vectors_not_pointing_in_y
        else:
            return faces_with_vectors_not_pointing_in_y[::-1]
    else:
        top_bottom_faces = []

        for i, face in enumerate(envelope.Faces):
            if i != self.envelope_front_face_id and i != self.envelope_back_face_id:
                list_of_z_points = []
                for vertexes in face.Vertexes:
                    list_of_z_points.append(round(vertexes.Point.z, 1))
                    #print('   ',vertexes.Point.z)
                #print(list_of_z_points)
                number_of_matching_z_points = Counter(list_of_z_points)

                if number_of_matching_z_points.values() == [
                        2, 2
                ] or number_of_matching_z_points.values() == [4]:

                    top_bottom_faces.append(face)

        if len(top_bottom_faces) == 2:

            if top_bottom_faces[0].CenterOfMass.Point.z > top_bottom_faces[
                    1].CenterOfMass.Point.z:
                return top_bottom_faces
            else:
                return top_bottom_faces[::-1]

        else:

            Part.makeCompound(top_bottom_faces).exportStep(
                os.path.join(self.output_folder,
                             'error_top_bottom_faces.step'))
            Part.makeCompound([front_face]).exportStep(
                os.path.join(self.output_folder,
                             'error_top_bottom_faces_ff.step'))

            raise ValueError('method failed, on ' +
                             self.envelope_directory_filename +
                             ' to many or few faces found')
Example #46
0
    def execute(self, obj):
        import Part, math, DraftGeomUtils
        pl = obj.Placement
        self.baseface = None

        base = None
        if obj.Base and obj.Angles:
            w = None
            if obj.Base.isDerivedFrom("Part::Feature"):
                if (obj.Base.Shape.Faces and obj.Face):
                    w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
                elif obj.Base.Shape.Wires:
                    w = obj.Base.Shape.Wires[0]
            if w:
                if w.isClosed():
                    self.profilsDico = []
                    self.shps = []
                    self.subVolshps = []
                    heights = []
                    edges = DraftGeomUtils.sortEdges(w.Edges)
                    l = len(edges)
                    print("le contour contient " + str(l) + " aretes")
                    for i in range(l):
                        self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i],
                                                obj.IdRel[i], obj.Overhang[i],
                                                obj.Thickness[i])
                    for i in range(l):
                        self.calcMissingData(i)
                    for i in range(l):
                        self.calcEdgeGeometry(edges, i)
                    for i in range(l):
                        self.calcDraftEdges(i)
                    for i in range(l):
                        self.calcEave(i)
                    for p in self.profilsDico:
                        heights.append(p["height"])
                    obj.Heights = heights
                    for i in range(l):
                        self.getRoofPaneProject(i)
                        profilCurrent = self.findProfil(i)
                        midpoint = DraftGeomUtils.findMidpoint(
                            profilCurrent["edge"])
                        ptsPaneProject = profilCurrent["points"]
                        lp = len(ptsPaneProject)
                        if lp != 0:
                            #print FreeCAD.Vector(ptsPaneProject[0])
                            ptsPaneProject.append(ptsPaneProject[0])
                            edgesWire = []
                            for p in range(lp):
                                edge = Part.makeLine(ptsPaneProject[p],
                                                     ptsPaneProject[p + 1])
                                edgesWire.append(edge)
                            wire = Part.Wire(edgesWire)
                            d = wire.BoundBox.DiagonalLength
                            thicknessV = profilCurrent["thickness"] / (
                                math.cos(math.radians(profilCurrent["angle"])))
                            overhangV = profilCurrent["overhang"] * math.tan(
                                math.radians(profilCurrent["angle"]))
                            if wire.isClosed():
                                f = Part.Face(wire)
                                #Part.show(f)
                                f = f.extrude(
                                    FreeCAD.Vector(
                                        0, 0, profilCurrent["height"] +
                                        2 * thicknessV + 2 * overhangV))
                                f.translate(
                                    FreeCAD.Vector(0.0, 0.0, -2 * overhangV))
                            ptsPaneProfil = [
                                FreeCAD.Vector(-profilCurrent["overhang"],
                                               -overhangV, 0.0),
                                FreeCAD.Vector(profilCurrent["run"],
                                               profilCurrent["height"], 0.0),
                                FreeCAD.Vector(
                                    profilCurrent["run"],
                                    profilCurrent["height"] + thicknessV, 0.0),
                                FreeCAD.Vector(-profilCurrent["overhang"],
                                               -overhangV + thicknessV, 0.0)
                            ]
                            self.createProfilShape(ptsPaneProfil, midpoint,
                                                   profilCurrent["rot"],
                                                   profilCurrent["vec"],
                                                   profilCurrent["run"], d,
                                                   self.shps, f)
                            ## subVolume shape
                            ptsSubVolumeProfil = [
                                FreeCAD.Vector(-profilCurrent["overhang"],
                                               -overhangV, 0.0),
                                FreeCAD.Vector(profilCurrent["run"],
                                               profilCurrent["height"], 0.0),
                                FreeCAD.Vector(profilCurrent["run"],
                                               profilCurrent["height"] + 10000,
                                               0.0),
                                FreeCAD.Vector(0.0,
                                               profilCurrent["height"] + 10000,
                                               0.0)
                            ]
                            self.createProfilShape(ptsSubVolumeProfil,
                                                   midpoint,
                                                   profilCurrent["rot"],
                                                   profilCurrent["vec"],
                                                   profilCurrent["run"], d,
                                                   self.subVolshps, f)

                    ## SubVolume
                    self.sub = self.subVolshps.pop()
                    for s in self.subVolshps:
                        self.sub = self.sub.fuse(s)
                    self.sub = self.sub.removeSplitter()
                    if not self.sub.isNull():
                        if not DraftGeomUtils.isNull(pl):
                            self.sub.Placement = pl
                    ## BaseVolume
                    base = Part.makeCompound(self.shps)
                    if not base.isNull():
                        if not DraftGeomUtils.isNull(pl):
                            base.Placement = pl
        base = self.processSubShapes(obj, base)
        if base:
            if not base.isNull():
                obj.Shape = base
Example #47
0
    def makeRibs(self, obj):
        pl = obj.Placement
        ribs = []
        curvebox = FreeCAD.BoundBox(float("-inf"), float("-inf"),
                                    float("-inf"), float("inf"), float("inf"),
                                    float("inf"))

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

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

        areavec = Vector(curvebox.XLength, curvebox.YLength, curvebox.ZLength)
        deltavec = areavec.scale(
            obj.Axis.x, obj.Axis.y,
            obj.Axis.z) - (obj.OffsetStart + obj.OffsetEnd) * obj.Axis
        sections = int(obj.Items)
        startvec = Vector(curvebox.XMin, curvebox.YMin, curvebox.ZMin)
        if obj.Axis.x < 0: startvec.x = curvebox.XMax
        if obj.Axis.y < 0: startvec.y = curvebox.YMax
        if obj.Axis.z < 0: startvec.z = curvebox.ZMax
        pos0 = startvec + (obj.OffsetStart * obj.Axis)

        for x in range(0, sections):
            if sections > 1:
                d = CurvedShapes.distribute(x / (sections - 1),
                                            obj.Distribution,
                                            obj.DistributionReverse)

                posvec = pos0 + (deltavec * d)
            else:
                posvec = pos0

            dolly = self.makeRib(obj, posvec)
            if dolly:
                if not obj.Twist == 0:
                    dolly.rotate(dolly.BoundBox.Center, obj.Axis,
                                 obj.Twist * posvec.Length / areavec.Length)
                ribs.append(dolly)

        if (obj.Surface or obj.Solid) and obj.Items > 1:
            obj.Shape = CurvedShapes.makeSurfaceSolid(ribs, obj.Solid)
        else:
            obj.Shape = Part.makeCompound(ribs)

        obj.Placement = pl

        if self.extract:
            CompoundTools.Explode.explodeCompound(obj)
            obj.ViewObject.hide()
Example #48
0
def createAnnotation(annotation,doc,ifcscale,preferences):
    """creates an annotation object"""

    anno = None
    if annotation.is_a("IfcGrid"):
        axes = []
        uvwaxes = ()
        if annotation.UAxes:
            uvwaxes = annotation.UAxes
        if annotation.VAxes:
            uvwaxes = uvwaxes + annotation.VAxes
        if annotation.WAxes:
            uvwaxes = uvwaxes + annotation.WAxes
        for axis in uvwaxes:
            if axis.AxisCurve:
                sh = get2DShape(axis.AxisCurve,ifcscale)
                if sh and (len(sh[0].Vertexes) == 2):  # currently only straight axes are supported
                    sh = sh[0]
                    l = sh.Length
                    pl = FreeCAD.Placement()
                    pl.Base = sh.Vertexes[0].Point
                    pl.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0,1,0),sh.Vertexes[-1].Point.sub(sh.Vertexes[0].Point))
                    o = Arch.makeAxis(1,l)
                    o.Length = l
                    o.Placement = pl
                    o.CustomNumber = axis.AxisTag
                    axes.append(o)
        if axes:
            name = "Grid"
            grid_placement = None
            if annotation.Name:
                name = annotation.Name
                if six.PY2:
                    name = name.encode("utf8")
            if annotation.ObjectPlacement:
                # https://forum.freecadweb.org/viewtopic.php?f=39&t=40027
                grid_placement = getPlacement(annotation.ObjectPlacement,scaling=1)
            if preferences['PREFIX_NUMBERS']:
                name = "ID" + str(aid) + " " + name
            anno = Arch.makeAxisSystem(axes,name)
            if grid_placement:
                anno.Placement = grid_placement
        print(" axis")
    else:
        name = "Annotation"
        if annotation.Name:
            name = annotation.Name
            if six.PY2:
                name = name.encode("utf8")
        if "annotation" not in name.lower():
            name = "Annotation " + name
        if preferences['PREFIX_NUMBERS']: name = "ID" + str(aid) + " " + name
        shapes2d = []
        for rep in annotation.Representation.Representations:
            if rep.RepresentationIdentifier in ["Annotation","FootPrint","Axis"]:
                sh = get2DShape(rep,ifcscale)
                if sh in doc.Objects:
                    # dirty hack: get2DShape might return an object directly if non-shape based (texts for ex)
                    anno = sh
                else:
                    shapes2d.extend(sh)
        if shapes2d:
            import Part
            sh = Part.makeCompound(shapes2d)
            #if preferences['DEBUG']: print(" shape")
            anno = doc.addObject("Part::Feature",name)
            anno.Shape = sh
            p = getPlacement(annotation.ObjectPlacement,ifcscale)
            if p:  # and annotation.is_a("IfcAnnotation"):
                anno.Placement = p
        #else:
            #if preferences['DEBUG']: print(" no shape")

    return anno
Example #49
0
    def execute(self, obj):
        """ Compute the wall shape as boolean operations among the component objects """


        # print("running " + obj.Name + " execute() method\n")
        import Part

        # gather base wall_shape (from obj.BaseGeometry or from default shape)
        wall_shape = None
        if hasattr(obj, "BaseGeometry") and obj.BaseGeometry:
            wall_shape = self.get_shape_from_base_geometry(obj)
        else:
            wall_shape = self.get_default_shape(obj)
        
        if wall_shape is None:
            return

        """
        Perform boolean operations between the base shape and 
        Additions, Subtractions, and Openings.

        Openings have to provide a proper shape to cut the wall through
        opening.Proxy.get_void_shape(opening) method that returns a Part Shape
        already in the right relative position.
        If the user wants to use a random shape to cut the wall he will use 
        the Subtractions list.
        """
        if hasattr(obj, "Additions") and obj.Additions:
            # get wall base shape from BaseGeometry objects
            shape_collection = []
            for o in obj.Additions:
                if hasattr(o, "Shape") and not o.Shape.isNull():
                    shape_collection.append(o.Shape)
            if shape_collection:
                shape_collection.append(wall_shape)
                # TODO: Is it better to fuse the additions instead of grouping them with a compound?
                wall_shape = Part.makeCompound(shape_collection)

        # subtract Subtractions
        if hasattr(obj, "Subtractions") and obj.Subtractions:
            for o in obj.Subtractions:
                cut_shape = None
                if o in obj.Group and hasattr(o, "Shape"):
                    # subtraction object is inside the wall
                    relative_placement = o.Placement
                    if hasattr(o, "InList") and o.InList[0] != obj:
                        # dont' remember why this is necessary...
                        relative_placement = o.InList[0].Placement.multiply(o.Placement)
                    cut_shape = o.Shape.copy()
                    cut_shape.Placement = relative_placement
                elif hasattr(o, "Shape"):
                    # subtraction object is not inside the wall, compute it's correct relative placement
                    global_placement = o.getGlobalPlacement()
                    relative_placement = obj.getGlobalPlacement().inverse().multiply(global_placement)
                    cut_shape = o.Shape.copy()
                    cut_shape.Placement = relative_placement

                if cut_shape is not None:
                    wall_shape = wall_shape.cut(cut_shape)

        if hasattr(obj, "Openings") and obj.Openings:
            # objects marked as Openings must be appropriate Opening objects to cut the wall
            # TODO: Add a flag to also subtract window positive shapes from wall
            for o in obj.Openings:
                # cut opening void
                void = None
                if o in obj.Group and hasattr(o, "VoidShape"):
                    void = o.VoidShape.copy()
                elif hasattr(o, "VoidShape"):
                    # opening object is not inside the wall, compute it's correct relative placement
                    global_placement = o.getGlobalPlacement()
                    relative_placement = obj.getGlobalPlacement().inverse().multiply(global_placement)
                    void = o.VoidShape.copy()
                    # void placement can be different from opening placement:
                    void.Placement = relative_placement.multiply(o.Placement.inverse().multiply(void.Placement))

                if void is not None:
                    wall_shape = wall_shape.cut(void)

        obj.Shape = wall_shape
Example #50
0
    def execute(self, obj):

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

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

        commandlist = []
        toolLoad = obj.ToolController

        self.depthparams = depth_params(
                clearance_height=obj.ClearanceHeight.Value,
                safe_height=obj.SafeHeight.Value,
                start_depth=obj.SafeHeight.Value,
                step_down=obj.StepDown,
                z_finish_step=obj.FinishDepth.Value,
                final_depth=obj.FinalDepth.Value,
                user_depths=None)

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

            if tool.Diameter == 0:
                FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.")
                return
            else:
                self.radius = tool.Diameter/2

        commandlist.append(Path.Command("(" + obj.Label + ")"))

        # Facing is done either against base objects
        if obj.Base:
            PathLog.debug("obj.Base: {}".format(obj.Base))
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                    else:
                        PathLog.debug('The base subobject is not a face')
                        return
            planeshape = Part.makeCompound(faces)
            PathLog.info("Working on a collection of faces {}".format(faces))

        # If no base object, do planing of top surface of entire model
        else:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                PathLog.debug("No base object. No parent job found")
                return
            baseobject = parentJob.Base
            if baseobject is None:
                PathLog.debug("Parent job exists but no Base Object")
                return
            planeshape = baseobject.Shape
            PathLog.info("Working on a shape {}".format(baseobject.Name))

        # if user wants the boundbox, calculate that
        PathLog.info("Boundary Shape: {}".format(obj.BoundaryShape))
        bb = planeshape.BoundBox
        if obj.BoundaryShape == 'Boundbox':
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(0, 0, 1))
            env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams)
        else:
            env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams)

        # save the envelope for reference
        obj.removalshape = env

        try:
            commandlist.extend(self._buildPathArea(obj, env).Commands)
        except Exception as e:
            FreeCAD.Console.PrintError(e)
            FreeCAD.Console.PrintError(translate("Path_MillFace", "The selected settings did not produce a valid path.\n"))

        # Let's finish by rapid to clearance...just for safety
        commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))

        path = Path.Path(commandlist)
        obj.Path = path
Example #52
0
    def execute(self, obj):

        "constructs the shape of the stairs"

        import Part
        self.steps = []
        self.pseudosteps = []
        self.structures = []
        pl = obj.Placement
        landings = 0

        # base tests
        if not obj.Width.Value:
            return
        if not obj.Height.Value:
            if not obj.Base:
                return
        if obj.NumberOfSteps < 2:
            return
        if obj.Base:
            if not obj.Base.isDerivedFrom("Part::Feature"):
                return
            if obj.Base.Shape.Solids:
                obj.Shape = obj.Base.Shape.copy()
                obj.Placement = FreeCAD.Placement(
                    obj.Base.Placement).multiply(pl)
                obj.TreadDepth = 0.0
                obj.RiserHeight = 0.0
                return
            if not obj.Base.Shape.Edges:
                return
            if obj.Base.Shape.Faces:
                return
            if (len(obj.Base.Shape.Edges) == 1):
                edge = obj.Base.Shape.Edges[0]
                if isinstance(edge.Curve, Part.Line):
                    if obj.Landings == "At center":
                        landings = 1
                        self.makeStraightStairsWithLanding(obj, edge)
                    else:
                        self.makeStraightStairs(obj, edge)
                else:
                    if obj.Landings == "At center":
                        landings = 1
                        self.makeCurvedStairsWithLandings(obj, edge)
                    else:
                        self.makeCurvedStairs(obj, edge)
        else:
            if not obj.Length.Value:
                return
            edge = Part.Line(Vector(0, 0, 0), Vector(obj.Length.Value, 0,
                                                     0)).toShape()
            if obj.Landings == "At center":
                landings = 1
                self.makeStraightStairsWithLanding(obj, edge)
            else:
                self.makeStraightStairs(obj, edge)

        if self.structures or self.steps:
            shape = Part.makeCompound(self.structures + self.steps)
            shape = self.processSubShapes(obj, shape, pl)
            obj.Shape = shape
            obj.Placement = pl
        elif self.pseudosteps:
            shape = Part.makeCompound(self.pseudosteps)
            obj.Shape = shape
            obj.Placement = pl
        else:
            print "unable to calculate a stairs shape"

        # compute step data
        if obj.NumberOfSteps > 1:
            l = obj.Length.Value
            h = obj.Height.Value
            if obj.Base:
                if obj.Base.isDerivedFrom("Part::Feature"):
                    l = obj.Base.Shape.Length
                    if obj.Base.Shape.BoundBox.ZLength:
                        h = obj.Base.Shape.BoundBox.ZLength
            obj.TreadDepth = float(l - (landings * obj.Width.Value)) / (
                obj.NumberOfSteps - (1 + landings))
            obj.RiserHeight = float(h) / obj.NumberOfSteps
            obj.BlondelRatio = obj.RiserHeight.Value * 2 + obj.TreadDepth.Value
Example #53
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        PathLog.track()

        if obj.UseComp:
            self.commandlist.append(
                Path.Command("(Compensated Tool Path. Diameter: " +
                             str(self.radius * 2) + ")"))
        else:
            self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))

        shapes = []
        self.profileshape = []  # pylint: disable=attribute-defined-outside-init

        baseSubsTuples = []
        subCount = 0
        allTuples = []

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            if obj.EnableRotation != 'Off':
                for p in range(0, len(obj.Base)):
                    (base, subsList) = obj.Base[p]
                    for sub in subsList:
                        subCount += 1
                        shape = getattr(base.Shape, sub)
                        if isinstance(shape, Part.Face):
                            rtn = False
                            (norm, surf) = self.getFaceNormAndSurf(shape)
                            (rtn, angle, axis,
                             praInfo) = self.faceRotationAnalysis(
                                 obj, norm, surf)  # pylint: disable=unused-variable
                            if rtn is True:
                                (clnBase, angle, clnStock,
                                 tag) = self.applyRotationalAnalysis(
                                     obj, base, angle, axis, subCount)
                                # Verify faces are correctly oriented - InverseAngle might be necessary
                                faceIA = getattr(clnBase.Shape, sub)
                                (norm, surf) = self.getFaceNormAndSurf(faceIA)
                                (rtn, praAngle, praAxis,
                                 praInfo) = self.faceRotationAnalysis(
                                     obj, norm, surf)  # pylint: disable=unused-variable
                                if rtn is True:
                                    PathLog.error(
                                        translate(
                                            "Path",
                                            "Face appears misaligned after initial rotation."
                                        ))
                                    if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
                                        (clnBase, clnStock,
                                         angle) = self.applyInverseAngle(
                                             obj, clnBase, clnStock, axis,
                                             angle)
                                    else:
                                        msg = translate(
                                            "Path",
                                            "Consider toggling the 'InverseAngle' property and recomputing."
                                        )
                                        PathLog.error(msg)
                                else:
                                    PathLog.debug(
                                        "Face appears to be oriented correctly."
                                    )

                                tup = clnBase, sub, tag, angle, axis, clnStock
                            else:
                                if self.warnDisabledAxis(obj, axis) is False:
                                    PathLog.debug(
                                        str(sub) + ": No rotation used")
                                axis = 'X'
                                angle = 0.0
                                tag = base.Name + '_' + axis + str(
                                    angle).replace('.', '_')
                                stock = PathUtils.findParentJob(obj).Stock
                                tup = base, sub, tag, angle, axis, stock

                            allTuples.append(tup)

                if subCount > 1:
                    msg = translate('Path',
                                    "Multiple faces in Base Geometry.") + "  "
                    msg += translate(
                        'Path', "Depth settings will be applied to all faces.")
                    PathLog.warning(msg)

                (Tags, Grps) = self.sortTuplesByIndex(
                    allTuples, 2)  # return (TagList, GroupList)
                subList = []
                for o in range(0, len(Tags)):
                    subList = []
                    for (base, sub, tag, angle, axis, stock) in Grps[o]:
                        subList.append(sub)

                    pair = base, subList, angle, axis, stock
                    baseSubsTuples.append(pair)
                # Efor
            else:
                PathLog.debug(
                    translate("Path", "EnableRotation property is 'Off'."))
                stock = PathUtils.findParentJob(obj).Stock
                for (base, subList) in obj.Base:
                    baseSubsTuples.append((base, subList, 0.0, 'X', stock))

            # for base in obj.Base:
            finish_step = obj.FinishDepth.Value if hasattr(
                obj, "FinishDepth") else 0.0
            for (base, subsList, angle, axis, stock) in baseSubsTuples:
                holes = []
                faces = []
                faceDepths = []
                startDepths = []

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

                        # Add face depth to list
                        faceDepths.append(shape.BoundBox.ZMin)
                    else:
                        ignoreSub = base.Name + '.' + sub
                        msg = translate(
                            'Path',
                            "Found a selected object which is not a face. Ignoring: {}"
                            .format(ignoreSub))
                        PathLog.error(msg)
                        FreeCAD.Console.PrintWarning(msg)

                # Set initial Start and Final Depths and recalculate depthparams
                finDep = obj.FinalDepth.Value
                strDep = obj.StartDepth.Value
                if strDep > stock.Shape.BoundBox.ZMax:
                    strDep = stock.Shape.BoundBox.ZMax

                startDepths.append(strDep)
                self.depthparams = self._customDepthParams(obj, strDep, finDep)

                for shape, wire in holes:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                    drillable = PathUtils.isDrillable(shape, wire)
                    if (drillable
                            and obj.processCircles) or (not drillable
                                                        and obj.processHoles):
                        env = PathUtils.getEnvelope(
                            shape, subshape=f, depthparams=self.depthparams)
                        tup = env, True, 'pathProfileFaces', angle, axis, strDep, finDep
                        shapes.append(tup)

                if len(faces) > 0:
                    profileshape = Part.makeCompound(faces)
                    self.profileshape.append(profileshape)

                if obj.processPerimeter:
                    if obj.HandleMultipleFeatures == 'Collectively':
                        custDepthparams = self.depthparams
                        if obj.LimitDepthToFace is True and obj.EnableRotation != 'Off':
                            if profileshape.BoundBox.ZMin > obj.FinalDepth.Value:
                                finDep = profileshape.BoundBox.ZMin
                                custDepthparams = self._customDepthParams(
                                    obj, strDep,
                                    finDep - 0.5)  # only an envelope
                        try:
                            env = PathUtils.getEnvelope(
                                base.Shape,
                                subshape=profileshape,
                                depthparams=custDepthparams)
                        except Exception:  # pylint: disable=broad-except
                            # PathUtils.getEnvelope() failed to return an object.
                            PathLog.error(
                                translate(
                                    'Path',
                                    'Unable to create path for face(s).'))
                        else:
                            tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
                            shapes.append(tup)

                    elif obj.HandleMultipleFeatures == 'Individually':
                        for shape in faces:
                            profShape = Part.makeCompound([shape])
                            finalDep = obj.FinalDepth.Value
                            custDepthparams = self.depthparams
                            if obj.Side == 'Inside':
                                if finalDep < shape.BoundBox.ZMin:
                                    # Recalculate depthparams
                                    finalDep = shape.BoundBox.ZMin
                                    custDepthparams = self._customDepthParams(
                                        obj, strDep, finalDep - 0.5)

                            env = PathUtils.getEnvelope(
                                base.Shape,
                                subshape=profShape,
                                depthparams=custDepthparams)
                            tup = env, False, 'pathProfileFaces', angle, axis, strDep, finalDep
                            shapes.append(tup)

            # Lower high Start Depth to top of Stock
            startDepth = max(startDepths)
            if obj.StartDepth.Value > startDepth:
                obj.StartDepth.Value = startDepth

        else:  # Try to build targets from the job base
            if 1 == len(self.model):
                if hasattr(self.model[0], "Proxy"):
                    PathLog.info("hasattr() Proxy")
                    if isinstance(self.model[0].Proxy,
                                  ArchPanel.PanelSheet):  # process the sheet
                        if obj.processCircles or obj.processHoles:
                            for shape in self.model[0].Proxy.getHoles(
                                    self.model[0], transform=True):
                                for wire in shape.Wires:
                                    drillable = PathUtils.isDrillable(
                                        self.model[0].Proxy, wire)
                                    if (drillable and obj.processCircles) or (
                                            not drillable
                                            and obj.processHoles):
                                        f = Part.makeFace(
                                            wire, 'Part::FaceMakerSimple')
                                        env = PathUtils.getEnvelope(
                                            self.model[0].Shape,
                                            subshape=f,
                                            depthparams=self.depthparams)
                                        tup = env, True, 'pathProfileFaces', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value
                                        shapes.append(tup)

                        if obj.processPerimeter:
                            for shape in self.model[0].Proxy.getOutlines(
                                    self.model[0], transform=True):
                                for wire in shape.Wires:
                                    f = Part.makeFace(wire,
                                                      'Part::FaceMakerSimple')
                                    env = PathUtils.getEnvelope(
                                        self.model[0].Shape,
                                        subshape=f,
                                        depthparams=self.depthparams)
                                    tup = env, False, 'pathProfileFaces', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value
                                    shapes.append(tup)

        self.removalshapes = shapes  # pylint: disable=attribute-defined-outside-init
        PathLog.debug("%d shapes" % len(shapes))

        return shapes
def import_fastercap(filename, folder=DEF_FOLDER, use_mesh=True):
    '''Import file in FasterCap format as Mesh or Part.compound
        
    'filename' is the name of the export file
    'folder' is the folder where the file resides
        
    Example:
    fastercapObj = import_fastercap('cube.txt')
'''
    
    if not os.path.isdir(folder):
        FreeCAD.Console.PrintMessage("Error: '" + folder + "' is not a valid folder\n")
        return
        
    if not os.path.exists(folder + os.sep + filename):
        FreeCAD.Console.PrintMessage("Error: '" + filename + "' is not a valid file in the directory " + folder + "\n")
        return
        
    try:
        with open(folder + os.sep + filename, 'rb') as fid:
            # reset the list of triangle vertexes
            panelVertexes = []
            chargeDensity = []
            # and scan all the file
            for i, line in enumerate(fid):
                # if first line, or empty line, skip
                if i == 0 or line in ['', '\n', '\r\n']:
                    continue
                # now check for actual statements
                #
                # first split the line into the components
                splitLine = line.split()
                # if the line was actually composed only by separators, continue
                if len(splitLine) == 0:
                    continue

                # then check content
                #
                # if triangle
                if splitLine[0] == 'T':
                    try:
                        # if using mesh, we need a flat list of vertexed, that will be used in triplets
                        # to build the triangular-only mesh faces
                        if use_mesh == True:
                            panelVertexes.extend( [ [float(splitLine[2]), float(splitLine[3]), float(splitLine[4])],
                                                    [float(splitLine[5]), float(splitLine[6]), float(splitLine[7])],
                                                    [float(splitLine[8]), float(splitLine[9]), float(splitLine[10])] ])
                        # if using faces, we need FreeCAD.Vector or tuple of three floats for each vertex, in a vector
                        # with as many elements as the vertexes of the polygon supporting the face
                        else:
                            panelVertexes.append( [ (float(splitLine[2]), float(splitLine[3]), float(splitLine[4])),
                                                    (float(splitLine[5]), float(splitLine[6]), float(splitLine[7])),
                                                    (float(splitLine[8]), float(splitLine[9]), float(splitLine[10])) ])
                    except (IndexError, ValueError):
                        FreeCAD.Console.PrintMessage("Error on line " + format(i) + " : " + line + "\n")   
                    # if there is trailing charge density information, store it
                    if len(splitLine) >= 12:
                        chargeDensity.append(float(splitLine[11]))
                # if quadrilateral
                if splitLine[0] == 'Q':
                    try:
                        if use_mesh == True:
                            panelVertexes.extend( [ [float(splitLine[2]), float(splitLine[3]), float(splitLine[4])],
                                                    [float(splitLine[5]), float(splitLine[6]), float(splitLine[7])],
                                                    [float(splitLine[8]), float(splitLine[9]), float(splitLine[10])],
                                                    [float(splitLine[2]), float(splitLine[3]), float(splitLine[4])],
                                                    [float(splitLine[8]), float(splitLine[9]), float(splitLine[10])],
                                                    [float(splitLine[11]), float(splitLine[12]), float(splitLine[13])] ])
                            # if there is trailing charge density information, store it
                            if len(splitLine) >= 15:
                                # add twice, as a quadrilateral panel spits into two triangles in a triangular mesh
                                chargeDensity.extend([float(splitLine[14]), float(splitLine[14])])
                        else:
                            panelVertexes.extend( [[ (float(splitLine[2]), float(splitLine[3]), float(splitLine[4])),
                                                     (float(splitLine[5]), float(splitLine[6]), float(splitLine[7])),
                                                     (float(splitLine[8]), float(splitLine[9]), float(splitLine[10])),
                                                     (float(splitLine[11]), float(splitLine[12]), float(splitLine[13])) ]])              
                            # if there is trailing charge density information, store it
                            if len(splitLine) >= 15:
                                chargeDensity.append(float(splitLine[14]))
                    except ValueError:
                        FreeCAD.Console.PrintMessage("Error on line " + format(i) + " : " + line + "\n")  
                    # if there is trailing charge density information, store it
                    if len(splitLine) >= 15:
                        chargeDensity.append(float(splitLine[14]))

            fid.closed

    except OSError as err:
        FreeCAD.Console.PrintMessage("OS error: " + format(err) + "\n")
        return
                
    if use_mesh == True:
        # now create the mesh. As of FreeCAD 0.16 we cannot color the mesh faces individually,
        # so we'll ignore the charge information, even if present
        fastercapMesh = Mesh.Mesh(panelVertexes)
        # and show it
        Mesh.show(fastercapMesh)
        return fastercapMesh
    else:
        # check if there is charge information
        if len(chargeDensity) > 0:
            # check if every panel has the info
            if len(chargeDensity) != len(panelVertexes):
                FreeCAD.Console.PrintMessage("\nWarning: charge densities vector has length " + 
                                          format(len(chargeDensity)) + " while panels are " +
                                          format(len(panelVertexes)))
                chargeDensity = []
        # create faces
        facelist = []
        for panel in panelVertexes:
            # to create closed wires, the last point should be identical to the first
            wirepoly = Part.makePolygon(panel + [panel[0]])
            face = Part.Face(wirepoly)
            facelist.append(face)
        # cannot use a shell, otherwise face order will be all scrambled up,
        # as Part will stitch faces when building the shell, cutting the 
        # edges where there are other triangle vertexes in contact, and 
        # doing so changes the face order
        #shellObj = Part.makeShell(facelist)
        # a compound instead will just contain a list of faces
        compObj = Part.makeCompound(facelist)
        # might use "Part.show(compObj)" but we need access to the Part::Feature 'featObj'
        # to be able to change its ViewObject properties
        doc = App.ActiveDocument
        partFeatObj = doc.addObject("Part::Feature","FasterCap_Compound")
        partFeatObj.Shape = compObj
        doc.recompute() 
        # add density color
        if len(chargeDensity) > 0:
            # create colormap
            gradTable = [ (0.0, 1.0, 1.0), (0.0, 0.0, 1.0),
                          (0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 1.0, 0.0)]
            colorMap = colormap(gradTable)
            
            #
            # create gradient table (debug only). Should implement using Pivy to have a fixed table at the side
            #~ facelist = []
            #~ for i in range(0,256):
                #~ wirepoly = Part.makePolygon( [ (0.0, i*10.0, 0.0), (0.0, (i+1)*10.0, 0.0), (0.0, (i+1)*10.0, 50.0),
                                               #~ (0.0, i*10.0, 50.0), (0.0, i*10.0, 0.0) ] )
                #~ face = Part.Face(wirepoly)
                #~ facelist.append(face)
            #~ shellGradObj = Part.makeShell(facelist)
            #~ gradObj = doc.addObject("Part::Feature","Gradient_Table")
            #~ gradObj.Shape = shellGradObj
            #~ doc.recompute()
            #~ gradObj.ViewObject.DiffuseColor = [colorMap[x] for x in range(0,256)]
            # end debug
            #
            
            # convert the charge density values into color indexes
            coeff = (COLORMAP_LEN - 1) / (max(chargeDensity) - min(chargeDensity))
            partFeatObj.ViewObject.DiffuseColor = [colorMap[(int)((x-min(chargeDensity))*coeff)] for x in chargeDensity]
        return partFeatObj
Example #55
0
    def processSubShapes(self,obj,base,placement=None):

        "Adds additions and subtractions to a base shape"

        import Draft,Part
        #print("Processing subshapes of ",obj.Label, " : ",obj.Additions)

        if placement:
            if placement.isIdentity():
                placement = None
            else:
                placement = FreeCAD.Placement(placement)
                placement = placement.inverse()

        # treat additions
        for o in obj.Additions:

            if not base:
                if o.isDerivedFrom("Part::Feature"):
                    base = o.Shape
            else:
                if base.isNull():
                    if o.isDerivedFrom("Part::Feature"):
                        base = o.Shape
                else:
                    # special case, both walls with coinciding endpoints
                    import ArchWall
                    js = ArchWall.mergeShapes(o,obj)
                    if js:
                        add = js.cut(base)
                        if placement:
                            add.Placement = add.Placement.multiply(placement)
                        base = base.fuse(add)

                    elif o.isDerivedFrom("Part::Feature"):
                        if o.Shape:
                            if not o.Shape.isNull():
                                if o.Shape.Solids:
                                    s = o.Shape.copy()
                                    if placement:
                                        s.Placement = s.Placement.multiply(placement)
                                    if base:
                                        if base.Solids:
                                            try:
                                                base = base.fuse(s)
                                            except Part.OCCError:
                                                print("Arch: unable to fuse object ", obj.Name, " with ", o.Name)
                                    else:
                                        base = s

        # treat subtractions
        subs = obj.Subtractions
        for link in obj.InList:
            if hasattr(link,"Hosts"):
                for host in link.Hosts:
                    if host == obj:
                        subs.append(link)
        for o in subs:

            if base:
                if base.isNull():
                    base = None

            if base:
                if (Draft.getType(o) == "Window") or (Draft.isClone(o,"Window",True)):
                        # windows can be additions or subtractions, treated the same way
                        f = o.Proxy.getSubVolume(o)
                        if f:
                            if base.Solids and f.Solids:
                                if placement:
                                    f.Placement = f.Placement.multiply(placement)
                                if len(base.Solids) > 1:
                                    base = Part.makeCompound([sol.cut(f) for sol in base.Solids])
                                else:
                                    base = base.cut(f)

                elif (Draft.getType(o) == "Roof") or (Draft.isClone(o,"Roof")):
                    # roofs define their own special subtraction volume
                    f = o.Proxy.getSubVolume(o)
                    if f:
                        if base.Solids and f.Solids:
                            if len(base.Solids) > 1:
                                base = Part.makeCompound([sol.cut(f) for sol in base.Solids])
                            else:
                                base = base.cut(f)

                elif o.isDerivedFrom("Part::Feature"):
                    if o.Shape:
                        if not o.Shape.isNull():
                            if o.Shape.Solids and base.Solids:
                                    s = o.Shape.copy()
                                    if placement:
                                        s.Placement = s.Placement.multiply(placement)
                                    try:
                                        if len(base.Solids) > 1:
                                            base = Part.makeCompound([sol.cut(s) for sol in base.Solids])
                                        else:
                                            base = base.cut(s)
                                    except Part.OCCError:
                                        print("Arch: unable to cut object ",o.Name, " from ", obj.Name)
        return base
Example #56
0
    def execute(self, fp):
        b = fp.pin_circle_radius
        d = fp.roller_diameter
        e = fp.eccentricity
        n = fp.teeth_number
        p = b / n
        s = fp.segment_count
        ang = fp.pressure_angle_lim
        c = fp.pressure_angle_offset

        q = 2 * math.pi / float(s)

        # Find the pressure angle limit circles
        minAngle = -1.0
        maxAngle = -1.0
        for i in range(0, 180):
            x = self.calc_pressure_angle(p, d, n, i * math.pi / 180.)
            if (x < ang) and (minAngle < 0):
                minAngle = float(i)
            if (x < -ang) and (maxAngle < 0):
                maxAngle = float(i - 1)

        minRadius = self.calc_pressure_limit(p, d, e, n,
                                             minAngle * math.pi / 180.)
        maxRadius = self.calc_pressure_limit(p, d, e, n,
                                             maxAngle * math.pi / 180.)
        # unused
        # Wire(Part.makeCircle(minRadius,App.Vector(-e, 0, 0)))
        # Wire(Part.makeCircle(maxRadius,App.Vector(-e, 0, 0)))

        App.Console.PrintMessage("Generating cam disk\r\n")
        #generate the cam profile - note: shifted in -x by eccentricicy amount
        i = 0
        x = self.calc_x(p, d, e, n, q * i / float(n))
        y = self.calc_y(p, d, e, n, q * i / n)
        x, y = self.check_limit(x, y, maxRadius, minRadius, c)
        points = [App.Vector(x - e, y, 0)]
        for i in range(0, s):
            x = self.calc_x(p, d, e, n, q * (i + 1) / n)
            y = self.calc_y(p, d, e, n, q * (i + 1) / n)
            x, y = self.check_limit(x, y, maxRadius, minRadius, c)
            points.append([x - e, y, 0])

        wi = make_bspline_wire([points])
        wires = []
        mat = App.Matrix()
        mat.move(App.Vector(e, 0., 0.))
        mat.rotateZ(2 * np.pi / n)
        mat.move(App.Vector(-e, 0., 0.))
        for _ in range(n):
            wi = wi.transformGeometry(mat)
            wires.append(wi)

        cam = Face(Wire(wires))
        #add a circle in the center of the cam
        centerCircle = Face(
            Wire(Part.makeCircle(fp.hole_radius.Value, App.Vector(-e, 0, 0))))
        cam = cam.cut(centerCircle)

        to_be_fused = []
        if fp.show_disk0 == True:
            if fp.disk_height.Value == 0:
                to_be_fused.append(cam)
            else:
                to_be_fused.append(
                    cam.extrude(App.Vector(0, 0, fp.disk_height.Value)))

        #secondary cam disk
        if fp.show_disk1 == True:
            App.Console.PrintMessage("Generating secondary cam disk\r\n")
            second_cam = cam.copy()
            mat = App.Matrix()
            mat.rotateZ(np.pi)
            mat.move(App.Vector(-e, 0, 0))
            mat.rotateZ(np.pi / n)
            mat.move(App.Vector(e, 0, 0))
            second_cam = second_cam.transformGeometry(mat)
            if fp.disk_height.Value == 0:
                to_be_fused.append(second_cam)
            else:
                to_be_fused.append(
                    second_cam.extrude(App.Vector(0, 0,
                                                  -fp.disk_height.Value)))

        #pins
        if fp.show_pins == True:
            App.Console.PrintMessage("Generating pins\r\n")
            pins = []
            for i in range(0, n + 1):
                x = p * n * math.cos(2 * math.pi / (n + 1) * i)
                y = p * n * math.sin(2 * math.pi / (n + 1) * i)
                pins.append(Wire(Part.makeCircle(d / 2, App.Vector(x, y, 0))))

            pins = Face(pins)

            z_offset = -fp.pin_height.Value / 2

            if fp.center_pins == True:
                if fp.show_disk0 == True and fp.show_disk1 == False:
                    z_offset += fp.disk_height.Value / 2
                elif fp.show_disk0 == False and fp.show_disk1 == True:
                    z_offset += -fp.disk_height.Value / 2
            #extrude
            if z_offset != 0:
                pins.translate(App.Vector(0, 0, z_offset))
            if fp.pin_height != 0:
                pins = pins.extrude(App.Vector(0, 0, fp.pin_height.Value))

            to_be_fused.append(pins)

        if to_be_fused:
            fp.Shape = Part.makeCompound(to_be_fused)
Example #57
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
Example #58
0
    def execute(self,obj):

        "builds the wall shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils
        base = None
        pl = obj.Placement
        extdata = self.getExtrusionData(obj)
        if extdata:
            bplates = extdata[0]
            extv = extdata[2].Rotation.multVec(extdata[1])
            if isinstance(bplates,list):
                shps = []
                for b in bplates:
                    b.Placement = extdata[2].multiply(b.Placement)
                    b = b.extrude(extv)
                    shps.append(b)
                base = Part.makeCompound(shps)
            else:
                bplates.Placement = extdata[2].multiply(bplates.Placement)
                base = bplates.extrude(extv)
        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
                elif obj.Base.Shape.Solids:
                    base = obj.Base.Shape.copy()

                # blocks calculation
                elif hasattr(obj,"MakeBlocks") and hasattr(self,"basewires"):
                    if obj.MakeBlocks and self.basewires and extdata and obj.Width and obj.BlockLength.Value and obj.BlockHeight.Value:
                        #print "calculating blocks"
                        if len(self.basewires) == 1:
                            blocks = []
                            n = FreeCAD.Vector(extv)
                            n.normalize()
                            cuts1 = []
                            cuts2 = []
                            for i in range(2):
                                if i == 0:
                                    offset = obj.OffsetFirst.Value
                                else:
                                    offset = obj.OffsetSecond.Value
                                for edge in self.basewires[0].Edges:
                                    while offset < (edge.Length-obj.Joint.Value):
                                        #print i," Edge ",edge," : ",edge.Length," - ",offset
                                        if offset:
                                            t = edge.tangentAt(offset)
                                            p = t.cross(n)
                                            p.multiply(1.1*obj.Width.Value)
                                            p1 = edge.valueAt(offset).add(p)
                                            p2 = edge.valueAt(offset).add(p.negative())
                                            sh = Part.LineSegment(p1,p2).toShape()
                                            if obj.Joint.Value:
                                                sh = sh.extrude(t.multiply(obj.Joint.Value))
                                            sh = sh.extrude(n)
                                            if i == 0:
                                                cuts1.append(sh)
                                            else:
                                                cuts2.append(sh)
                                        offset += (obj.BlockLength.Value+obj.Joint.Value)
                                    else:
                                        offset -= (edge.Length-obj.Joint.Value)
                            if cuts1 and cuts2:
                                if isinstance(bplates,list):
                                    bplates = bplates[0]
                                fsize = obj.BlockHeight.Value+obj.Joint.Value
                                bvec = FreeCAD.Vector(n)
                                bvec.multiply(obj.BlockHeight.Value)
                                svec = FreeCAD.Vector(n)
                                svec.multiply(fsize)
                                plate1 = bplates.cut(cuts1).Faces
                                blocks1 = Part.makeCompound([f.extrude(bvec) for f in plate1])
                                plate2 = bplates.cut(cuts2).Faces
                                blocks2 = Part.makeCompound([f.extrude(bvec) for f in plate2])
                                interval = extv.Length/(fsize)
                                entires = int(interval)
                                rest = (interval - entires)
                                for i in range(entires):
                                    if i % 2: # odd
                                        b = blocks2.copy()
                                    else:
                                        b = blocks1.copy()
                                    if i:
                                        t = FreeCAD.Vector(svec)
                                        t.multiply(i)
                                        b.translate(t)
                                    blocks.append(b)
                                if rest:
                                    rest = extv.Length-(entires*fsize)
                                    rvec = FreeCAD.Vector(n)
                                    rvec.multiply(rest)
                                    if entires % 2:
                                        b = Part.makeCompound([f.extrude(rvec) for f in plate2])
                                    else:
                                        b = Part.makeCompound([f.extrude(rvec) for f in plate1])
                                    t = FreeCAD.Vector(svec)
                                    t.multiply(entires)
                                    b.translate(t)
                                    blocks.append(b)
                                if blocks:
                                    base = Part.makeCompound(blocks)
                            else:
                                FreeCAD.Console.PrintWarning(translate("Arch","Error computing block cuts for wall")+obj.Label+"\n")
                        else:
                            FreeCAD.Console.PrintWarning(translate("Arch","Cannot compute blocks for wall")+obj.Label+"\n")

            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(translate("Arch","This mesh is an invalid solid")+"\n")
                            obj.Base.ViewObject.show()
        if not base:
            FreeCAD.Console.PrintError(translate("Arch","Error: Invalid base object")+"\n")
            return

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

        # count blocks
        if hasattr(obj,"MakeBlocks"):
            if obj.MakeBlocks:
                fvol = obj.BlockLength.Value * obj.BlockHeight.Value * obj.Width.Value
                if fvol:
                    #print("base volume:",fvol)
                    #for s in base.Solids:
                        #print(abs(s.Volume - fvol))
                    ents = [s for s in base.Solids if abs(s.Volume - fvol) < 1]
                    obj.CountEntire = len(ents)
                    obj.CountBroken = len(base.Solids) - len(ents)
                else:
                    obj.CountEntire = 0
                    obj.CountBroken = 0

        # set the length property
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Edges:
                    if not obj.Base.Shape.Faces:
                        if hasattr(obj.Base.Shape,"Length"):
                            l = obj.Base.Shape.Length
                            if obj.Length.Value != l:
                                obj.Length = l
Example #59
0
    def execute(self, obj):

        if self.clone(obj):
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0], "Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if father.isDerivedFrom("Part::Feature"):
                fathershape = father.Shape

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

                if h <= 0:
                    h = 0.01
            else:  # bottomSide
                h = -obj.Height.Value

                if h >= 0:
                    h = -0.01
            ##
            self.spisObiektowTXT = []
            for i in obj.Base.Geometry:
                if i.Construction:
                    continue

                if i.__class__.__name__ == 'LineSegment':

                    x1 = i.StartPoint.x
                    y1 = i.StartPoint.y
                    x2 = i.EndPoint.x
                    y2 = i.EndPoint.y
                    #
                    self.addLineWidth(x1, y1, x2, y2, obj.Width.Value)
                    self.setFace(not obj.Flat, h * 1000)
                elif i.__class__.__name__ == 'Circle':
                    x = i.Center.x
                    y = i.Center.y
                    r = i.Radius
                    #
                    self.addCircle(x, y, r, 0)
                    self.setFace(not obj.Flat, h * 1000)
                elif i.__class__.__name__ == 'ArcOfCircle':
                    curve = degrees(i.LastParameter - i.FirstParameter)

                    points = i.discretize(Distance=i.length() / 2)
                    if i.Circle.Axis.z < 0:
                        p1 = [points[2].x, points[2].y]
                        p2 = [points[0].x, points[0].y]
                    else:
                        p1 = [points[0].x, points[0].y]
                        p2 = [points[2].x, points[2].y]
                    p3 = [points[1].x, points[1].y]  # mid point

                    self.addArcWidth(p1, p2, curve, obj.Width.Value, p3)
                    self.setFace(not obj.Flat, h * 1000)
            #
            if len(self.spisObiektowTXT) > 0:
                path = Part.makeCompound(self.spisObiektowTXT)
                # if obj.Flat == False:
                # path = path.extrude(FreeCAD.Base.Vector(0, 0, h))
                obj.Shape = path
            else:
                obj.Shape = Part.Shape()

            obj.recompute()
            obj.Base.recompute()
            obj.purgeTouched()
            obj.Base.purgeTouched()

            obj.Placement.Base.z = obj.Base.Placement.Base.z
            obj.Volume = obj.Shape.Volume
        except Exception as e:
            FreeCAD.Console.PrintWarning(u"{0}\n".format(e))