Part-o-magic (again) [icon ideas for new tool wanted!]

Need help, or want to share a macro? Post here!
triplus
Posts: 4866
Joined: Mon Dec 12, 2011 4:45 pm

Re: Part-o-magic (again) [new feature - ShapeGroup(Compound) container]

Postby triplus » Thu Mar 02, 2017 12:49 pm

DeepSOIC wrote:
triplus wrote:I am guessing entering the shape group edit mode and doing whatever users wants instead isn't an option?
Actually, it is!


In its current form or possible in the future? As setting Operation property to None does enable me to do something like that. But i can't place the result after when using Assembly 2.
DeepSOIC
Posts: 4507
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Part-o-magic (again) [new feature - ShapeGroup(Compound) container]

Postby DeepSOIC » Thu Mar 02, 2017 5:23 pm

triplus wrote:In its current form or possible in the future? As setting Operation property to None does enable me to do something like that.
In current form. Just leave the operation in "Compound". Activate the group and fuse some stuff that it already contains. The originals should be withdrawn from the result by this bit of "smartness" code:

Code: Select all

    def advanceTip(self, selfobj, new_object):
        if new_object.Name.startswith("ShapeBinder"): return
        import copy
        # general idea: New object is always added to the tip. If new object is an operation applied to an old object, old object is withdrawn from tip.
        old_tip = selfobj.Tip
        new_tip = copy.copy(old_tip)
        if new_object in old_tip: return # unlikely to happen. It's just a fail-safe.
        new_tip.append(new_object)
        for obj in set(new_object.OutList): # set() is here to remove duplicates, otherwise exception may arise when removing an already removed object
            if obj in old_tip:
                new_tip.remove(obj)
       
        if new_tip == old_tip: return
        selfobj.Tip = new_tip

ShapeGroup also has a Tip like Module and Body do, but it is a list rather than a single link. It is not user-editable as of now, but I plan to introduce a way to update Tip based on visibility (it will probably be a context menu command).
triplus
Posts: 4866
Joined: Mon Dec 12, 2011 4:45 pm

Re: Part-o-magic (again) [new feature - ShapeGroup(Compound) container]

Postby triplus » Thu Mar 02, 2017 9:10 pm

DeepSOIC wrote:In current form. Just leave the operation in "Compound". Activate the group and fuse some stuff that it already contains.


Indeed they are there on the toolbar. Commands to enter and leave the edit mode. I have overlooked that.

ShapeGroup also has a Tip like Module and Body do, but it is a list rather than a single link. It is not user-editable as of now, but I plan to introduce a way to update Tip based on visibility (it will probably be a context menu command).


Or remove it altogether like the Operation property. For us the inexperienced users not to get lost in it. We just want to put things we can edit in it and after to be able to place them around when we are not editing them. ;)
DeepSOIC
Posts: 4507
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Part-o-magic (again)

Postby DeepSOIC » Sun Mar 05, 2017 4:48 pm

Example project, showcasing Module container.
rotating plate.png
rotating plate.png (556.57 KiB) Viewed 179 times
rotating plate v01.FCStd
(39.09 KiB) Downloaded 7 times
User avatar
easyw-fc
Posts: 609
Joined: Thu Jul 09, 2015 9:34 am

Re: Part-o-magic (again)

Postby easyw-fc » Sun Mar 05, 2017 8:44 pm

DeepSOIC wrote:Example project, showcasing Module container.


Hi, very nice WB...
I tested latest on win10 and FreeCAD_0.17.10423_x64_dev_win but I miss 2 icons...
pom-icons.png
pom-icons.png (88.32 KiB) Viewed 162 times

would you please check it?
Thx
Maurice
DeepSOIC
Posts: 4507
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Part-o-magic (again)

Postby DeepSOIC » Sun Mar 05, 2017 8:57 pm

easyw-fc wrote:but I miss 2 icons
These are super new tools, I'm working on the icons.
User avatar
easyw-fc
Posts: 609
Joined: Thu Jul 09, 2015 9:34 am

Re: Part-o-magic (again)

Postby easyw-fc » Sun Mar 05, 2017 9:11 pm

DeepSOIC wrote:
easyw-fc wrote:but I miss 2 icons
These are super new tools, I'm working on the icons.

I thought it was a problem in my installation...
thx :)
User avatar
easyw-fc
Posts: 609
Joined: Thu Jul 09, 2015 9:34 am

Re: Part-o-magic (again) [new feature - ShapeGroup(Compound) container]

Postby easyw-fc » Mon Mar 06, 2017 1:36 pm

easyw-fc wrote:ATM I found a small issue... I can apply colors to sub-parts, but they get lost when exporting the file as STEP... Is there something that can be improved?

DeepSOIC wrote:I'm afraid, to support colors, I may have to move over to c++.

Hi DeepSOIC
I tried to do a simple copy of a ShapeGroup conserving colors with a Macro in python and I can do it just applying multiply Placements to the Group and included objects
shapegroup-test-base.FCStd
(6.79 KiB) Downloaded 5 times

here the macro I used for a single copy with colors

Code: Select all

