Nuova versione Guida allo Scripting

Forum per le domande e le discussioni in Italiano
Forum rules
regole del forum e le informazioni utili

Importante: PRIMA di chiedere aiuto leggete qui!
Luixx
Posts: 155
Joined: Thu Jan 25, 2018 9:12 am

Re: Nuova versione Guida allo Scripting

Postby Luixx » Tue Sep 15, 2020 8:48 pm

ok appena posso leggo tutto quello che mi hai scritto. per adesso sto facendo altro (Lavori di casa) e poi dove ho il computer si muore dal caldo. ti ringrazio molto e buona settimana. grazie mille e scusa del ritardo.
onekk
Posts: 400
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Nuova versione Guida allo Scripting

Postby onekk » Wed Sep 16, 2020 8:53 am

Nessun problema. Buoni lavori di casa.

Saluti

Carlo D.
Luixx
Posts: 155
Joined: Thu Jan 25, 2018 9:12 am

Re: Nuova versione Guida allo Scripting

Postby Luixx » Wed Sep 16, 2020 2:25 pm

ok ti ringrazio molto e funziona senza problemi..

poi si potrebbe fare il tool "cut" sempre più oggetti insieme.

grazie mille e grazie del codice.
Luixx
Posts: 155
Joined: Thu Jan 25, 2018 9:12 am

Re: Nuova versione Guida allo Scripting

Postby Luixx » Wed Oct 14, 2020 10:19 am

ciao onekk . ti volevo dirti sai mica come si chiama tube? in part::tube perché non me lo prende. ti posto tutto il codice:

Code: Select all

import FreeCAD, FreeCADGui, Part
App = FreeCAD
Gui = FreeCADGui

class document():
    def __init__(self, doc):
        self.doc = doc
    def create(self):
        App.newDocument()
        App.setActiveDocument("" + self.doc + "")
        App.ActiveDocument=App.getDocument("" + self.doc + "")
        Gui.ActiveDocument=Gui.getDocument("" + self.doc + "")

    def refresh(self):
        App.ActiveDocument.recompute()
        Gui.SendMsgToActiveView("ViewFit")
        Gui.activeDocument().activeView().viewIsometric()

class tube():
    def __init__(self, name):
        self.name = name
        self.obj = None
    def create(self, height, inner_radius, outer_radius):
        tube = App.ActiveDocument.addObject("Part::Tube", self.name)
        tube.Height = height
        tube.InnerRadius = length
        tube.OuterRadius = width
        self.obj = tube

class box():
    def __init__(self, name):
        self.name = name
        self.obj = None

    def create(self, height, length, width):    
        box = App.ActiveDocument.addObject("Part::Box", self.name)
        box.Height = height
        box.Length = length
        box.Width = width

        self.obj = box

class cylinder():
    def __init__(self, name):
        self.name  = name
        self.obj = None

    def create(self, radius , height , angle):
        cylinder = App.ActiveDocument.addObject("Part::Cylinder", self.name)
        cylinder.Radius = radius
        cylinder.Height = height
        cylinder.Angle  = angle
        self.obj = cylinder

class boolTool():
    def __init__(self, name):
        self.name = name
        self.obj = None

    def multi_fuse(self, objs):
        shapes = []
        for name in objs:
            shape = App.ActiveDocument.getObject(name) ##Stai passando i nomi non self.name che è nel caso d'esempio "bool1"
            if shape is None:
                pass
            else:
                shapes.append(shape)
        print(shapes)
        if shapes is []:
            print("operazione non riuscita, controlla i nomi passati")
            return None
        else:
            obj = App.ActiveDocument.addObject("Part::MultiFuse", self.name)
            obj.Shapes = shapes
            obj.Refine = True
            App.ActiveDocument.recompute()
            self.obj = obj
            return obj

doc = document("Unnamed")
doc.create()

box1 = box("box1")
print("init box")
box1.create(10,20,60)
print("create box")
box1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place box")
doc.refresh()
print("refresh1")

