Macro Unroll Ruled Surface/it: Difference between revisions
Renatorivo (talk | contribs) (Macro_unrollRuledSurface it) |
Renatorivo (talk | contribs) mNo edit summary |
||
Line 3: | Line 3: | ||
==Descrizione== |
==Descrizione== |
||
Questa macro permette di creare lo sviluppo di una superficie rigata e di disegnarlo in una pagina, |
Questa macro permette di creare lo sviluppo di una superficie rigata e di disegnarlo in una pagina, e di inserire il disegno in un foglio A3 o A4. |
||
<br><br> |
<br><br> |
Revision as of 19:37, 14 September 2013
File:Text-x-python Macro_unrollRuledSurface |
Descrizione |
---|
Permette di srotolare superfici rigate e di disegnarle su una pagina. Autore: Hervé B. |
Autore |
Hervé B. |
Download |
None |
Link |
Raccolta di macro Come installare le macro Personalizzare la toolbar |
Versione macro |
1.0 |
Data ultima modifica |
None |
Versioni di FreeCAD |
None |
Scorciatoia |
Nessuna |
Vedere anche |
Nessuno |
Descrizione
Questa macro permette di creare lo sviluppo di una superficie rigata e di disegnarlo in una pagina, e di inserire il disegno in un foglio A3 o A4.
Installazione
Secondo quanto descritto in Macro for unrolling ruled surfaces
Copiare il file del codice nella directory :
- Linux & Mac : $home/.Freecad/Mod/UnrollRuledSurface.
- Windows : C:\Program Files\FreeCAD0.13
Aggiungere i modelli dei foglio : A3_Landscape_Empty.svg A3_Landscape.svg A4_Landscape_Empty.svg A4_Landscape.svg
Opzioni
- Numero di generatrici
- Scala manuale o automatica
- Formato della pagina: A3, A4
- Tabella (secondo i modelli di FreeCAD)
- Raggruppamento dei disegni nella stessa pagina se è possibile.
Utlizzo
- Selezionare una supeficie in un oggetto
- Scomporre l'oggetto (menu Draft -> Retrocedere)
- Selezionare le supefici da sviluppare
- Eseguire la macro
Codice Python
Macro_unrollRuledSurface.py
#*************************************************************************** #* * #* Copyright (c) 2013 - DoNovae/Herve BAILLY <hbl13@donovae.com> * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * #* as published by the Free Software Foundation; either version 2 of * #* the License, or (at your option) any later version. * #* for detail see the LICENCE text file. * #* * #* This program is distributed in the hope that it will be useful, * #* but WITHOUT ANY WARRANTY; without even the implied warranty of * #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * #* GNU Library General Public License for more details. * #* * #* You should have received a copy of the GNU Library General Public * #* License along with this program; if not, write to the Free Software * #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * #* USA * #* * #*************************************************************************** ##################################### # Macro UnrollRuledSurface # Unroll of a ruled surface ##################################### import FreeCAD , FreeCADGui , Part, Draft, math, Drawing , PyQt4, os from PyQt4 import QtGui,QtCore from FreeCAD import Base fields_l = [] unroll_l = [] ##################################### ##################################### # Functions ##################################### ##################################### ##################################### # Function errorDialog ##################################### def errorDialog(msg): diag = QtGui.QMessageBox(QtGui.QMessageBox.Critical,u"Error Message",msg ) diag.setWindowFlags(PyQt4.QtCore.Qt.WindowStaysOnTopHint) diag.exec_() ##################################### # Function proceed ##################################### def proceed(): QtGui.qApp.setOverrideCursor(QtCore.Qt.WaitCursor) FreeCAD.Console.PrintMessage("===========================================\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface: start.\n") try: file_name = fields_l[0].text() pts_nbr = float(fields_l[1].text()) scale = float(fields_l[2].text()) scale_auto = scale_check.isChecked() a3 = a3_check.isChecked() cartridge = cartridge_check.isChecked() onedrawing = onedrawing_check.isChecked() FreeCAD.Console.PrintMessage("UnrollRuledSurface.file_name: "+file_name+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.pts_nbr: "+str(pts_nbr)+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.scale: "+str(scale)+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.scale_check: "+str(scale_auto)+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.a3_check: "+str(a3)+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.cartridge: "+str(cartridge)+"\n") FreeCAD.Console.PrintMessage("UnrollRuledSurface.onedrawing: "+str(onedrawing)+"\n") except: msg="UnrollRuledSurface: wrong inputs...\n" FreeCAD.Console.PrintError(msg) errorDialog(msg) QtGui.qApp.restoreOverrideCursor() DialogBox.hide() draw=Drawing2d( scale, scale_auto , a3 , cartridge , onedrawing ) unrollRS=unrollRuledSurface( file_name , pts_nbr ) # # Get selection # sel=FreeCADGui.Selection.getSelection() faceid=0 for objid in range( sel.__len__() ): shape=sel[objid].Shape faces=shape.Faces for id in range( faces.__len__() ): FreeCAD.Console.PrintMessage("UnrollRuledSurface.proceed: ObjId= "+str(objid)+" , faceId= "+str( faceid )+"\n") unroll_l.append( unrollRS.unroll(faces[id]) ) faceid=faceid+1 draw.all( unroll_l ) FreeCAD.Console.PrintMessage("UnrollRuledSurface: end.\n") FreeCAD.Console.PrintMessage("===========================================\n") ##################################### # Function close ##################################### def close(): DialogBox.hide() ##################################### # Class unrollRuledSurface # - file_name : ouput file # - pts_nbr : nbr point of # discretization ##################################### class unrollRuledSurface: def __init__( self, file_name, pts_nbr ): self.doc = FreeCAD.newDocument( str(file_name) ) self.file_name = file_name self.pts_nbr = int(pts_nbr) FreeCAD.Console.PrintMessage("UnrollRuledSurface.unroll - file_name: "+self.file_name+" , pts_nbr: "+str(self.pts_nbr)+"\n") ##################################### # Function discretize ##################################### def discretize(self,curve): if type(curve).__name__=='GeomLineSegment': sd=curve.discretize( self.pts_nbr ) elif type(curve).__name__=='GeomBSplineCurve': nodes=curve.getPoles() spline=Part.BSplineCurve() spline.buildFromPoles( nodes ) sd=spline.discretize( self.pts_nbr ) elif type(curve).__name__=='GeomCircle': sd=curve.discretize( self.pts_nbr ) else: sd=curve.discretize( self.pts_nbr ) return sd ##################################### # Function discretize ##################################### def nbpoles(self,curve): if type(curve).__name__=='GeomLineSegment': nbpol=0 elif type(curve).__name__=='GeomBSplineCurve': nbpol=curve.NbPoles elif type(curve).__name__=='GeomCircle': nbpol=1 else: nbpol=0 return nbpol ##################################### # Function unroll ##################################### # Unroll of a face # composed of 2 or 4 edges ##################################### def unroll(self,face): FreeCAD.Console.PrintMessage("UnrollRuledSurface.unroll: Ege Nbr= "+str( face.Edges.__len__())+"\n") if face.Edges.__len__() == 2: e1=face.Edges[0] e2=face.Edges[1] sd1=e1.Curve.discretize( self.pts_nbr ) sd2=e2.Curve.discretize( self.pts_nbr ) elif face.Edges.__len__() == 3: e1=face.Edges[0] e2=face.Edges[2] sd1=e1.Curve.discretize( self.pts_nbr ) sd2=e2.Curve.discretize( self.pts_nbr ) else: E0=face.Edges[0] E1=face.Edges[1] E2=face.Edges[2] E3=face.Edges[3] # # Choose more complexe curve as edge # nbpol0=self.nbpoles(E0.Curve) nbpol1=self.nbpoles(E1.Curve) nbpol2=self.nbpoles(E2.Curve) nbpol3=self.nbpoles(E3.Curve) if nbpol0 + nbpol2 > nbpol1 + nbpol3: e1=E0 e2=E2 v=self.discretize( E1 ) v0=v[0] v1=v[self.pts_nbr-1] else: e1=E1 e2=E3 v=self.discretize( E2 ) v0=v[0] v1=v[self.pts_nbr-1] sd1=self.discretize( e1 ) sd2=self.discretize( e2 ) # # Reverse if curves cross over # if not ( sd2[0].__eq__( v0 ) or not sd2[0].__eq__( v1 ) ): sd2.reverse() # # Create a polygon object and set its nodes # devlxy_l=self.devlxyz( sd1 , sd2 ) FreeCAD.Console.PrintMessage("UnrollRuledSurface.unroll: size devlxy_l: "+str( devlxy_l.__len__())+"\n") p=self.doc.addObject("Part::Polygon","Polygon") p.Nodes=devlxy_l self.doc.recompute() FreeCADGui.SendMsgToActiveView("ViewFit") return p ##################################### # Function vect_copy # - vect: # - return copy of vector ##################################### def vect_copy( self, vect): v= vect + FreeCAD.Base.Vector(0,0,0) return v ##################################### # Function vect_cos # - vect1,2: # - return cos angle between # 2 vectors ##################################### def vect_cos( self , vect1, vect2 ): cosalp=vect1.dot(vect2)/vect1.Length/vect2.Length return cosalp ##################################### # Function vect_sin # - vect1,2: # - return abs(sin) angle between # 2 vectors ##################################### def vect_sin( self , vect1, vect2 ): v= FreeCAD.Base.Vector(0,0,0) v.x=vect1.y*vect2.z-vect1.z*vect2.y v.y=vect1.z*vect2.x-vect1.x*vect2.z v.z=vect1.x*vect2.y-vect1.y*vect2.x sinalp=v.Length/vect1.Length/vect2.Length return sinalp ##################################### # Function devlxyz # - vect1,2: 2 edges of the shape # - return dvlxy_l ##################################### # unroll of a face # composed of 4 edges ##################################### def devlxyz( self , vect1 , vect2 ): # # Init # if ( vect1.__len__() != vect2.__len__()) or ( vect1.__len__() != self.pts_nbr ) or ( vect2.__len__() != self.pts_nbr ): msg="UnrollRuledSurface.devlxyz: incompatility of sizes vect1 , vect2, pts_nbr- "+str( vect1.__len__())+" , "+str( vect2.__len__())+" , "+str( self.pts_nbr )+"\n" FreeCAD.Console.PrintError(msg) errorDialog(msg) devlxy_l=[] devl1xy_l=[] devl2xy_l=[] errormax=0.0 # # Init unroll # AB # a1b1=vect2[0].sub(vect1[0]) oa1=FreeCAD.Vector(0,0,0) devl1xy_l.append( oa1 ) #A1 ob1=FreeCAD.Vector(a1b1.Length,0,0) devl2xy_l.append( ob1 ) #B1 for j in range( 1 , self.pts_nbr ) : # # AB # ab=vect2[j-1].sub(vect1[j-1]) # # AC # ac=vect1[j].sub(vect1[j-1]) # # BD # bd=vect2[j].sub(vect2[j-1]) # # CD # cd=vect2[j].sub(vect1[j]) # # A1B1 in unroll plan # a1b1=devl2xy_l[j-1].sub(devl1xy_l[j-1]) a1b1n=self.vect_copy(a1b1) a1b1n.normalize() a1b1on=FreeCAD.Vector(-a1b1n.y,a1b1n.x,0) # # A1C1 # cosalp=self.vect_cos( ab , ac ) sinalp=self.vect_sin( ab , ac ) a1c1=self.vect_copy(a1b1n) a1c1.multiply(cosalp*ac.Length) v=self.vect_copy(a1b1on) v.multiply(sinalp*ac.Length) a1c1=a1c1.add(v) oa1=self.vect_copy(devl1xy_l[j-1]) oc1=oa1.add(a1c1) devl1xy_l.append(oc1) # # B1D1 # cosalp=self.vect_cos( ab , bd ) sinalp=self.vect_sin( ab , bd ) b1d1=self.vect_copy(a1b1n) b1d1.multiply(cosalp*bd.Length) v=self.vect_copy(a1b1on) v.multiply(sinalp*bd.Length) b1d1=b1d1.add(v) ob1=self.vect_copy(devl2xy_l[j-1]) od1=ob1.add(b1d1) devl2xy_l.append(od1) # # Draw generatrice # c1d1=devl2xy_l[j].sub( devl1xy_l[j] ) if ab.Length <> 0 : errormax=max(errormax,math.fabs(ab.Length-c1d1.Length)/ab.Length) # # The end # FreeCAD.Console.PrintMessage("UnrollRuledSurface Error cd,c1d1: {:.1f} %\n".format(errormax*100)) # # Close polygone # devlxy_l = devl1xy_l devl2xy_l.reverse() devlxy_l.extend( devl2xy_l ) v=FreeCAD.Vector(0,0,0) devlxy_l.append( v ) return devlxy_l ##################################### # Function draw_line # - vect0,1: two points ##################################### def draw_line( self , vect0 , vect1 ): l=Part.Line() l.StartPoint=vect0 l.EndPoint=vect1 self.doc.addObject("Part::Feature","Line").Shape=l.toShape() ##################################### # Class Drawing2d ##################################### class Drawing2d: ##################################### # Function __init__ # - Scale # - scale_auto # - a3 # - cartridge # - onedrawing ##################################### def __init__( self, scale , scale_auto , a3 , cartridge , onedrawing ): self.TopX_H=0 self.TopY_H=0 self.TopX_V=0 self.TopY_V=0 self.TopX_Hmax=0 self.TopY_Hmax=0 self.TopX_Vmax=0 self.TopY_Vmax=0 self.a3=a3 self.scale=scale self.scale_auto=scale_auto self.cartridge=cartridge self.onedrawing=onedrawing if self.a3: self.L=420 self.H=297 self.marge=6 else: self.L=297 self.H=210 self.marge=6 self.name="Page" ##################################### # Function newPage ##################################### def newPage( self ): freecad_dir=os.getenv('HOME')+"/.FreeCAD/Mod/unrollRuledSurface" page = FreeCAD.activeDocument().addObject('Drawing::FeaturePage', self.name ) if self.a3: if self.cartridge: page.Template = freecad_dir+'/A3_Landscape.svg' else: page.Template = freecad_dir+'/A3_Landscape_Empty.svg' else: if self.cartridge: page.Template = freecad_dir+'/A4_Landscape.svg' else: page.Template = freecad_dir+'/A4_Landscape_Empty.svg' return page ##################################### # Function all ##################################### def all( self, obj_l ): for objid in range( obj_l.__len__() ): if objid == 0 or not self.onedrawing: page = self.newPage() else: page = FreeCAD.activeDocument().getObject( self.name ) self.done( objid , obj_l[objid] , page ) ##################################### # Function all ##################################### def done( self, id , obj , page ): # # Init # xmax=obj.Shape.BoundBox.XMax-obj.Shape.BoundBox.XMin ymax=obj.Shape.BoundBox.YMax-obj.Shape.BoundBox.YMin if ymax > xmax : Draft.rotate( obj , 90 ) Draft.move( obj , FreeCAD.Base.Vector( -obj.Shape.BoundBox.XMin , -obj.Shape.BoundBox.YMin , 0)) xmax=obj.Shape.BoundBox.XMax-obj.Shape.BoundBox.XMin ymax=obj.Shape.BoundBox.YMax-obj.Shape.BoundBox.YMin scale=min((self.L-4*self.marge)/xmax,(self.H-4*self.marge)/ymax) if ( not self.scale_auto ) or ( self.onedrawing ) : scale=self.scale FreeCAD.Console.PrintMessage("UnrollRuledSurface.drawing: scale= {:.2f}\n".format(scale)) if id == 0 or not self.onedrawing: # # Init # self.TopX_H=self.marge*2 self.TopY_H=self.marge*2 TopX=self.TopX_H TopY=self.TopY_H self.TopX_H=self.TopX_H + xmax * scale + self.marge self.TopY_H=self.TopY_H self.TopX_Hmax=max( self.TopX_Hmax , self.TopX_H ) self.TopY_Hmax=max( self.TopY_Hmax , self.TopY_H + ymax*scale+self.marge ) self.TopX_Vmax=max( self.TopX_Vmax , self.TopX_Hmax ) self.TopX_V=max(self.TopX_Vmax,self.TopX_V) self.TopY_V=self.marge*2 elif self.onedrawing: if ( self.TopX_H + xmax * scale < self.L ): if ( self.TopY_H + ymax * scale + self.marge*2 < self.H ): # # H Add at right on same horizontal line # TopX=self.TopX_H TopY=self.TopY_H self.TopX_H=self.TopX_H + xmax * scale + self.marge self.TopY_H=self.TopY_H self.TopX_Hmax=max( self.TopX_Hmax , self.TopX_H ) self.TopY_Hmax=max( self.TopY_Hmax , self.TopY_H + ymax*scale+self.marge ) self.TopX_Vmax=max( self.TopX_Hmax , self.TopX_Vmax ) self.TopX_Vmax=max( self.TopX_Vmax , self.TopX_Hmax ) self.TopX_V=max(self.TopX_Vmax,self.TopX_V) else: # # V Add at right on same horizontal line # Draft.rotate( obj , 90 ) Draft.move( obj , FreeCAD.Base.Vector( -obj.Shape.BoundBox.XMin , -obj.Shape.BoundBox.YMin , 0)) self.TopX_V=max(self.TopX_Vmax, self.TopX_V) TopX=self.TopX_V TopY=self.TopY_V self.TopX_V = self.TopX_V + ymax * scale + self.marge self.TopY_Vmax=max( self.TopY_Vmax , self.TopY_V + xmax * scale + self.marge ) else: # # H Carriage return # if ( self.TopY_Hmax + ymax * scale + self.marge*2 < self.H ): TopX=self.marge*2 TopY=self.TopY_Hmax self.TopX_H=TopX + xmax * scale + self.marge self.TopY_H=TopY self.TopX_Hmax=max( self.TopX_Hmax , self.TopX_H ) self.TopY_Hmax=self.TopY_H + ymax*scale+self.marge self.TopX_Vmax=max( self.TopX_Vmax , self.TopX_Hmax ) self.TopX_V=max(self.TopX_Vmax,self.TopX_V) else: # # V Add at right on same horizontal line # Draft.rotate( obj , 90 ) Draft.move( obj , FreeCAD.Base.Vector( -obj.Shape.BoundBox.XMin , -obj.Shape.BoundBox.YMin , 0)) TopX=self.TopX_V TopY=self.TopY_V self.TopX_V = self.TopX_V + ymax * scale + self.marge self.TopY_Vmax=max( self.TopY_Vmax , self.TopY_V + xmax * scale + self.marge ) TopView = FreeCAD.activeDocument().addObject('Drawing::FeatureViewPart','TopView') TopView.Source = obj TopView.Direction = (0.0,0.0,1) TopView.Rotation = 0 TopView.X = TopX TopView.Y = TopY TopView.ShowHiddenLines = False TopView.Scale = scale page.addObject(TopView) FreeCAD.activeDocument().recompute() ##################################### ##################################### # Dialog Box ##################################### ##################################### fields = [[ "File Name" , "UnrollSurface" ]] fields.append(["Dicretization Points Nbr","100" ]) fields.append(["Scale","1" ]) DialogBox = QtGui.QDialog() DialogBox.resize(250,250) DialogBox.setWindowTitle("UnrollRuledSurface") la = QtGui.QVBoxLayout(DialogBox) # # Input fields # for id in range(len( fields )): la.addWidget(QtGui.QLabel( fields[ id ][ 0 ] )) fields_l.append( QtGui.QLineEdit( fields[ id ][ 1 ] )) la.addWidget( fields_l[ id ] ) scale_check = QtGui.QCheckBox( DialogBox ) scale_check.setObjectName("checkBox") scale_check.setChecked(True) la.addWidget(QtGui.QLabel("Scale auto")) la.addWidget(scale_check) a3_check = QtGui.QCheckBox( DialogBox ) a3_check.setObjectName("checkBox") la.addWidget(QtGui.QLabel("A3 Format")) a3_check.setChecked(False) la.addWidget(a3_check) cartridge_check = QtGui.QCheckBox( DialogBox ) cartridge_check.setObjectName("checkBox") la.addWidget(QtGui.QLabel("Cartridge")) cartridge_check.setChecked(False) la.addWidget(cartridge_check) onedrawing_check = QtGui.QCheckBox( DialogBox ) onedrawing_check.setObjectName("checkBox") la.addWidget(QtGui.QLabel("Group drawings in page")) cartridge_check.setChecked(False) la.addWidget(onedrawing_check) box = QtGui.QDialogButtonBox(DialogBox) box = QtGui.QDialogButtonBox(DialogBox) box.setOrientation(QtCore.Qt.Horizontal) box.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) la.addWidget(box) QtCore.QObject.connect(box, QtCore.SIGNAL("accepted()"), proceed ) QtCore.QObject.connect(box, QtCore.SIGNAL("rejected()"), close ) QtCore.QMetaObject.connectSlotsByName(DialogBox) DialogBox.show()