Stretch in 3D

Show off your FreeCAD projects here!
User avatar
johnwang
Posts: 578
Joined: Sun Jan 27, 2019 12:41 am

Re: Stretch in 3D

Postby johnwang » Sun Nov 01, 2020 11:10 am

result


s3d3.jpg
s3d3.jpg (5.07 KiB) Viewed 599 times
s3dm.jpg
s3dm.jpg (11.29 KiB) Viewed 599 times
Last edited by johnwang on Mon Nov 02, 2020 11:54 am, edited 1 time in total.
hfc series CAE workbenches for FreeCAD (hfcNastran95, hfcMystran, hfcFrame3DD, hfcSU2 and more)
chrisb
Posts: 30620
Joined: Tue Mar 17, 2015 9:14 am

Re: Stretch in 3D

Postby chrisb » Sun Nov 01, 2020 12:28 pm

Will your version be available in the AddonManager?
You need at least FreeCAD 0.19.23300 to edit my current sketches.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
User avatar
johnwang
Posts: 578
Joined: Sun Jan 27, 2019 12:41 am

Re: Stretch in 3D

Postby johnwang » Mon Nov 02, 2020 4:54 am

chrisb wrote:
Sun Nov 01, 2020 12:28 pm
Will your version be available in the AddonManager?
I seldom use AddonManager.

The file still has some problems.

From here https://github.com/yorikvanhavre/BIM_Workbench/pull/38
It seems

Code: Select all

import DraftTrackers
should change to

Code: Select all

from draftguitools import gui_trackers
This is used to animation the stretch process.
hfc series CAE workbenches for FreeCAD (hfcNastran95, hfcMystran, hfcFrame3DD, hfcSU2 and more)
xbit
Posts: 131
Joined: Mon Sep 21, 2020 10:48 am

Re: Stretch in 3D

Postby xbit » Mon Nov 09, 2020 12:28 am

Hello johnwang.

I am trying to execute your scirpt, in order to move face, along with the supporting fillets.

I have some questions regarding the program.
These are:
1. You said
At the end i added

Code: Select all

showup()
.
In the last commands, they are indented. So is the showup() command indented as well, or is it outside the identation?

2. You said to save the file as .py file, and run it from the python console of FreeCAD. Could you please tell me how can i execute a script from inside the FreeCAD python console?

3. Finally, you mention that
It seems that

Code: Select all

import DraftTrackers
should change to

Code: Select all

from draftguitools import gui_trackers
So , based on your experiments, should this change be done or not?

------

It would be best if you pasted the python script here directly, so we would just get it without bothering you with these questions.
Thank you very much!
xbit
Posts: 131
Joined: Mon Sep 21, 2020 10:48 am

Re: Stretch in 3D

Postby xbit » Mon Nov 09, 2020 11:59 am

I get this error when trying to run this script:

Code: Select all

ModuleNotFoundError: No module named 'DraftTrackers'
@watsug How did you manage to run this?
xbit
Posts: 131
Joined: Mon Sep 21, 2020 10:48 am

Re: Stretch in 3D

Postby xbit » Mon Nov 09, 2020 12:03 pm

I managed to run this by changing

Code: Select all

import DraftTrackers
to

Code: Select all

import draftguitools.gui_trackers as DraftTrackers
I get no error, but nothing happens when i run this though..
What did you guys did differently?
User avatar
johnwang
Posts: 578
Joined: Sun Jan 27, 2019 12:41 am

Re: Stretch in 3D

Postby johnwang » Mon Nov 09, 2020 9:31 pm

run py file in python console is talked here:

https://forum.freecadweb.org/viewtopic. ... 7&start=10
hfc series CAE workbenches for FreeCAD (hfcNastran95, hfcMystran, hfcFrame3DD, hfcSU2 and more)
User avatar
johnwang
Posts: 578
Joined: Sun Jan 27, 2019 12:41 am

Re: Stretch in 3D

Postby johnwang » Mon Nov 09, 2020 9:35 pm

the result is the same as your "Moving a clone and joining (original + clone)"
hfc series CAE workbenches for FreeCAD (hfcNastran95, hfcMystran, hfcFrame3DD, hfcSU2 and more)
User avatar
watsug
Posts: 72
Joined: Sat Sep 26, 2020 10:51 pm

Re: Stretch in 3D

Postby watsug » Mon Nov 09, 2020 11:48 pm