cylinder1 = cylinder("cylinder1")
print("init cyl")
cylinder1.create(20,10,360)
print("create cyl")
cylinder1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place cyl")
tube1 = tube("tube1")
print("init tube1")
tube1.create(20,10,5)
print("create tube1")
tube1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place tube1")
bool1 =  boolTool("bool1")
print("init bool")
objs = ("box1", "cylinder1") ## questi sono i nomi degli oggetti che devi recuperare poi con la funzione App.ActiveDocument.getObject(name) 
bool1.multi_fuse(objs)
print("fuse objs")

doc.refresh()
print("refresh2")
in questo pezzo:

Code: Select all

class tube():
    def __init__(self, name):
        self.name = name
        self.obj = None
    def create(self, height, inner_radius, outer_radius):
        tube = App.ActiveDocument.addObject("Part::Tube", self.name)
        tube.Height = height
        tube.InnerRadius = length
        tube.OuterRadius = width
        self.obj = tube
Non riesco ad intercettare il tubo messo in freecad 0.19 ultime versioni.

Hai idea?.
Grazie mille.
renatorivo
Posts: 2609
Joined: Tue Feb 21, 2012 8:07 pm
Location: Torino - Italy

Re: Nuova versione Guida allo Scripting

Postby renatorivo » Wed Oct 14, 2020 12:22 pm

Luixx
Posts: 155
Joined: Thu Jan 25, 2018 9:12 am

Re: Nuova versione Guida allo Scripting

Postby Luixx » Wed Oct 14, 2020 12:48 pm

renatorivo wrote:
Wed Oct 14, 2020 12:22 pm
Vedi se questo https://github.com/FreeCAD/FreeCAD/blob ... /Shapes.py è utile
sto facendo .. funziona , crea nell'albero ...ma non lo vedo nella viewport.
ecco il codice:

Code: Select all

import FreeCAD, FreeCADGui, Part
App = FreeCAD
Gui = FreeCADGui

class document():
    def __init__(self, doc):
        self.doc = doc
    def create(self):
        App.newDocument()
        App.setActiveDocument("" + self.doc + "")
        App.ActiveDocument=App.getDocument("" + self.doc + "")
        Gui.ActiveDocument=Gui.getDocument("" + self.doc + "")

    def refresh(self):
        App.ActiveDocument.recompute()
        Gui.SendMsgToActiveView("ViewFit")
        Gui.activeDocument().activeView().viewIsometric()

class tube():
    def __init__(self, name):
        self.name = name
        self.obj = None
    def create(self, height, inner_radius, outer_radius):
       # tube = App.ActiveDocument.addObject("PartDesign::Tube", self.name)
        tube = App.ActiveDocument.addObject("Part::FeaturePython","Tube", self.name)
        tube.addProperty("App::PropertyLength","OuterRadius","Tube","Outer radius").OuterRadius = outer_radius
        tube.addProperty("App::PropertyLength","InnerRadius","Tube","Inner radius").InnerRadius = inner_radius
        tube.addProperty("App::PropertyLength","Height","Tube", "Height of the tube").Height = height
        tube.addExtension("Part::AttachExtensionPython", self.name)
        self.obj = tube

class box():
    def __init__(self, name):
        self.name = name
        self.obj = None

    def create(self, height, length, width):    
        box = App.ActiveDocument.addObject("Part::Box", self.name)
        box.Height = height
        box.Length = length
        box.Width = width

        self.obj = box

class cylinder():
    def __init__(self, name):
        self.name  = name
        self.obj = None

    def create(self, radius , height , angle):
        cylinder = App.ActiveDocument.addObject("Part::Cylinder", self.name)
        cylinder.Radius = radius
        cylinder.Height = height
        cylinder.Angle  = angle
        self.obj = cylinder

class boolTool():
    def __init__(self, name):
        self.name = name
        self.obj = None

    def multi_fuse(self, objs):
        shapes = []
        for name in objs:
            shape = App.ActiveDocument.getObject(name) ##Stai passando i nomi non self.name che è nel caso d'esempio "bool1"
            if shape is None:
                pass
            else:
                shapes.append(shape)
        print(shapes)
        if shapes is []:
            print("operazione non riuscita, controlla i nomi passati")
            return None
        else:
            obj = App.ActiveDocument.addObject("Part::MultiFuse", self.name)
            obj.Shapes = shapes
            obj.Refine = True
            App.ActiveDocument.recompute()
            self.obj = obj
            return obj

