Macros recipes

From FreeCAD Documentation
Revision as of 19:30, 5 October 2010 by Tremblou (talk | contribs)

Rotate the view by 90°

This macro rotates the current view by 90° to the left. Only works if you are in Top view.

import math
from pivy import coin
cam = Gui.ActiveDocument.ActiveView.getCameraNode()
rot = coin.SbRotation()
rot.setValue(coin.SbVec3f(0,0,1),math.pi/2)
nrot = cam.orientation.getValue() * rot
cam.orientation = nrot

Array copy

This macro copies the selected object several times, on an array grid. You can define the number of rows and columns and the distance between them. You need pyqt installed.

import FreeCAD, FreeCADGui, Part
from PyQt4 import QtGui,QtCore

def proceed():
    try:
        u = (int(l1.text()),float(l2.text()))   
        v = (int(l3.text()),float(l4.text()))
    except:
        FreeCAD.Console.PrintError("Wrong input! Only numbers allowed...\n")
    sel = FreeCADGui.Selection.getSelection()
        if sel:
            sel = sel[0]
            name = sel.Name   
            shape = sel.Shape
            for column in range(u[0]):
                for row in range(v[0]):
                    if (column != 0) or (row != 0):
                        delta = FreeCAD.Vector(column*u[1],row*v[1],0)   
                        newshape = sel.Shape
                        newshape.translate(delta)
                        newobject = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
                        newobject.Shape = newshape
        else:
            FreeCAD.Console.PrintError("Error: One object must be selected")
        hide()

def hide():
    dialog.hide()

dialog = QtGui.QDialog()
dialog.resize(200,300)
dialog.setWindowTitle("Array")
la = QtGui.QVBoxLayout(dialog)
t1 = QtGui.QLabel("number of columns")
la.addWidget(t1)
l1 = QtGui.QLineEdit()
la.addWidget(l1)
t2 = QtGui.QLabel("distance between columns")
la.addWidget(t2)
l2 = QtGui.QLineEdit()
la.addWidget(l2)
t3 = QtGui.QLabel("number of rows")
la.addWidget(t3)
l3 = QtGui.QLineEdit()
la.addWidget(l3)
t4 = QtGui.QLabel("distance between rows")   
la.addWidget(t4)
l4 = QtGui.QLineEdit()
la.addWidget(l4)
okbox = QtGui.QDialogButtonBox(dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), hide)
QtCore.QMetaObject.connectSlotsByName(dialog)
dialog.show()

Flatten wire

This macro flattens draft wires that are not plane to their median Z coordinate.

import FreeCAD
obj = FreeCAD.ActiveDocument.ActiveObject
z = 0
for p in obj.Points: z += p.z
z = z/len(obj.Points)
newpoints = []
for p in obj.Points: newppoints.append(FreeCAD.Vector(p.x,p.y,z))
obj.Points = newppoints

Convert Meshes to Parts

This macro converts selected meshes to parts. It has a broad tolerance, so use it only with objects that have no curves otherwise you'll get weird results.

import FreeCAD,FreeCADGui,Mesh,Part,MeshPart

for obj in FreeCADGui.Selection.getSelection():
	if "Mesh" in obj.PropertiesList:
		faces = []		
		mesh = obj.Mesh
		segments = mesh.getPlanes(0.01) # use rather strict tolerance here

		for i in segments:
		  if len(i) > 0:
		     # a segment can have inner holes
		     wires = MeshPart.wireFromSegment(mesh, i)
		     # we assume that the exterior boundary is that one with the biggest bounding box
		     if len(wires) > 0:
		        ext = None
		        max_length = 0
		        for i in wires:		
		           if i.BoundBox.DiagonalLength > max_length:
		              max_length = i.BoundBox.DiagonalLength
		              ext = i
	        	wires.remove(ext)
	        	# all interior wires mark a hole and must reverse their orientation, otherwise Part.Face fails
	        	for i in wires:
	        	   i.reverse()
	        	# make sure that the exterior wires comes as first in the lsit
	        	wires.insert(0, ext)
	        	faces.append(Part.Face(wires))

		shell=Part.Compound(faces)
		solid = Part.Solid(Part.Shell(faces))
		name = obj.Name
		FreeCAD.ActiveDocument.removeObject(name)
		FreeCAD.ActiveDocument.addObject("Part::Feature",name).Shape = solid

Joint wire

This macro allow to find and joint all non connected edge to the closest non connected one using a line. It take a shape matrix in entry ( [shape1,shape2,...]).

