Union of all elements of a group

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
churchill
Posts: 8
Joined: Wed Feb 28, 2018 12:27 pm

Union of all elements of a group

Post by churchill »

Hello,

Sorry for my English, I speak French (French version of this post here).

To test scripting, and for a future project, I wrote a little script to draw a ruler in cm for laser engraving..

Code: Select all

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide import QtGui
import Draft
import FreeCAD


def get_infos():
    info = {"cm_mini":0, "cm_maxi":0, "direction":1}
    r = QtGui.QInputDialog.getInt(None, u"Ruler","cm Mini (ex. -2)", -1)
    if r[1]:
        info["cm_mini"] = r[0]
    else:
        # Cancel
        return (False, {})
    r = QtGui.QInputDialog.getInt(None, u"Ruler","cm Maxi (ex. 10)", 1)
    if r[1]:
        info["cm_maxi"] = r[0]
    else:
        # Cancel
        return (False, {})

    r = QtGui.QMessageBox.question(None, u"Ruler", u"Inverted ruler ?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
    if r == QtGui.QMessageBox.Yes:
        info["direction"] = -1
    
    # OK
    return (True, info)

def trace_lines(parent, info):
    group = parent.newObject("App::DocumentObjectGroup","lines")
    direction = info["direction"]
    
    def line_mm(mm, lg):
        # Draw line
        points=[FreeCAD.Vector(0.0,direction*mm,0.0),FreeCAD.Vector(lg,direction*mm,0.0)]
        line = Draft.makeWire(points,closed=False,face=True,support=None)
        group.addObject(line)
    
    for cm in xrange(info["cm_mini"], info["cm_maxi"]):
        for mm in xrange(0,10):
            if mm==0:
                line_mm(cm*10, 10)   # line of cm = 10mm
            elif mm==5:
                line_mm(cm*10+mm, 7) # line if 1/2 cm = 7mm
            else:
                line_mm(cm*10+mm, 5) # line of mm = 5mm
    # Last cm line
    line_mm((cm+1)*10, 10)

def trace_text(parent, info):
    font = "/usr/share/fonts/truetype/ocr-a/OCRA.ttf"
    group = parent.newObject("App::DocumentObjectGroup","texts")
    direction = info["direction"]
    
    def text_cm(cm):
        text = Draft.makeShapeString("%d" % cm, font, 2.0,0)
        plm=FreeCAD.Placement()
        plm.Base=FreeCAD.Vector(12.0,direction*cm*10-1.5,0.0)
        text.Placement=plm
        group.addObject(text)
    
    for cm in xrange(info["cm_mini"], info["cm_maxi"]+1):
        text_cm(cm)

def init():
    info = get_infos()
    if info[0]:
        group_name = "regle_%d_%d" % (info[1]["cm_mini"], info[1]["cm_maxi"])
        v = Draft.makeVisGroup(name=group_name)
        trace_lines(v, info[1])
        trace_text(v, info[1])
        App.ActiveDocument.recompute()

if __name__=="__main__":
    init()
I created a "VisGroup" to be able to change lines colors for all objects at once (used to separate cutting and engraving shapes). In this VisGroup I created 2 groups, one with vectors, and the other with the text. But may be is not the right way to do it.

I would like to make an union of all objects of a group, to finally have only 2 objetcs (lines+numbers) easier to move.... but I don't know how to do that...

Any idea ?

PS: If you would like to execute this script, be carreful to font path in "trace_text". Running this script take longtime (why ?)

Code: Select all

OS: Ubuntu 18.04.1 LTS
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.17.13541 (Git)
Build type: None
Branch: releases/FreeCAD-0-17
Hash: 9948ee4f1570df9216862a79705afb367b2c6ffb
Python version: 2.7.15rc1
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: French/Switzerland (fr_CH)
[*]
User avatar
Chris_G
Veteran
Posts: 2596
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Union of all elements of a group

Post by Chris_G »

churchill wrote: Fri Oct 19, 2018 2:44 pm I would like to make an union of all objects of a group, to finally have only 2 objetcs (lines+numbers) easier to move.... but I don't know how to do that...

Any idea ?
You can easily make a Compound of shapes.
In the code below, I added a extract_shape() function to extract shapes from objects (recursive on groups)

Code: Select all

import FreeCAD
import FreeCADGui
import Part
vec = FreeCAD.Vector


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide import QtGui
import Draft
import FreeCAD


def get_infos():
    info = {"cm_mini":0, "cm_maxi":0, "direction":1}
    r = QtGui.QInputDialog.getInt(None, u"Ruler","cm Mini (ex. -2)", -1)
    if r[1]:
        info["cm_mini"] = r[0]
    else:
        # Cancel
        return (False, {})
    r = QtGui.QInputDialog.getInt(None, u"Ruler","cm Maxi (ex. 10)", 1)
    if r[1]:
        info["cm_maxi"] = r[0]
    else:
        # Cancel
        return (False, {})

    r = QtGui.QMessageBox.question(None, u"Ruler", u"Inverted ruler ?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
    if r == QtGui.QMessageBox.Yes:
        info["direction"] = -1
    
    # OK
    return (True, info)

def trace_lines(parent, info):
    group = parent.newObject("App::DocumentObjectGroup","lines")
    direction = info["direction"]
    
    def line_mm(mm, lg):
        # Draw line
        points=[FreeCAD.Vector(0.0,direction*mm,0.0),FreeCAD.Vector(lg,direction*mm,0.0)]
        line = Draft.makeWire(points,closed=False,face=True,support=None)
        group.addObject(line)
    
    for cm in range(info["cm_mini"], info["cm_maxi"]):
        for mm in range(0,10):
            if mm==0:
                line_mm(cm*10, 10)   # line of cm = 10mm
            elif mm==5:
                line_mm(cm*10+mm, 7) # line if 1/2 cm = 7mm
            else:
                line_mm(cm*10+mm, 5) # line of mm = 5mm
    # Last cm line
    line_mm((cm+1)*10, 10)

def trace_text(parent, info):
    font = "/usr/share/fonts/truetype/ubuntu/Ubuntu-C.ttf"
    group = parent.newObject("App::DocumentObjectGroup","texts")
    direction = info["direction"]
    
    def text_cm(cm):
        text = Draft.makeShapeString("%d" % cm, font, 2.0,0)
        plm=FreeCAD.Placement()
        plm.Base=FreeCAD.Vector(12.0,direction*cm*10-1.5,0.0)
        text.Placement=plm
        group.addObject(text)
    
    for cm in range(info["cm_mini"], info["cm_maxi"]+1):
        text_cm(cm)

def extract_shape(obj):
    if "Group" in obj.PropertiesList:
        shape_list = list()
        for o in obj.Group:
            shape_list.append(extract_shape(o))
        return(Part.Compound(shape_list))
    elif "Shape" in obj.PropertiesList:
        return(obj.Shape)

def init():
    info = get_infos()
    if info[0]:
        group_name = "regle_%d_%d" % (info[1]["cm_mini"], info[1]["cm_maxi"])
        v = Draft.makeVisGroup(name=group_name)
        trace_lines(v, info[1])
        trace_text(v, info[1])
        App.ActiveDocument.recompute()
        for subgroup in v.Group:
            Part.show(extract_shape(subgroup))

if __name__=="__main__":
    init()
Post Reply