doc = document("Unnamed")
doc.create()

box1 = box("box1")
print("init box")
box1.create(10,20,60)
print("create box")
box1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place box")
doc.refresh()
print("refresh1")

cylinder1 = cylinder("cylinder1")
print("init cyl")
cylinder1.create(20,10,360)
print("create cyl")
cylinder1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place cyl")
tube1 = tube("tube1")
print("init tube1")
tube1.create(40,10,10)
print("create tube1")
tube1.Placement = FreeCAD.Placement(App.Vector(10,10,10), App.Rotation(45,0,0))
print("place tube1")
bool1 =  boolTool("bool1")
print("init bool")
objs = ("box1", "cylinder1") ## questi sono i nomi degli oggetti che devi recuperare poi con la funzione App.ActiveDocument.getObject(name) 
bool1.multi_fuse(objs)
print("fuse objs")

doc.refresh()
print("refresh2")
Immagine.jpg
Immagine.jpg (449.2 KiB) Viewed 138 times
idee?

Code: Select all

class tube():
    def __init__(self, name):
        self.name = name
        self.obj = None
    def create(self, height, inner_radius, outer_radius):
       # tube = App.ActiveDocument.addObject("PartDesign::Tube", self.name)
        tube = App.ActiveDocument.addObject("Part::FeaturePython","Tube", self.name)
        tube.addProperty("App::PropertyLength","OuterRadius","Tube","Outer radius").OuterRadius = outer_radius
        tube.addProperty("App::PropertyLength","InnerRadius","Tube","Inner radius").InnerRadius = inner_radius
        tube.addProperty("App::PropertyLength","Height","Tube", "Height of the tube").Height = height
        tube.addExtension("Part::AttachExtensionPython", self.name)
        self.obj = tube
renatorivo
Posts: 2609
Joined: Tue Feb 21, 2012 8:07 pm
Location: Torino - Italy

Re: Nuova versione Guida allo Scripting

Postby renatorivo » Wed Oct 14, 2020 5:27 pm

Luixx wrote:
Wed Oct 14, 2020 12:48 pm
idee?
Due,
la prima; il tuo diametro interno e diametro esterno sono uguali, quindi il tubo è senza spessore, comunque anche variando i valori il tubo non si vede, quindi
seconda idea: il tubo viene creato sottraendo un cilindro ad un altro cilindro, cioè mi pare che sia un composto, come indicato nelle proprietà Dati -> Shape quando si crea un tubo usando il comando di Part, a differenza del tubo che crea la macro; confronta questa proprietà nei due oggetti.
In attesa della soluzione di onekk
onekk
Posts: 400
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Nuova versione Guida allo Scripting

Postby onekk » Thu Oct 15, 2020 7:57 am

Il programma funziona alla perfezione, infatti crea un oggetto con le proprietà corrette.

Peccato che questo ogetto non contenga una "forma" ma solo le proprietà.

manca la parte che assegna una forma a questo ogetto.

Non sono esperto della parte GUI, per cui non so se un oggetto

Code: Select all

"Part::FeaturePython"
Abbia o meno una proprietà shape e soprattutto come fare a dire a FreeCAD che quanto cambi i parametri tramite l'interfaccia grafica deva ricalcolare l'oggetto visualizzato per riflettere il cambiamento dei parametri.

Rimane sempre il problema di capire lo "scopo" della programmazione:

1) creare Macro per velocizzare la creazione di determinati oggetti tramite la GUI
2) intervenire sulla parte interna di FreeCAD per estenderla
3) usare il modellatore di FreeCAD per creare oggetti descritti usando uno script.

La mia guida chiaramente si dedica al punto 3, mentre tu con questi esempi sembra che voglia realizzare una operazione più simile al punto 1.

Se devo creare un tubo o una tubificazione, mi interessa crearlo con uno script, non mi interessa tutta la parte inutile della visualizzazione e del cambiamento delle proprietà mediante la GUI.

Mi interessa piuttosto un workflow che permetta una scrittura "concisa" di quello che volgio realizzare.