xbit wrote:
Mon Nov 09, 2020 11:59 am
@watsug How did you manage to run this?
I made the changes that were in this thread, some errors were related to utf8 and qt5. To import the tool, you can put the "stretcher_u8.py" file in your bin folder and then "import stretcher_u8", or something like this with another filepath.

Code: Select all

import types
import importlib.machinery
loader = importlib.machinery.SourceFileLoader('stretch', '/home/watsug/Documents/freeCAD/stretch_u8.py')
mod = types.ModuleType(loader.name)
loader.exec_module(mod)
To run the tool in freecad, run the showup() function with mod.showup().

This is my modified code, I can start the tool but get an error when trying to select object.

Code: Select all

# -*- coding: utf-8 -*-
#####################################
#    3D                           
#    2015/10/05 11:35   
#          hahaha~
#####################################
import FreeCADGui, Part
import FreeCAD
import DraftVecUtils
#import DraftTrackers
from draftguitools import gui_trackers
from PySide import QtCore, QtGui
from PySide.QtCore import QObject
from pivy.coin import *
from pivy import coin
import Draft
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_reobsel(object):
    def __init__(self):
        global LCD_CM,LCD_NM
        LCD_CM = []
        LCD_NM = []
        self.setupUi()
        self.view = FreeCADGui.ActiveDocument.ActiveView
        self.stack = []
        self.point = None
        self.p = None
        self.CLG = None
        self.presc = -1
        self.getobj()     
        self.aline()       
        self.c = self.view.addEventCallback("SoEvent",self.action)
    def action(self,info):
        global LCD_CM,LCD_NM,SSCM,movt,ONMIDOBJ,MD
        if self.stack: lastpoint = self.stack[-1]
        else: lastpoint = None
        self.point = FreeCADGui.Snapper.snap(info["Position"],lastpoint,info["ShiftDown"],info["ShiftDown"],True)  #snap
        #~ FreeCAD.Console.PrintMessage('\nself.point:'+str(self.point)) 
        if info["Type"] == "SoKeyboardEvent": 
            if info["Key"] == 'ESCAPE':  #  ESC
                self.reob()
        elif info["Type"] == "SoLocation2Event" : #    move
            if len(self.stack) == 1:
                p1 = [self.stack[-1][0],self.stack[-1][1],self.stack[-1][2]]
                p2 = [self.point[0],self.point[1],self.point[2]]
                diagonal = self.point.sub(self.stack[-1])
                p3 = self.stack[-1].add(DraftVecUtils.project(diagonal,FreeCAD.DraftWorkingPlane.v))
                p4 = self.stack[-1].add(DraftVecUtils.project(diagonal,FreeCAD.DraftWorkingPlane.u))
                p3 = [p3[0],p3[1],p3[2]]
                p4 = [p4[0],p4[1],p4[2]]
                pt = [p1,p3,p2,p4]
                self.coords1.point.setValues(pt)
                self.lines1.coordIndex.setValues(0,5,[0,1,2,3,0])
            if len(self.stack) == 3: 
                #~ prf('SSCM',SSCM)
                #~ for i in SSCM:
                    #~ FreeCADGui.ActiveDocument.getObject(i.Name).Visibility = False
                self.coords2.point.setValues([[self.stack[-1][0],self.stack[-1][1],self.stack[-1][2]],[self.point[0],self.point[1],self.point[2]]])
                self.lines2.coordIndex.setValues(0,2,[0,1])
                MD = self.point.sub(self.stack[-1])
                self.p.move(MD)
                self.DCL1.setText(str(round(MD[0],4)))
                self.DCL2.setText(str(round(MD[1],4)))
                self.DCL3.setText(str(round(MD[2],4)))
                self.DCL12.setText(str(round(MD.Length,4)))
                self.DCL12.setFocus()
                self.DCL12.selectAll()
        elif info["Type"] == "SoMouseButtonEvent":#   click
            if info["State"] == 'DOWN' and info["Button"] == "BUTTON1":#DOWN
                self.stack.append(self.point) 
                if len(self.stack) == 1: #point1
                    FreeCAD.Console.PrintMessage("\nplease pick 1 point!")
                elif len(self.stack) == 2: #point2
                    self.label9.setText(QtGui.QApplication.translate("Form", "pls pick 2 point ", None))
                    self.sg1.removeChild(self.no1) #remove
                    p1 = self.stack[0] # point1
                    p2 = self.stack[1] # point2
                    diagonal = self.stack[1].sub(self.stack[0])
                    p3 = self.stack[0].add(DraftVecUtils.project(diagonal,FreeCAD.DraftWorkingPlane.v))
                    p4 = self.stack[0].add(DraftVecUtils.project(diagonal,FreeCAD.DraftWorkingPlane.u))
                    FreeCAD.ActiveDocument.openTransaction("3D Stretch-cut") # undo
                    LCD_CM,LCD_NM = cutobj(p1,p3,p2,p4) # cut
                    FreeCAD.ActiveDocument.commitTransaction() # undo
                    self.presc = 0 # esc
                    SSCM = []
                    prf("LCD_CM",LCD_CM)
                    for i in LCD_CM:
                        for ii in i:
                            SSCM.append(ii)
                    prf('SSCM',SSCM)
                    for i in ONMIDOBJ:
                        SSCM.append(i)
                    # self.p=DraftTrackers.ghostTracker(SSCM) # trackers  give my obj
                    self.p=gui_trackers.ghostTracker(SSCM) # trackers  give my obj
                    self.p.on() # trackers   on !
                elif len(self.stack) == 4:
                    self.sg2.removeChild(self.no2) # close  line
                    self.precs = 1
                    movt = self.stack[-1].sub(self.stack[-2]) # move_distance
                    self.CKDS()
    def accept(self): # accept
        self.CKDS()
    def reject(self):  # cancel
        self.reob()
    def reob(self):#close
        global LCD_NM,LCD_CM,FACELIST
        self.sg1.removeChild(self.no1)
        self.sg2.removeChild(self.no2)
        if self.p: self.p.off() # close tracker
        FreeCADGui.Snapper.off()  #close snap
        FreeCAD.Console.PrintMessage("\nStretch  quit...!")
        self.view.removeEventCallback("SoEvent",self.c)  #close Observer
        prf('close self.c')
        FreeCADGui.Control.closeDialog()
        prf(self.presc)
        if self.presc == 0:
            prf('press ESC ... visibility => True')
            try:
                for ii in FACELIST:
                    prf('ii',ii)
                    FreeCADGui.ActiveDocument.getObject(ii[0].Name).Visibility = True
                    prf(ii[0].Name)
                prf("LCD_CM",LCD_CM[0][0].Name)
                prf("LCD_NM",LCD_NM[0][0].Name)
                for i in LCD_CM:
                    for ii in i:
                        FreeCAD.ActiveDocument.removeObject(ii.Name)
                for i in LCD_NM:
                    for ii in i:
                      FreeCAD.ActiveDocument.removeObject(ii.Name)
                prf("del ok..!")
            except:
                prf("DELERROR")
        close()
    def getobj(self):# sel 
        self.sg1 = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
        ma = coin.SoBaseColor()
        ma.rgb = (1,0,0)
        self.coords1 = coin.SoCoordinate3()
        self.lines1 = coin.SoIndexedLineSet()
        self.no1 = coin.SoSeparator()
        self.no1.addChild(self.coords1)
        self.no1.addChild(ma)
        self.no1.addChild(self.lines1)
        self.sg1.addChild(self.no1)
    def aline(self):# a line 
        self.sg2 = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
        ma = coin.SoBaseColor()
        ma.rgb = (0,0,1)
        self.coords2 = coin.SoCoordinate3()
        self.lines2 = coin.SoIndexedLineSet()
        self.no2 = coin.SoSeparator()
        self.no2.addChild(self.coords2)
        self.no2.addChild(ma)
        self.no2.addChild(self.lines2)
        self.sg2.addChild(self.no2)
    def setupUi(self):
        widget1 = QtGui.QWidget()
        #widget1.setWindowTitle(QtGui.QApplication.translate("Form", "3D Stretch", None,QtGui.QApplication.UnicodeUTF8))
        widget1.setWindowTitle(QtGui.QApplication.translate("Form", "3D Stretch", None))
        self.layout = QtGui.QGridLayout(widget1)
        self.layout.setSpacing(5)
        self.layout.setColumnMinimumWidth(0,10)

        self.form = [widget1]
        self.getK = QtGui.QPushButton(widget1)
        self.getK.setObjectName(_fromUtf8("getK"))
        self.layout.addWidget(self.getK,1,0)

        self.form = [widget1]
        self.OK = QtGui.QPushButton(widget1)
        self.OK.setObjectName(_fromUtf8("OK"))
        self.layout.addWidget(self.OK,6,1)

        self.label1 = QtGui.QLabel(widget1)
        self.label1.setObjectName(_fromUtf8("label1"))
        self.layout.addWidget(self.label1,2,0)

        self.DCL1 = QtGui.QLineEdit(widget1)
        self.DCL1.setObjectName(_fromUtf8("DCL1"))
        self.layout.addWidget(self.DCL1,2,1)

        self.label2 = QtGui.QLabel(widget1)
        self.label2.setObjectName(_fromUtf8("label2"))
        self.layout.addWidget(self.label2,3,0)

        self.label = QtGui.QLabel(widget1)
        self.label.setObjectName(_fromUtf8("label"))
        self.layout.addWidget(self.label,5,0)

        self.DCL12 = QtGui.QLineEdit(widget1)
        self.DCL12.setObjectName(_fromUtf8("DCL12"))
        self.layout.addWidget(self.DCL12,5,1)
        
        self.DCL2 = QtGui.QLineEdit(widget1)
        self.DCL2.setObjectName(_fromUtf8("DCL2"))
        self.layout.addWidget(self.DCL2,3,1)

        self.label3 = QtGui.QLabel(widget1)
        self.label3.setObjectName(_fromUtf8("label3"))
        self.layout.addWidget(self.label3,4,0)

        self.label4 = QtGui.QLabel(widget1)
        self.label4.setObjectName(_fromUtf8("label4"))
        self.layout.addWidget(self.label4,6,0)

        self.label5 = QtGui.QLabel(widget1)
        self.label5.setObjectName(_fromUtf8("label5"))
        self.layout.addWidget(self.label5,8,0)

        self.label9 = QtGui.QLabel(widget1)
        self.label9.setObjectName(_fromUtf8("label9"))
        self.layout.addWidget(self.label9,9,0)


        self.DCL3 = QtGui.QLineEdit(widget1)
        self.DCL3.setObjectName(_fromUtf8("DCL3"))
        self.layout.addWidget(self.DCL3,4,1)

        QtCore.QObject.connect(self.OK, QtCore.SIGNAL("clicked()"), self.CKDS)
        QtCore.QObject.connect(self.getK, QtCore.SIGNAL("clicked()"), self.getKK)

        QtCore.QObject.connect(self.DCL12, QtCore.SIGNAL(_fromUtf8("editingFinished()")), self.norgetpos)

        self.DCL1.setText("0.00")
        self.DCL2.setText("0.00")
        self.DCL3.setText("0.00")
        self.DCL12.setText("0")
        self.DCL1.setEnabled(False)
        self.DCL2.setEnabled(False)
        self.DCL3.setEnabled(False)

        self.label.setText(QtGui.QApplication.translate("Form", "Distance:", None))
        self.label1.setText(QtGui.QApplication.translate("Form", "X Distance:", None))
        self.label2.setText(QtGui.QApplication.translate("Form", "Y Distance:", None))
        self.label3.setText(QtGui.QApplication.translate("Form", "Z Distance:", None))
        self.label9.setText(QtGui.QApplication.translate("Form", "pls sel obj", None))
        self.OK.setText(QtGui.QApplication.translate("reobsel", "move", None))
        self.getK.setText(QtGui.QApplication.translate("reobsel", "restart", None))
    def CKDS(self):
        global LCD_CM,LCD_NM,SSCM,ONMIDOBJ
        if LCD_CM == LCD_NM == []: return(errorDialog("please selection obj first!"))
        prf("GOGOGO")
        x=float(self.DCL1.text())
        y=float(self.DCL2.text())
        z=float(self.DCL3.text())
        mov = FreeCAD.Vector(x,y,z)
        FreeCAD.ActiveDocument.openTransaction("3D Stretch-move") # undo
        prf('ONMIDOBJ',ONMIDOBJ)
        for i in ONMIDOBJ:# move!
            Draft.move(i,mov,copy=False)
        ssobj(LCD_CM,LCD_NM,mov) # stretch!
        FreeCAD.ActiveDocument.commitTransaction() # undo
        self.reob()
    def getKK(self): # close and open
            self.reob()
            showup()
    def norgetpos(self):
        global MD
        
        d=float(self.DCL12.text())
        cd = MD.normalize()*d
        prf('cd',cd)
        self.DCL1.setText(str(round(float(cd[0]),4)))
        self.DCL2.setText(str(round(float(cd[1]),4)))
        self.DCL3.setText(str(round(float(cd[2]),4)))
        