def findWires(edges):

       finds connected edges in the list, and returns a list of lists containing edges
       that can be connected
   def verts(shape):
               return [shape.Vertexes[0].Point,shape.Vertexes[-1].Point]
       def group(shapes):
               shapesIn = shapes[:]
               pointTst = []
       pointOut =[]
       for s in shapesIn :
           pointTst=pointTst+[s.Vertexes[0].Point]
           pointTst=pointTst+[s.Vertexes[-1].Point]
       print pointTst               
       changed = False
               for s in shapesIn:
                       if len(s.Vertexes) < 2:
               print "one vertex, its a circle, just add"
                       else:                             
                               for v in verts(s):
                   twoDot=0
                                       for vv in pointTst:
                                               if v == vv:
                           twoDot=twoDot+1                           
                       if v==vv and twoDot==2 :                   
                           changed = True
                           print "found matching vert"
                           break
                                   if twoDot<2:
                       print "didn't find any matching vert..."
                       pointOut.append(v)
       print "Dots non connected", pointOut
               return(changed,pointOut)
   def joint(point):
       for p in range(len(point)/2) :
           print point
           deltI=Part.Vertex(100,100,100).Point
           pos=1
           for pp in range(len(point)-1) :
               print "position:",pp+1
               if len(point)-1>1:
                   deltN=(point[0]-point[pp+1])
                   if deltN.Length<deltI.Length:
                       deltI=deltN
                       pos=pp+1
                       print "changement",pos
               else:
                   pos=1   
           print "points a joindre",point[0],point[pos]
           if point[0]!=point[pos]:
               Part.show(Part.makePolygon([point[0],point[pos]]))
           else:
               print "WARNING les points ont la meme valeurs "
           point.pop(0)
           point.pop(pos-1)
       point=0 #to have a return normally void
       return(point)
   working = True
       edgeSet = edges
   result = group(edgeSet)
       working = result[0]
       edgeSet = result[1]
   joint(result[1])
       return result[1]

Automatic Drawing

This code allow the user to get the view of his object in a drawing with 4 different position(front,top,iso,right). Need some modification to be perfecly effective.

import FreeCAD, Part, Drawing

if len(Gui.Selection.getSelectionEx())>1:

   App.Console.PrintError("Warning: Only the first item is generate")

if len(Gui.Selection.getSelectionEx())==0:

   App.Console.PrintError("Warning: Need to select one item")


Piece=Gui.Selection.getSelectionEx()[0] App.activeDocument().addObject('Drawing::FeaturePage','AutoDrawing') App.activeDocument().AutoDrawing.Template = App.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' DH=20 DL=30 L=Piece.Object.Shape.BoundBox.XMax H=Piece.Object.Shape.BoundBox.ZMax P=Piece.Object.Shape.BoundBox.YMax


Sc=(400-3*DL)/(L+H) Sc2=(250-3*DH)/(P+H)

if Sc>Sc2 :

   Sc=Sc2


TopX=DL+Sc*L FrontX=DL+Sc*L RightX=2*DL+Sc*L IsoX=2*DL+Sc*(L) TopY=DH+Sc*P RightY=DH+P*Sc FrontY=2*DH+Sc*(P+H) IsoY=2*DH+Sc*P

print TopX,RightX,TopY,FrontY

  1. Create topView

App.activeDocument().addObject('Drawing::FeatureViewPart','topView') App.activeDocument().topView.Source =Piece.Object App.activeDocument().topView.Direction = (0,0,1) App.activeDocument().topView.Rotation=180 App.activeDocument().topView.X = TopX App.activeDocument().topView.Y = TopY App.activeDocument().topView.ShowHiddenLines=True App.activeDocument().AutoDrawing.addObject(App.activeDocument().topView) App.activeDocument().topView.Scale = Sc

  1. Create FrontView

App.activeDocument().addObject('Drawing::FeatureViewPart','FrontView') App.activeDocument().FrontView.Source =Piece.Object App.activeDocument().FrontView.Direction = (0,-1,0) App.activeDocument().FrontView.Rotation=90 App.activeDocument().FrontView.Scale = Sc App.activeDocument().FrontView.X = FrontX App.activeDocument().FrontView.Y = FrontY App.activeDocument().FrontView.ShowHiddenLines=True App.activeDocument().AutoDrawing.addObject(App.activeDocument().FrontView)

  1. Create RightView

App.activeDocument().addObject('Drawing::FeatureViewPart','RightView') App.activeDocument().RightView.Source =Piece.Object App.activeDocument().RightView.Direction = (1,0,0) App.activeDocument().RightView.Scale = Sc App.activeDocument().RightView.X = RightX App.activeDocument().RightView.Y = RightY App.activeDocument().RightView.ShowHiddenLines=True App.activeDocument().AutoDrawing.addObject(App.activeDocument().RightView)

  1. Create IsotView

App.activeDocument().addObject('Drawing::FeatureViewPart','IsoView') App.activeDocument().IsoView.Source =Piece.Object App.activeDocument().IsoView.Direction = (1,1,1) App.activeDocument().IsoView.Rotation=60 App.activeDocument().IsoView.Scale = Sc*.6 App.activeDocument().IsoView.X = IsoX App.activeDocument().IsoView.Y = IsoY App.activeDocument().IsoView.ShowHiddenLines=True App.activeDocument().AutoDrawing.addObject(App.activeDocument().IsoView)