Macro Unfold Box/fr: Difference between revisions

From FreeCAD Documentation
mNo edit summary
mNo edit summary
Line 18: Line 18:
Cf [http://forum.freecadweb.org/viewtopic.php?f=17&t=4587 Macro for unfolding box surfaces]
Cf [http://forum.freecadweb.org/viewtopic.php?f=17&t=4587 Macro for unfolding box surfaces]


== Options ==
<div class="mw-translate-fuzzy">
=== Options ===


* Échelle manuelle ou automatique
* Échelle manuelle ou automatique
Line 25: Line 24:
* Groupe les dessins dans la même page si possible.
* Groupe les dessins dans la même page si possible.
* Attache ou non les bords de la pièce.
* Attache ou non les bords de la pièce.
</div>


<div class="mw-translate-fuzzy">
<div class="mw-translate-fuzzy">

Revision as of 16:37, 9 August 2018

Other languages:

File:Text-x-python Macro Unfold Box

Description
La macro permet de déplier les surfaces d'un objet de n'importe quelle forme et la dessiner sur une page.

Version macro : 1.0
Date dernière modification : 2013-09-20
Auteur: Hervé B.
Auteur
Hervé B.
Téléchargement
None
Liens
Version Macro
1.0
Dernière modification
2013-09-20
Version(s) FreeCAD
None
Raccourci clavier
None
Voir aussi
None

Description

La macro permet de déplier les surfaces d'un objet de n'importe quelle forme et la dessiner sur une page.


Macro_unfoldBox

Installation

Copiez le fichier de la macro dans le répertoire :

  • Linux & Mac  : $home/.Freecad/Mod/unfoldBox.
  • Windows : C:\Program Files\FreeCAD0.13

Ajouter les templates : A3_Landscape_Empty.svg A3_Landscape.svg A4_Landscape_Empty.svg A4_Landscape.svg

Cf Macro for unfolding box surfaces

Options

  • Échelle manuelle ou automatique
  • Format de Page : A3 / A4, cartouche (cf FreeCAD modèles)
  • Groupe les dessins dans la même page si possible.
  • Attache ou non les bords de la pièce.

Utilisation

  1. Sélectionnez un volume créé avec par exemple Part::Loft tool
  2. Développe la forme dans le plan de la forme (cf Draft menu)
  3. Sélectionnez la surface
  4. Exécuter la macro

Script

Macro_unfoldBox.py

Macro_unfoldBox.FCMacro

#***************************************************************************
#*                                                                         *
#*   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 unfoldBox
#     Unroll of a ruled surface
#####################################
import FreeCAD , FreeCADGui , Part, Draft, math, Drawing , PySide, os
from PySide 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(PySide.QtCore.Qt.WindowStaysOnTopHint)
    diag.exec_()


#####################################
# Function proceed 
#####################################
def proceed():
   QtGui.qApp.setOverrideCursor(QtCore.Qt.WaitCursor)

   FreeCAD.Console.PrintMessage("===========================================\n")
   FreeCAD.Console.PrintMessage("unfoldBox: start.\n")
   try:
      file_name  = fields_l[0].text()
      scale    = float(fields_l[1].text())
      scale_auto = scale_check.isChecked()
      a3 = a3_check.isChecked()
      cartridge = cartridge_check.isChecked()
      onedrawing = onedrawing_check.isChecked()
      sewed = sewed_check.isChecked()
      FreeCAD.Console.PrintMessage("unfoldBox.file_name: "+file_name+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.scale: "+str(scale)+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.scale_check: "+str(scale_auto)+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.a3_check: "+str(a3)+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.cartridge: "+str(cartridge)+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.onedrawing: "+str(onedrawing)+"\n")
      FreeCAD.Console.PrintMessage("unfoldBox.sewed: "+str(sewed)+"\n")
   except:
      msg="unfoldBox: wrong inputs...\n"
      FreeCAD.Console.PrintError(msg)
      errorDialog(msg)

   QtGui.qApp.restoreOverrideCursor()
   DialogBox.hide()
   #
   # Get selection
   #
   sel=FreeCADGui.Selection.getSelection()
   faceid=0
   objnames_l=[]
   tree_l=[]
   grp=FreeCAD.activeDocument().addObject("App::DocumentObjectGroup", str(file_name)) 
   for objid in range( sel.__len__() ):
     obj=Draft.clone(sel[objid])
     grp.addObject(obj)
     objnames_l.append( [ obj , sel[objid].Name ] )

   unfold=unfoldBox()
   if sewed : 
       objnames_l=unfold.done(objnames_l)
       grp.addObject(objnames_l[0][0])
   else:
       for objid in range( objnames_l.__len__() ):
         unfold.moveXY(objnames_l[objid][0])

   id=0
   while objnames_l.__len__() > 0:
       draw=Drawing2d( scale, scale_auto , a3 , cartridge , onedrawing , FreeCAD.activeDocument().Name , "Page"+str(id) ) 
       objnames_l=draw.all( objnames_l )
       id=id+1
       FreeCAD.Console.PrintMessage("unfoldBox: obj_l= "+str(objnames_l.__len__())+"\n")

   FreeCAD.Console.PrintMessage("unfoldBox: end.\n")
   FreeCAD.Console.PrintMessage("===========================================\n")


#####################################
# Function close 
#####################################
def close():
   DialogBox.hide()

#####################################
# Class unfoldBox 
#####################################
class unfoldBox:
  #####################################
  # Function __init__ 
  #####################################
  def __init__(self):
     FreeCAD.Console.PrintMessage("unfoldBox.unfoldBox\n")
     self.LIMIT=0.0001


  #####################################
  # Function done 
  #####################################
  def done(self,objnames_l):
       tree_l=self.makeTree(objnames_l)
       for id in range( objnames_l.__len__() ): 
         face=objnames_l[id]
         self.moveXY(face[0])
       self.sew( objnames_l , tree_l )
       return self.fusion(objnames_l)

    
  #####################################
  # Function makeTree 
  #####################################
  def makeTree(self,objnames_l):
     #
     # Initialisation of tree_l
     #
     tree_l=[]
     for k in range( objnames_l.__len__() ):
        facek=objnames_l[k][0]
	facek_l=[]
	for i in range( facek.Shape.Edges.__len__() ):
	   if False and type(facek.Shape.Edges[i].Curve).__name__ != 'GeomLineSegment':
             facek_l.append([-1,-1])
	   else:
	     #
	     # Search face link to the ith edge
	     #
	     vki0=facek.Shape.Edges[i].Curve.StartPoint
	     vki1=facek.Shape.Edges[i].Curve.EndPoint
	     found=False
	     for l in range( k+1 , objnames_l.__len__() ):
               facel=objnames_l[l][0]
	       for j in range( facel.Shape.Edges.__len__() ):
	            vlj0=facel.Shape.Edges[j].Curve.StartPoint
	            vlj1=facel.Shape.Edges[j].Curve.EndPoint
	            if vki0.__eq__(vlj0) and vki1.__eq__(vlj1): 
	                arelinked=False
	                isfacek=False
	                isfacel=False
	                for kk in range( k-1 ):
	                   for ii in range( tree_l[kk].__len__() ):
		              if tree_l[kk][ii][0]==k: isfacek=True
		              if tree_l[kk][ii][0]==l: isfacel=True
		           if isfacek and isfacel: 
		              arelinked=True 
		              break
			if not arelinked:
                          facek_l.append([l,j])
			  found=True
			  break
	            if found: break
	   if not found: facek_l.append([-1,-1])
        tree_l.append(facek_l) 
     return tree_l


  #####################################
  # Function sew 
  #####################################
  def sew( self,objnames_l , tree_l ):
    placed_l=[]
    for k in range( tree_l.__len__() ):
      iskplaced=False
      for p in range( placed_l.__len__() ):
         if placed_l[p] == k:
            iskplaced=True 
      if not iskplaced:placed_l.append(k)
      facek=tree_l[k]
      objk=objnames_l[k][0]
      for i in range( facek.__len__() ):
        edgeki=facek[i]
        l=edgeki[0]
        j=edgeki[1]
	islplaced=False
	for p in range( placed_l.__len__() ):
	     if placed_l[p] == l: 
	        islplaced=True 
		break
	if not islplaced: placed_l.append(l)
        if l >= 0 and not ( islplaced and iskplaced ):
	  iskplaced=True
          #
  	  # Move facel.edgelj to facek.edgeki
  	  #
          objl=objnames_l[l][0]
          vki0=objk.Shape.Edges[i].Curve.StartPoint
          vki1=objk.Shape.Edges[i].Curve.EndPoint
	  vlj0=objl.Shape.Edges[j].Curve.StartPoint
	  vlj1=objl.Shape.Edges[j].Curve.EndPoint
	  vk=vki1.sub(vki0)
	  vl=vlj1.sub(vlj0)
	  alpk=vk.getAngle(vl)*180/math.pi
	  alpl=vl.getAngle(vk)*180/math.pi
          self.isPlanZ(objk)
	  if islplaced:
            Draft.move( objk , vlj0.sub(vki0) )
	  else:
            Draft.move( objl , vki0.sub(vlj0) )
          self.isPlanZ(objk)

	  if math.fabs( vk.dot(FreeCAD.Base.Vector(-vl.y,vl.x,0))) > self.LIMIT:
	     if islplaced:
               Draft.rotate( objk , -alpl , vlj0 , self.vecto( vl , vk ))
	     else:
               Draft.rotate( objl , -alpk , vki0 , self.vecto( vk , vl ))
	  elif vk.dot(vl)<0:
	     if islplaced:
               Draft.rotate( objk , 180 , vlj0 , self.vecto( vl , FreeCAD.Base.Vector(-vl.y,vl.x,0) ))
	     else:
               Draft.rotate( objl , 180 , vki0 , self.vecto( vk , FreeCAD.Base.Vector(-vk.y,vk.x,0)))
          #
	  # Verifications
	  #
          vki0=objk.Shape.Edges[i].Curve.StartPoint
          vki1=objk.Shape.Edges[i].Curve.EndPoint
	  vlj0=objl.Shape.Edges[j].Curve.StartPoint
	  vlj1=objl.Shape.Edges[j].Curve.EndPoint
	  vk=vki1.sub(vki0)
	  vl=vlj1.sub(vlj0)
          self.isPlanZ(objk)

	  #
	  # Flip or not
	  #
          L=max(objl.Shape.BoundBox.XMax,objk.Shape.BoundBox.XMax) - min( objl.Shape.BoundBox.XMin,objk.Shape.BoundBox.XMin) 
          W=max(objl.Shape.BoundBox.YMax,objk.Shape.BoundBox.YMax) - min( objl.Shape.BoundBox.YMin,objk.Shape.BoundBox.YMin) 
	  S1=L*W
	  if islplaced:
	    dum=0
            Draft.rotate( objk , 180 , vlj0 ,vl)
	  else:
	    dum=0
            Draft.rotate( objl , 180 , vki0 ,vk)
          L=max(objl.Shape.BoundBox.XMax,objk.Shape.BoundBox.XMax) - min( objl.Shape.BoundBox.XMin,objk.Shape.BoundBox.XMin) 
          W=max(objl.Shape.BoundBox.YMax,objk.Shape.BoundBox.YMax) - min( objl.Shape.BoundBox.YMin,objk.Shape.BoundBox.YMin) 
	  S2=L*W
	  if (S2<=S1):
	     if islplaced:
	        dum=0
                Draft.rotate( objk , 180 , vlj0 ,vl)
	     else:
	        dum=0
                Draft.rotate( objl , 180 , vki0 ,vk)
          self.isPlanZ(objk)

  #####################################
  # Function isPlanZ 
  #####################################
  def isPlanZ(self,obj):
     L=obj.Shape.BoundBox.XMax - obj.Shape.BoundBox.XMin
     W=obj.Shape.BoundBox.YMax - obj.Shape.BoundBox.YMin
     H=obj.Shape.BoundBox.ZMax - obj.Shape.BoundBox.ZMin
     if H < self.LIMIT:
       return True
     else:
       return False


  #####################################
  # Function fusion 
  #####################################
  def fusion(self,objnames_l):
     #
     # Init
     #
     obj_l=[]
     objna_l=[]
     obj0=objnames_l[0][0];name=objnames_l[0][1]
     objfuse=FreeCAD.activeDocument().addObject("Part::MultiFuse","Unfolding")
     for k in range( objnames_l.__len__() ):
       objk=objnames_l[k][0]
       obj_l.append(objk)
     objfuse.Shapes=obj_l
     FreeCAD.activeDocument().recompute()
     objna_l.append([objfuse,name])
     return objna_l 

  #####################################
  # Function get2Vectors 
  #####################################
  def get2Vectors(self,shape):
    v0=FreeCAD.Base.Vector(0,0,0) 
    v1=FreeCAD.Base.Vector(0,0,0) 

    edges= shape.Edges
    for id in range( edges.__len__()-1):
       va=edges[id].Curve.EndPoint.sub(edges[id].Curve.StartPoint)
       vb=edges[id+1].Curve.EndPoint.sub(edges[id+1].Curve.StartPoint)
       if vb.sub(va).Length > v1.sub(v0).Length:
         v0=self.vect_copy(va);v1=self.vect_copy(vb)
    #FreeCAD.Console.PrintMessage("unfoldBox.get2Vectors: v0= {:s}, v1= {:s}\n".format(str(v0),str(v1)))
    return [ v0 , v1 ]

  #####################################
  # Function vecto 
  #   - vect1,2:  
  #   - return abs(sin) angle between 
  #     2 vectors 
  #####################################
  def vecto( 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
     return v 


  #####################################
  # Function vect_copy 
  #   - vect:  
  #   - return copy of vector
  #####################################
  def vect_copy( self,vect):
     v= vect.add( FreeCAD.Base.Vector(0,0,0) )
     return v 


  #####################################
  # Function movexy 
  #####################################
  def moveXY( self,obj ):
     #
     # Move to origin
     #
     Draft.move( obj , FreeCAD.Base.Vector( -obj.Shape.BoundBox.XMin , -obj.Shape.BoundBox.YMin , -obj.Shape.BoundBox.ZMin ))
     #
     # Find 2 vectors defining the plan of surface
     #
     tab=self.get2Vectors( obj.Shape )
     v0=tab[0];v1=tab[1]
     norm=self.vecto(v0,v1)
     norm.normalize()
     #FreeCAD.Console.PrintMessage("unfoldBox.moveXY: norm= {:s}\n".format(str(norm)))

     #
     # Rotate
     #
     if math.fabs(norm.x) < self.LIMIT and math.fabs(norm.y) < self.LIMIT:
        dum=0
     elif math.fabs(norm.x) < self.LIMIT and math.fabs(norm.z) < self.LIMIT:
        Draft.rotate( obj , 90 , FreeCAD.Base.Vector(0,0,0) , FreeCAD.Base.Vector(1,0,0) )
     elif math.fabs(norm.y) < self.LIMIT and math.fabs(norm.z) < self.LIMIT:
        Draft.rotate( obj , 90 , FreeCAD.Base.Vector(0,0,0) , FreeCAD.Base.Vector(0,1,0) )
     else:
	#
	# Rotate following the angle to the normal direction of the plan
	#
        oz= FreeCAD.Base.Vector(0,0,1)
	alp=oz.getAngle(norm)*180/math.pi
        #FreeCAD.Console.PrintMessage("unfoldBox.moveXY: alp= "+str(alp)+"\n")
        #FreeCAD.Console.PrintMessage("unfoldBox.moveXY: vecto= {:s}\n".format(str(self.vecto(oz,norm))))
        Draft.rotate( obj , -alp , FreeCAD.Base.Vector(0,0,0) , self.vecto( oz, norm ))
     #
     # Move to z=0
     #
     Draft.move( obj , FreeCAD.Base.Vector( 0 , 0 , -obj.Shape.BoundBox.ZMin ))
     L=obj.Shape.BoundBox.XMax - obj.Shape.BoundBox.XMin
     W=obj.Shape.BoundBox.YMax - obj.Shape.BoundBox.YMin
     H=obj.Shape.BoundBox.ZMax - obj.Shape.BoundBox.ZMin


#####################################
# Class Drawing2d 
#####################################
class Drawing2d:
  #####################################
  # Function __init__ 
  #     - Scale
  #     - scale_auto
  #     - a3
  #     - cartridge
  #     - onedrawing
  #####################################
  def __init__( self,  scale , scale_auto , a3 , cartridge , onedrawing , drawing_name , page_name ):
    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.pts_nbr=100
    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.page_name=page_name
    self.drawing_name=drawing_name

  #####################################
  # Function newPage 
  #####################################
  def newPage( self ):
    freecad_dir=os.getenv('HOME')+"/.FreeCAD/Mod/unfoldBox"
    page = FreeCAD.activeDocument().addObject('Drawing::FeaturePage', self.page_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, objnames_l ):
      obj_l=[]
      for objid in range( objnames_l.__len__() ):
        if objid == 0 or not self.onedrawing:
          page = self.newPage()
        obj_l.extend( self.done( objid , objnames_l[objid] ))
      return obj_l 




  #####################################
  # Function done 
  #####################################
  def done( self, id , objname ):
    #
    # Init
    #
    obj_l=[]
    obj=objname[0]
    objname=objname[1]
    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


    if id == 0 or not self.onedrawing:
      #
      # Init
      #
      FreeCAD.Console.PrintMessage("Dawing2d: init\n")
      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
	   #
           FreeCAD.Console.PrintMessage("Dawing2d: horizontal\n")
           TopX=self.TopX_H
           TopY=self.TopY_H
           self.TopX_H=self.TopX_H + xmax * scale + self.marge
	   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
	   #
           FreeCAD.Console.PrintMessage("Dawing2d: vertival\n")
           if self.TopX_V + ymax * scale +2* self.marge < self.L and self.TopY_V + xmax * scale + 2*self.marge < self.H :
             Draft.rotate( obj , 90 )
	     Draft.move( obj , FreeCAD.Base.Vector( -obj.BoundBox.XMin , -obj.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:
	     obj_l.append( [ obj , name ] )
	     return obj_l

      else:
	#
	# H Carriage return 
	#
        if ( self.TopY_Hmax + ymax * scale + self.marge*2 < self.H ):   
           FreeCAD.Console.PrintMessage("Dawing2d: carriage return: "+str(self.TopY_H + ymax * scale )+" > "+str(self.H)+"\n")
           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_Hmax + 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
	   #
           FreeCAD.Console.PrintMessage("Dawing2d: vertival: "+str(self.TopX_V)+" , "+str(self.TopX_Vmax)+"\n")
           if self.TopX_V + ymax * scale + 2*self.marge < self.L and self.TopY_V + xmax * scale + 2*self.marge < self.H :
             Draft.rotate( obj , 90 )
	     Draft.move( obj , FreeCAD.Base.Vector( -obj.BoundBox.XMin , -obj.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 )
	   else:
	     obj_l.append( [ obj , name ] )
	     return obj_l

    page=FreeCAD.activeDocument().getObject(self.page_name )

    Text=FreeCAD.activeDocument().addObject('Drawing::FeatureViewAnnotation', objname+"_txt")
    Text.Text=objname
    Text.X=TopX+xmax/2*scale
    Text.Y=TopY+ymax/2*scale
    Text.Scale=1

    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 = True
    TopView.Scale = scale 
    page.addObject(TopView)
    page.addObject(Text)
    FreeCAD.activeDocument().recompute()
    return obj_l




#####################################
#####################################
# Dialog Box 
#####################################
#####################################
fields = [[ "Group Name" , "Unfolding" ]]
fields.append(["Scale","1" ])

DialogBox = QtGui.QDialog()
DialogBox.resize(250,250)
DialogBox.setWindowTitle("unfoldBox")
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"))
onedrawing_check.setChecked(True)
la.addWidget(onedrawing_check)

sewed_check = QtGui.QCheckBox( DialogBox )
sewed_check.setObjectName("checkBox")
la.addWidget(QtGui.QLabel("Sewed surfaces"))
sewed_check.setChecked(True)
la.addWidget(sewed_check)

box = QtGui.QDialogButtonBox(DialogBox)

box = QtGui.QDialogButtonBox(DialogBox)
box.setOrientation(QtCore.Qt.Horizontal)
box.setStandardButtons(QtGui.QDialogButtonBox.Cancel