# -*- coding: utf-8 -*-
# creating simple copy of App::Part
# https://forum.freecadweb.org/viewtopic.php?f=10&t=2530
# https://forum.freecadweb.org/viewtopic.php?t=3561
## https://forum.freecadweb.org/viewtopic.php?t=11014
#
 
__title__   = "simple copy App::Part"
__author__  = "maurice"
__url__     = "kicad stepup"
__version__ = "0.3"
__date__    = "03.2017"
 
## todo:
# add pause observer
# add multi level (it works only with one nested ShapeGroup)
 
import FreeCAD, FreeCADGui, Draft, Part
import PySide
from PySide import QtGui, QtCore
#import OpenSCADUtils

disable_PoM_Observer = False
try:
    import PartOMagic
    import PartOMagic.Gui.Observer as Observer
    disable_PoM_Observer = True
except:
    FreeCAD.Console.PrintMessage("PoM not present\n")

def say(*msg):
    FreeCAD.Console.PrintMessage(" ".join(map(str,msg)) + "\n")
    #FreeCAD.Console.PrintMessage(msg)
    #FreeCAD.Console.PrintMessage('\n')

def clear_console():
    #clearing previous messages
    mw=Gui.getMainWindow()
    c=mw.findChild(QtGui.QPlainTextEdit, "Python console")
    c.clear()
    r=mw.findChild(QtGui.QTextEdit, "Report view")
    r.clear()

def simple_copy(obj):

    s=obj.Shape
    App.ActiveDocument.addObject('Part::Feature',obj.Name+"_cp").Shape=s
    FreeCADGui.ActiveDocument.ActiveObject.ShapeColor=FreeCADGui.ActiveDocument.getObject(obj.Name).ShapeColor
    FreeCADGui.ActiveDocument.ActiveObject.LineColor=FreeCADGui.ActiveDocument.getObject(obj.Name).LineColor
    FreeCADGui.ActiveDocument.ActiveObject.PointColor=FreeCADGui.ActiveDocument.getObject(obj.Name).PointColor
    FreeCADGui.ActiveDocument.ActiveObject.DiffuseColor=FreeCADGui.ActiveDocument.getObject(obj.Name).DiffuseColor
    FreeCADGui.ActiveDocument.ActiveObject.Transparency=FreeCADGui.ActiveDocument.getObject(obj.Name).Transparency
    new_label=obj.Label
    FreeCAD.ActiveDocument.ActiveObject.Label=new_label
    FreeCAD.ActiveDocument.recompute()

   
def simple_copy_placement(obj,pchild,proot):

    s=obj.Shape
    t=s.copy()
    r=s.copy()
    r.Placement=FreeCAD.Placement(proot)
    t.Placement=r.Placement.multiply(t.Placement)  #incremental Placement
    App.ActiveDocument.addObject('Part::Feature',obj.Name+"_cp").Shape=t
    FreeCADGui.ActiveDocument.ActiveObject.ShapeColor=FreeCADGui.ActiveDocument.getObject(obj.Name).ShapeColor
    FreeCADGui.ActiveDocument.ActiveObject.LineColor=FreeCADGui.ActiveDocument.getObject(obj.Name).LineColor
    FreeCADGui.ActiveDocument.ActiveObject.PointColor=FreeCADGui.ActiveDocument.getObject(obj.Name).PointColor
    FreeCADGui.ActiveDocument.ActiveObject.DiffuseColor=FreeCADGui.ActiveDocument.getObject(obj.Name).DiffuseColor
    FreeCADGui.ActiveDocument.ActiveObject.Transparency=FreeCADGui.ActiveDocument.getObject(obj.Name).Transparency
    new_label=obj.Label
    FreeCAD.ActiveDocument.ActiveObject.Label=new_label
   
def removesubtree(objs):
    def addsubobjs(obj,toremoveset):
        toremove.add(obj)
        for subobj in obj.OutList:
            addsubobjs(subobj,toremoveset)

    import FreeCAD
    toremove=set()
    for obj in objs:
        addsubobjs(obj,toremove)
    checkinlistcomplete =False
    while not checkinlistcomplete:
        for obj in toremove:
            if (obj not in objs) and (frozenset(obj.InList) - toremove):
                toremove.remove(obj)
                break
        else:
            checkinlistcomplete = True
    for obj in toremove:
        obj.Document.removeObject(obj.Name)

##

clear_console()

selEx = FreeCADGui.Selection.getSelectionEx()
objs = [selobj.Object for selobj in selEx]
coords = []
j = 0