def isBoxIntersection(s1,s2):
    b1=s1.BoundBox
    b2=s2.BoundBox
    if b1.intersect(b2):
        prf("isBoxIntersection True!!!!!!")
        return(True)
    elif b2.closestPoint(b1.Center).sub(b1.closestPoint(b2.Center)).Length < 0.0005:
        prf("isBoxIntersection True!!!!!!")
        return(True)
    else:
        prf("isBoxIntersection False")
        return(False)


def cutobj(a1=[],a2=[],a3=[],a4=[]): # give 4 vec ... make a ..Shell ... cut obj ... return 2 list...
    global name,lcolor,pcolor,scolor,mygroup,commonFace,FACELIST,DELII,ONMIDOBJ
    DELII = []
    prf('p1 = FreeCAD.Vector('+str(a1[0])+','+str(a1[1])+','+str(a1[2])+')')
    prf('p2 = FreeCAD.Vector('+str(a2[0])+','+str(a2[1])+','+str(a2[2])+')')
    prf('p3 = FreeCAD.Vector('+str(a3[0])+','+str(a3[1])+','+str(a3[2])+')')
    prf('p4 = FreeCAD.Vector('+str(a4[0])+','+str(a4[1])+','+str(a4[2])+')')
    if a1==a2==a3==a4==[]:
        a1=FreeCAD.Vector(10,0,0)
        a2=FreeCAD.Vector(-10,20,0)
        a3=FreeCAD.Vector(10,30,0)
        a4=FreeCAD.Vector(30,0,0)
    shape=Part.Face(Part.makePolygon([a1,a2,a3,a4], True)) # shape
    nor = shape.normalAt(0,0) # nor
    dd = 200 # nor**
    v1po = a1+nor*dd
    v2po = a2+nor*dd
    v3po = a3+nor*dd
    v4po = a4+nor*dd
    v1ne = a1-nor*dd
    v2ne = a2-nor*dd
    v3ne = a3-nor*dd
    v4ne = a4-nor*dd
    shape1=Part.Face(Part.makePolygon([v1po,v2po,v3po,v4po], True))
    shape2=Part.Face(Part.makePolygon([v1ne,v2ne,v3ne,v4ne], True))
    shape3=Part.Face(Part.makePolygon([v1po,v2po,v2ne,v1ne], True))
    shape4=Part.Face(Part.makePolygon([v2po,v3po,v3ne,v2ne], True))
    shape5=Part.Face(Part.makePolygon([v3po,v4po,v4ne,v3ne], True))
    shape6=Part.Face(Part.makePolygon([v1po,v4po,v4ne,v1ne], True))
    shape_list = [shape1,shape2,shape3,shape4,shape5,shape6]
    shell_shape=Part.Shell([shape1,shape5,shape3,shape4,shape6,shape2])
    BOXSHAPE = Part.makeSolid(shell_shape)
    shellPt = Part.Vertex(shell_shape.CenterOfMass)
    shape_sum = 0
    cutobj = None
    commonFace = None
    mygroup = []
    FACELIST = []
    ONMIDOBJ = []
    NUM=1
    NUM1=len(FreeCAD.ActiveDocument.Objects)
    bar_showup()
    for i in FreeCAD.ActiveDocument.Objects: # all obj
        QQ=0
        setvalue(NUM*100/NUM1)
        NUM+=1
        if QQ == 0:
            if FreeCADGui.ActiveDocument.getObject(i.Name).Visibility == True:
                try: 
                    for j in shape_list:
                        FreeCAD.Console.PrintMessage('\ni:'+str(i.Name)+'   j:'+str(j)+'  =>  '+str(len(i.Shape.common(j).Faces)))
                        if len(i.Shape.common(j).Faces) >= 1:
                            commonFace = i.Shape.common(j).Faces # Face 
                            cutobj = i
                            objbaseshape = j
                            shape_sum += 1
                            prf('objName',cutobj.Name)
                            TRA = FreeCADGui.ActiveDocument.getObject(cutobj.Name).Transparency   # get Transparency
                            scolar=FreeCADGui.ActiveDocument.getObject(cutobj.Name).ShapeColor  # get shape color
                            lcolar=FreeCADGui.ActiveDocument.getObject(cutobj.Name).LineColor  # get line color
                            pcolar=FreeCADGui.ActiveDocument.getObject(cutobj.Name).PointColor  # get point locor
                            try:
                                C_GRP = cutobj.GROUP
                                C_ID = cutobj.ID
                            except:
                                C_GRP = []
                                C_ID = []
                                prf("NO~~~group  id")
                            if cutobj.InList > 0:  # get group
                                groupname = cutobj.InList[0].Name
                                mygroup = FreeCAD.ActiveDocument.getObject(groupname)
                            name = cutobj.Label # get name
                            prf("Transparency",TRA)
                            prf('scolar',scolar)
                            prf('lcolar',lcolar)
                            prf('pcolar',pcolar)
                            prf('mygroup',mygroup)
                            prf('name',name)# cut)obj  Base_face  common_face  Transparency shape.. point line shape group group id
                            FACELIST.append([i,j,commonFace,TRA,scolar,lcolar,pcolar,mygroup,name,C_GRP,C_ID]) 
                    try: # find obj in mid
                        if i.Shape.common(BOXSHAPE).Area == i.Shape.Area: #in mid
                            ONMIDOBJ.append(i)
                            prf('Area SAME')
                        else:
                            prf('Area NOT SAME . . . !  ')
                    except:
                        prf('MID FIND ERROR...')
                except: prf('\nNo Shape.')
    if shape_sum == 0:
        return(errorDialog("GET NO OBJECTS!"))
    #find GROUP
    ###
    C_CM=[]
    C_NM=[]
    CMOBJLIST = []
    NMOBJLIST = []
    NUM=1
    NUM1=len(FACELIST)
    bar_showup()
    for i in FACELIST: # cut)obj  Base_face  common_face
        setvalue(NUM*100/NUM1)
        NUM+=1
        #   i[0] = cutobj
        #   i[1] = objbaseshape
        #   i[2] = commonFace
        objbase = mkObj(i[1])
        objnor = commonFace[0].normalAt(0,0) # obj nor 
        #Extrude..
        EXT = FreeCAD.ActiveDocument.addObject("Part::Extrusion","Extrude")
        EXT.Base = objbase
        EXT.Dir = objnor*0.0001*-1
        EXT.Solid = (True)
        FreeCAD.ActiveDocument.recompute()
        #CUT
        mycut = FreeCAD.ActiveDocument.addObject("Part::Cut","Cut")
        mycut.Base = i[0]
        mycut.Tool = EXT
        FreeCAD.ActiveDocument.recompute()
        DOW = Draft.downgrade([mycut],delete=True)
        prf('DOW',DOW   ) # cut obj
        FreeCAD.ActiveDocument.recompute()
        T_CM=[]
        T_NM=[]
        for ii in DOW[0]:
            prf('common der Face:',len(BOXSHAPE.common(ii.Shape).Solids))
            if len(BOXSHAPE.common(ii.Shape).Solids) ==1:
                T_CM.append(ii) # MOVE
                prf("MOVE")
            else:
                T_NM.append(ii)# NO MOVE
                prf("NO MOVE")
        C_CM.append(T_CM)
        C_NM.append(T_NM)
        for ii in DOW[0]:
            FreeCADGui.ActiveDocument.getObject(ii.Name).Transparency = i[3]   # give Transparency
            FreeCADGui.ActiveDocument.getObject(ii.Name).ShapeColor = i[4]    # give shape color
            FreeCADGui.ActiveDocument.getObject(ii.Name).LineColor = i[5]      # give line color
            FreeCADGui.ActiveDocument.getObject(ii.Name).PointColor = i[6]     # give point locor
        prf('del objbase',objbase.Name)
        FreeCAD.ActiveDocument.removeObject(objbase.Name)
        #~ prf("i[0].Name",i[0].Name)
        DELII.append(i[0].Name) # find the objs will stretch
        prf("EXT.Name",EXT.Name)
        FreeCAD.ActiveDocument.removeObject(EXT.Name) # remove 
        prf("C_CM",C_CM)
        prf("C_NM",C_NM)
    close()
    return(C_CM,C_NM)

