Macros recipes

From FreeCAD Documentation
Revision as of 20:41, 24 November 2010 by Wmayer (talk | contribs) (Restore script)

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):
   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

#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
#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)
#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)
#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)

Draw 2D function

Use it to draw a function described by a "equation" [z=F(x)] (Z-X plane) The example done here generate a parabol. Need to be defined : F=variable used in the fonction, X=initial value of x, Nb= Number of step, Z=function express with x ZZ=function express with xx

import FreeCAD, FreeCADGui, Part
import math
F=800
X=-500
Nb=10
Step=1000/Nb
Y=0
for I in range(Nb):
	XX=X+Step 
	Z=X*X/(4*F)
	ZZ=XX*XX/(4*F)
	if I==0:
		print "Le test est vrai !"
		nomme=Part.makeLine((X,Y,Z),(XX,Y,ZZ))
		WWire=Part.Wire([nomme])
	else :
		print "Le test est 2 !"
		nomme=Part.makeLine((X,Y,Z),(XX,Y,ZZ))		
		WWire=Part.Wire([WWire,nomme])
	X=XX 

Part.show(WWire)