plcmt=[]
if len(objs) >= 1:
    for obj in objs:
        #s = objs[0].Shape
        say (obj.TypeId)
        #say(App.ActiveDocument.getObject(obj.Name).InList)
        if "App::Part" in obj.TypeId:
            say ("App::Part")
            say (obj.Placement)
            plcmt.append(obj.Placement)
            grp=App.ActiveDocument.getObject(obj.Name).OutList
            for i in grp:
                if "Part" in i.TypeId:
                    say("Name="+i.Name+" Label="+i.Label)
                    say (i.Placement)
                    plcmt.append(i.Placement)
        if "ShapeGroup" in obj.Name:
            say ("ShapeGroup")
            say (obj.Placement)
            plcmt.append(obj.Placement)
            grp=App.ActiveDocument.getObject(obj.Name).OutList
            Lbl_list=[]
            for i in grp:
                if "Part" in i.TypeId:
                    #if "ShapeGroup" not in i.Name:
                    say("Name="+i.Name+" Label="+i.Label)
                    say (i.Placement)
                    #if Lbl_prev != i.Label:
                    #    plcmt.append(i.Placement)
                    if i.Label not in Lbl_list:
                        plcmt.append(i.Placement)
                    Lbl_list.append(i.Label)
                    #Lbl_prev = i.Label
           
    #App.ActiveDocument.recompute()
else:
    say("Select an object !")

compound_list=[]   
main_label="_"
say(plcmt)
if len(objs) >= 1:
    for obj in objs:
        #s = objs[0].Shape
        say (obj.TypeId)
        #say(App.ActiveDocument.getObject(obj.Name).InList)
        if "App::Part" in obj.TypeId:
            say ("App::Part")
            main_label=obj.Label
            say (obj.Placement)
            #plcmt.append(obj.Placement)
            grp=App.ActiveDocument.getObject(obj.Name).OutList
            for i in grp:
                if "Part" in i.TypeId:
                    say("Name="+i.Name+" Label="+i.Label)
                    say (i.Placement)
                    #plcmt.append(i.Placement)
                    simple_copy_placement(i,i.Placement,plcmt[0])
        if "ShapeGroup" in obj.Name:
            say ("ShapeGroup")
            main_label=obj.Label
            say (obj.Placement)
            #plcmt.append(obj.Placement)
            grp=App.ActiveDocument.getObject(obj.Name).OutList
            Lbl_prev = ""
            Lbl_list=[]
            for i in grp:
                if "Part" in i.TypeId:
                    say("Name="+i.Name+" Label="+i.Label)
                    say (i.Placement)
                    #if Lbl_prev != i.Label:
                    #    plcmt.append(i.Placement)
                    if i.Label not in Lbl_list:
                        #plcmt.append(i.Placement)
                        simple_copy_placement(i,i.Placement,plcmt[0])
                        compound_list.append(FreeCAD.ActiveDocument.ActiveObject)
                    Lbl_list.append(i.Label)
                    #Lbl_prev = i.Label

    #App.ActiveDocument.recompute()
else:
    say("Select an object !")

for p in compound_list:
    say (p.Label)
   
FreeCAD.activeDocument().addObject("Part::Compound",'MultiPart')
FreeCAD.activeDocument().ActiveObject.Links = compound_list #[FreeCAD.activeDocument().Part__Feature,FreeCAD.activeDocument().Shape,]
FreeCAD.ActiveDocument.recompute()
mycompound=FreeCAD.activeDocument().ActiveObject
for obj in FreeCAD.activeDocument().Objects:
    # do what you want to automate
    FreeCADGui.Selection.removeSelection(obj)

FreeCADGui.Selection.addSelection(mycompound)
objC=FreeCAD.ActiveDocument.getObject('MultiPart')
#App.ActiveDocument.copyObject(App.ActiveDocument.MultiPart, False)
simple_copy(objC)
FreeCAD.ActiveDocument.ActiveObject.Label=main_label+" simple copy"

PoMObs_status = False
if Observer.isRunning():
    PoMObs_status=True
#if PoMObs_status:
    Observer.stop()
    say("disabling PoM Observer")
   
removesubtree(FreeCADGui.Selection.getSelection())
FreeCAD.ActiveDocument.recompute()
if PoMObs_status:
    Observer.start()
    say("enabling PoM Observer")


ATM the macro can make a single copy of just one level of ShapeGroup, I cannot make a simple copy with colors of nested ShapeGroups...
Unfortunately I don't know how to recursive efficiently the nested structure... :?

Anyway what I wanted to post here was just an early approach to have a simple copy with colors of the new ShapeGroup object just using python...
May be it would be an easier approach changing some part of C++ code ...

Maurice
triplus
Posts: 4866
Joined: Mon Dec 12, 2011 4:45 pm

Re: Part-o-magic (again)

Postby triplus » Mon Mar 06, 2017 2:08 pm

Looking good.

P.S.As for the container part. Do you have any plans to upstream it? Are there any plans to change the behaviour and to preserve feature hierarchy?
DeepSOIC
Posts: 4507
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Part-o-magic (again)

Postby DeepSOIC » Mon Mar 06, 2017 3:52 pm

triplus wrote:P.S. As for the container part. Do you have any plans to upstream it? Are there any plans to change the behaviour and to preserve feature hierarchy?
Upstream meaning merge into master FreeCAD? Maybe, but only when automatic sorting of new objects into active group is implemented. What workbench should they land to? Assembly? or spread over various containers across workbenches?

As for feature hierarchy, I don't know why does it behave like it does (flattens out everything). In C++ version of Module, I didn't have that problem. I think fixing it is most likely a C++ work.
cron