def ssobj(CO_CM,CO_NM,MOV):
    global name,lcolor,pcolor,scolor,mygroup,commonFace,FACELIST,DELII
    prf("FACELIST",FACELIST)
    num=0
    DELLIST=[]
    KED = 0
    LENN = MOV.Length
    LEN = MOV.Length+0.0015
    objnor = MOV.normalize() # obj nor 
    MMOV = objnor*LENN
    bar_showup()
    NUM=1
    NUM1=len(FACELIST)
    for ii in FACELIST: # N  [  [obj,obj,[face,face,face],tra,pc,lc,sc,group,name,grp,id] , [...] , [...] , [...]  ]
        setvalue(NUM*100/NUM1)
        NUM+=1
        CLOUD9=[] # obj need to Fuse
        TPA=[]
        for i in ii[2]:# commonface 
            TPA.append(mkObj(i))
            AEXT = FreeCAD.ActiveDocument.addObject("Part::Extrusion","Extrude") # Face __ Extrude
            AEXT.Base = TPA[-1]
            AEXT.Dir = objnor*(LEN)
            AEXT.Solid = (True)
            FreeCAD.ActiveDocument.recompute()
            for j in CO_NM[num]: # Judge cut or fuse
                if AEXT.Shape.common(j.Shape).Area > 0.1:
                    KED = 1
            FreeCAD.ActiveDocument.recompute()
            CLOUD9.append(AEXT)
            Draft.move(AEXT,objnor*-0.0005,copy=False)#stretch obj avoid ..0.0005..
            FreeCAD.ActiveDocument.recompute()
        # CM obj move ..
        Draft.move(CO_CM[num],MMOV,copy=False)
        prf('MOV',MOV)
        if KED == 1:    #  cut
            prf("cut")
            if len(CLOUD9) > 1:
                MuCut = FreeCAD.ActiveDocument.addObject("Part::MultiFuse","myEXXXX")
                MuCut.Shapes = CLOUD9
                FreeCAD.ActiveDocument.recompute()
            else:
                MuCut = CLOUD9[0]
                MuCut.Label = 'myEXXXX'
            DELLIST.append(MuCut.Name)
            if len(CO_NM[num]) > 1: # CUT BASE
                SECut = FreeCAD.ActiveDocument.addObject("Part::MultiFuse","CUTBAS")
                SECut.Shapes = CO_NM[num]
                FreeCAD.ActiveDocument.recompute()
            else:
                SECut = CO_NM[num][0]
                SECut.Label = 'CUTBASE'
            DELLIST.append(SECut.Name)
            C9Cut = FreeCAD.ActiveDocument.addObject("Part::Cut","Cut") #cut!
            C9Cut.Base = SECut
            C9Cut.Tool = MuCut
            DELLIST.append(C9Cut.Name)
            Draft.move(C9Cut,objnor*-0.0012,copy=False)
            FreeCAD.ActiveDocument.recompute()
            COO = [] # fuse_obj
            COO.append(C9Cut)
            for k in CO_CM[num]:
                COO.append(k)
            Mu = FreeCAD.ActiveDocument.addObject("Part::MultiFuse","Fusion")
            Mu.Shapes = COO
            FreeCAD.ActiveDocument.recompute()
            #~ if ii [9] <> []:
                #~ from GsCad.c1_std import addpro
                #~ Mui = addpro.addpro(Mui,ii[8],ii[9],ii[10],'    ',[[0,0,0]],ii[5],ii[6],ii[4])[0]
            #~ else:
            Mui = mkObj(Mu.Shape)
            Mui.Label = ii[8]    #name
            if ii[7]: mygroup.addObject(Mui)  #grp
            FreeCADGui.ActiveDocument.getObject(Mui.Name).Transparency = ii[3]   # Transparency
            FreeCADGui.ActiveDocument.getObject(Mui.Name).ShapeColor = ii[4]  # shape
            FreeCADGui.ActiveDocument.getObject(Mui.Name).LineColor = ii[5]      # line
            FreeCADGui.ActiveDocument.getObject(Mui.Name).PointColor = ii[6]   # point
            
            DELLIST.append(Mu.Name) # fuse_obj
            for iii in CO_NM[num]:
                CLOUD9.append(iii)
            for iii in CO_CM[num]:
                CLOUD9.append(iii)
            for ww in CLOUD9:
                DELLIST.append(ww.Name)
            for ww in TPA:
                DELLIST.append(ww.Name) # face
            num+=1
        else:    #  stretch
            prf("stretch")
            for i in CO_NM[num]:
                CLOUD9.append(i)
            for i in CO_CM[num]:
                CLOUD9.append(i)
            Mu = FreeCAD.ActiveDocument.addObject("Part::MultiFuse","Fusion")
            Mu.Shapes = CLOUD9
            FreeCAD.ActiveDocument.recompute()
            Mui = mkObj(Mu.Shape)
            #~ if ii [9] <> []:
                #~ from GsCad.c1_std import addpro
                #~ Mui = addpro.addpro(Mui,ii[8],ii[9],ii[10],'    ',[[0,0,0]],ii[5],ii[6],ii[4])[0]
            #~ else:
            Mui.Label = ii[8]  #name
            if ii[7]: mygroup.addObject(Mui)  # grp
            FreeCADGui.ActiveDocument.getObject(Mui.Name).Transparency = ii[3]   # Transparency
            FreeCADGui.ActiveDocument.getObject(Mui.Name).ShapeColor = ii[4]  # shape
            FreeCADGui.ActiveDocument.getObject(Mui.Name).LineColor = ii[5]      # line
            FreeCADGui.ActiveDocument.getObject(Mui.Name).PointColor = ii[6]   # point

            DELLIST.append(Mu.Name) # fuse obj
            for ww in TPA:
                DELLIST.append(ww.Name) # face
            for ww in CLOUD9:
                DELLIST.append(ww.Name) # face obj_A obj_B
            num+=1
    close()
    prf("DELLIST",DELLIST)
    for i in DELLIST:
        try:
            FreeCAD.ActiveDocument.removeObject(i)
        except:
            prf("DEL repeat!")
    prf("DELII",DELII)
    for i in DELII:
        try: FreeCAD.ActiveDocument.removeObject(i)
        except: prf("DELII no",i)