devo fare una piastra con 100 fori e ho le coordinate dei fori, faccio prima a creare uno script che prenda la "lista" delle coordiate e mi crei i 100 fori velocemente, piuttosto che creare un oggetto GUI che poi mi permetta di modificare le posizioni dei fori tramite la GUI, faccio prima a modificare il sorgente dello script che ad aprire la GUI e fare le modifiche che poi resteranno solo nel documento finale e non enllo script di creazione.

Se la devo realizzare una travatura complessa usando dei tubi, mi piacerebbe poter fornire le coordinate dei nodi e lasciare che il programma disegni tutta la tubificazione, mi interesserà poco poter modificare i nodi graficamente, dato che poi la creazione dei nodi è fatta dal programma.

Ovviamente questo è solo uno dei possibili modi di procedere, come nella realizzazione di uno script, puoi esplicitamente creare "forme" che sono "Oggetti documento" è quindi con le primitive modificabili, oppure creare un "contenitore" con la forma finale che è il frutto di tutta una serie di calcoli, ma che alla fine non è modificabile nei suoi componenti di base.

Come fare e perché dipende anche dal livello di complessità di quello che stai realizzando, molti "oggetti documento" consumano memoria e rallentano FreeCAD, ma rendono più flessibile modificare le cose anche tramite la GUI.

Sta a te scegliere il procedimento più comodo e più adatto al tuo modo di lavorare oppure al lavoro stesso.

Alcune tecniche di programmazione le puoi tranquillamente usare in ognuno dei tre "scenari" che ho descritto prima, in fin dei conti è sempre Python ed è sempre FreeCAD, molte tecniche che ho illustrato nella guida permettono di "ispezionare" gli oggetti e le proprietà, la disponibilità dei sorgenti ti permette di analizzare il modo con cui sono creati gli oggetti.

Mi spiace di non poterti aiutare ulteriormente, al momento non ho tempo di analizzare i sorgenti e di immergermi nella parte "programmazione GUI" di FreeCAD in modo da poterti indirizzare alla soluzione del tuo problema, ma rispetto allo scopo della guida che è appunto lo scripting e non la creazione di Macro e nemmeno la creazione di "nuovi oggetti" grafici. Questo lo lascio a chi è più esperto di me, perché va oltre lo scopo originale della guida.

Saluti

Carlo D.
carlopav
Posts: 1564
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: Nuova versione Guida allo Scripting

Postby carlopav » Thu Oct 15, 2020 10:20 am

onekk wrote:
Thu Oct 15, 2020 7:57 am
Non sono esperto della parte GUI, per cui non so se un oggetto

Code: Select all

"Part::FeaturePython"
Abbia o meno una proprietà shape e soprattutto come fare a dire a FreeCAD che quanto cambi i parametri tramite l'interfaccia grafica deva ricalcolare l'oggetto visualizzato per riflettere il cambiamento dei parametri.
Si, la Part::FeaturePython ha una proprietà Shape e l'oggetto viene automaticamente marcato da ricalcolare quando questa viene modificata o quando un parametro che iteressa il calcolo della Shape nel metodo execute() dell'oggetto viene modificato.
follow my experiments on BIM modelling for architecture design
onekk
Posts: 400
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Nuova versione Guida allo Scripting

Postby onekk » Thu Oct 15, 2020 1:59 pm

carlopav wrote:
Thu Oct 15, 2020 10:20 am
onekk wrote:
Thu Oct 15, 2020 7:57 am
Non sono esperto della parte GUI, per cui non so se un oggetto

Code: Select all

"Part::FeaturePython"
Abbia o meno una proprietà shape e soprattutto come fare a dire a FreeCAD che quanto cambi i parametri tramite l'interfaccia grafica deva ricalcolare l'oggetto visualizzato per riflettere il cambiamento dei parametri.
Si, la Part::FeaturePython ha una proprietà Shape e l'oggetto viene automaticamente marcato da ricalcolare quando questa viene modificata o quando un parametro che iteressa il calcolo della Shape nel metodo execute() dell'oggetto viene modificato.
Grazie per l'informazione.

Prima o poi dovrò dare una veloce occhiata alla parte GUI, per informazione mia e di chi ha fatto la domanda in origine, hai qualche link dove trovare informazioni più approfondite sul meccanismo di funzionamento degli oggetti FeaturePython?

Saluti

Carlo D.