def showup():
    global reobsel
    reobsel = Ui_reobsel()
    FreeCADGui.Control.showDialog(reobsel)

def isPtOnEdge(pt,edge) : # find is point on edge
    v = Part.Vertex(pt)
    d = v.distToShape(edge)
    if d:
        if d[0] < 0.01:
            return True
    return False

def mkObj(shape):  # make obj
    obj = FreeCAD.ActiveDocument.addObject("Part::Feature",'Temp')
    obj.Shape = shape
    FreeCAD.ActiveDocument.recompute()
    return(obj)

def errorDialog(msg): # message
    unicode_str =  unicode(msg,'utf-8')
    diag = QtGui.QMessageBox(QtGui.QMessageBox.Warning, 'Error MessageBox', unicode_str)
    diag.setWindowModality(QtCore.Qt.ApplicationModal)
    diag.exec_()

def prf(m,p=0):
    if p==0: FreeCAD.Console.PrintMessage('\n'+str(m))
    else: FreeCAD.Console.PrintMessage('\n'+str(m)+':'+str(p))


class Ui_Bar():
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(240, 138)
        self.centralWidget = QtGui.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.progressBar = QtGui.QProgressBar(self.centralWidget)
        self.progressBar.setGeometry(QtCore.QRect(10, 40, 211, 23))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.label = QtGui.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(30, 10, 267, 17))
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralWidget)
        self.menuBar = QtGui.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 240, 25))
        self.menuBar.setObjectName("menuBar")
        MainWindow.setMenuBar(self.menuBar)
        self.mainToolBar = QtGui.QToolBar(MainWindow)
        self.mainToolBar.setObjectName("mainToolBar")
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
        self.statusBar = QtGui.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        MainWindow.setStatusBar(self.statusBar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        screen=QtGui.QDesktopWidget().screenGeometry()
        size=MainWindow.geometry()
        MainWindow.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "A progress bar", None))
        self.label.setText(QtGui.QApplication.translate("MainWindow", "please wait...", None))

def close():
    bbbarui.close()

def setvalue(v):
    Barui.progressBar.setProperty("value", v)



bbbarui = QtGui.QMainWindow()
Barui = Ui_Bar()
def  bar_showup():
    Barui.setupUi(bbbarui)
    bbbarui.show()



I get this error

Code: Select all

00:44:41  <class 'AttributeError'>
00:44:41  Traceback (most recent call last):
00:44:41    File "/home/watsug/Documents/freeCAD/stretch_u8.py", line 50, in action
00:44:41      self.point = FreeCADGui.Snapper.snap(info["Position"],lastpoint,info["ShiftDown"],info["ShiftDown"],True)  #snap
00:44:41  AttributeError: module 'FreeCADGui' has no attribute 'Snapper'
FreeCAD info

Code: Select all

OS: Ubuntu 20.04.1 LTS (ubuntu:GNOME/ubuntu)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.22882 (Git)
Build type: Unknown
Branch: master
Hash: aebf568eaec7f62b95b29037851c04d1a6f65d47
Python version: 3.8.5
Qt version: 5.12.8
Coin version: 4.0.0
OCC version: 7.3.0
Locale: English/United States (en_US)
xbit
Posts: 131
Joined: Mon Sep 21, 2020 10:48 am

Re: Stretch in 3D

Postby xbit » Tue Nov 10, 2020 9:41 am

Thanks a lot johnwang and watsug!

Now we should figure out why this doesn't work. Johnwang, do you know why watsug's approach fails?
Could it be you share your own code/workflow?

Thanks a lot again!