Skip to content

Instantly share code, notes, and snippets.

@mario52a
Last active January 15, 2024 10:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mario52a/8b204a1d405106e3e0f497b86cab01ae to your computer and use it in GitHub Desktop.
Save mario52a/8b204a1d405106e3e0f497b86cab01ae to your computer and use it in GitHub Desktop.
This macro creates a helix around a solid object whatever its shape, the helix follows the entire surface of the object. (Python2 is request)
# -*- coding: utf-8 -*-
#from __future__ import unicode_literals
#
"""
***************************************************************************
* Copyright (c) 2019 2020 2021 2022 2023 2024 <mario52> *
* *
* This file is a supplement to the FreeCAD CAx development system. *
* *
* 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. *
** **
* Use at your own risk. The author assumes no liability for data loss. *
* It is advised to backup your data frequently. *
* If you do not trust the software do not use it. *
** **
* This software 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 macro; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************
* WARNING! All changes in this file will be lost and *
* may cause malfunction of the program *
***************************************************************************
"""
#Macro_FCSpring On Surface 20/12/2019 /_00 15/01/2024
#
#OS: Windows 10 build 19045
#Word size of FreeCAD: 64-bit
#Version: 0.22.0dev.35554 (Git)
#Build type: Release
#Branch: main
#Hash: 8e2ab9f76888ac4da971f9d5069cec7bcc2b572f
#Python 3.10.13, Qt 5.15.8, Coin 4.0.2, Vtk 9.2.6, OCC 7.6.3
#Locale: French/Mars (fr_MA)
#
__title__ = "FCSpring On Surface"
__author__ = "Mario52"
__url__ = "http://www.freecadweb.org/index-fr.html"
__Wiki__ = "http://www.freecadweb.org/wiki/index.php?title=FCSpring_On_Surface"
__version__ = "00.01"
__date__ = "2024/01/15" #YYYY/MM/DD
#original code by wandererfan
#How to intersect a line with a part
#http://www.forum.freecadweb.org/viewtopic.php?f=22&t=5456
import PySide2
from PySide2 import QtGui ,QtCore, QtWidgets
from PySide2.QtGui import *
from PySide2.QtCore import *
import time
import math
from math import sqrt, pi, sin, cos, asin
import Draft, Part, FreeCADGui, FreeCAD
from FreeCAD import Base
Gui = FreeCADGui
App = FreeCAD
global ui ; ui = ""
global lineLength ; lineLength = 0.0 # longueur de la ligne
global noPass ; noPass = 1 # switch observer
global detectFace ; detectFace = 0
global sel ; sel = ""
global objet ; objet = ""
####chrono################
import time
global depart ; depart = 0.0
global arrivee; arrivee = 0.0
def chrono(sec): # 0=depart autre=stop
#time.strftime('%X %x %Z')#'15:44:07 12/14/19 Paris, Madrid'
global depart
global arrivee
if sec == 0:
depart = time.time()#time.clock()
App.Console.PrintMessage("Chrono begin : "+str(time.strftime('%X'))+"\n")
else:
arrivee = time.time()#time.clock()
App.Console.PrintMessage("Chrono end : "+str(time.strftime('%X'))+"\n")
parcouru = ((arrivee - depart)/60.0)
App.Console.PrintError("Time execution : "+str("%.3f" % parcouru)+" min"+"\n")
# FreeCADGui.updateGui()
####chrono################
class Ui_MainWindow(object):
def __init__(self ):
self.window = MainWindow
#self.path = FreeCAD.ConfigGet("AppHomePath")
#self.path = FreeCAD.ConfigGet("UserAppData")
#self.path = "your path"
# param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
# self.path = param.GetString("MacroPath","") + "/" # macro path
# self.path = self.path.replace("\\","/")
# print("Path for the icons : " , self.path)
self.Pas = 1.0
self.Hauteur = 0.0
self.Precision = 36
self.steps = (360.0 / self.Precision)
self.longueurFil= 0.0
self.coor_X = 0.0
self.coor_Y = 0.0
self.coor_Z = 0.0
self.PointSize = 8 #heigth text
def setupUi(self, MainWindow):
self.window = MainWindow
MainWindow.setObjectName("MainWindow")
MainWindow.resize(251, 455)
# MainWindow.move(1150, 100) # position window
self.label_00_Title = QtWidgets.QLabel(MainWindow)
self.label_00_Title.setGeometry(QtCore.QRect(20, 5, 226, 16))
self.label_00_Title.setObjectName("label_00_Title")
####
self.GB_00_Configuration = QtWidgets.QGroupBox(MainWindow)
self.GB_00_Configuration.setGeometry(QtCore.QRect(15, 25, 186, 126))
self.GB_00_Configuration.setObjectName("GB_00_Configuration")
self.DS_GB_00_01_Pas = QtWidgets.QDoubleSpinBox(self.GB_00_Configuration)
self.DS_GB_00_01_Pas.setGeometry(QtCore.QRect(15, 20, 86, 22))
self.DS_GB_00_01_Pas.setObjectName("DS_GB_00_01_Pas")
self.DS_GB_00_01_Pas.setMaximum(999999)
self.DS_GB_00_01_Pas.setValue(self.Pas)
self.DS_GB_00_01_Pas.setDecimals(4)
self.DS_GB_00_01_Pas.setToolTip("The screw pitch (default = 1)")
self.DS_GB_00_01_Pas.valueChanged.connect(self.on_DS_GB_00_01_Pas)
self.Label_GB_00_01_Pas = QtWidgets.QLabel(self.GB_00_Configuration)
self.Label_GB_00_01_Pas.setGeometry(QtCore.QRect(115, 25, 66, 16))
self.Label_GB_00_01_Pas.setObjectName("Label_GB_00_01_Pas")
self.DS_GB_00_02_Hauteur = QtWidgets.QDoubleSpinBox(self.GB_00_Configuration)
self.DS_GB_00_02_Hauteur.setGeometry(QtCore.QRect(15, 55, 86, 22))
self.DS_GB_00_02_Hauteur.setObjectName("DS_GB_00_02_Hauteur")
# self.DS_GB_00_02_Hauteur.setValue()
self.DS_GB_00_02_Hauteur.setMaximum(999999)
self.DS_GB_00_02_Hauteur.setDecimals(4)
self.DS_GB_00_02_Hauteur.setToolTip("The height of the shape" + "\n"
"the default height is calculte" + "\n"
"by the max height of the BoundBox")
self.DS_GB_00_02_Hauteur.valueChanged.connect(self.on_DS_GB_00_02_Hauteur)
self.label_GB_00_02_Hauteur = QtWidgets.QLabel(self.GB_00_Configuration)
self.label_GB_00_02_Hauteur.setGeometry(QtCore.QRect(115, 60, 66, 16))
self.label_GB_00_02_Hauteur.setObjectName("label_GB_00_02_Hauteur")
self.SP_GB_00_03_Precision = QtWidgets.QSpinBox(self.GB_00_Configuration)
self.SP_GB_00_03_Precision.setGeometry(QtCore.QRect(15, 90, 86, 22))
self.SP_GB_00_03_Precision.setObjectName("DS_GB_00_03_Precision")
self.SP_GB_00_03_Precision.setValue(self.Precision)
self.SP_GB_00_03_Precision.setMaximum(360)
self.SP_GB_00_03_Precision.setMinimum(1)
self.SP_GB_00_03_Precision.setToolTip("The number of points for one turn" + "\n"
"(default = " + str(self.Precision) + ")")
self.SP_GB_00_03_Precision.valueChanged.connect(self.on_SP_GB_00_03_Precision)
self.label_GB_00_02_Precision = QtWidgets.QLabel(self.GB_00_Configuration)
self.label_GB_00_02_Precision.setGeometry(QtCore.QRect(115, 95, 66, 16))
self.label_GB_00_02_Precision.setObjectName("label_GB_00_02_Precision")
####
self.GB_01_Coordinate = QtWidgets.QGroupBox(MainWindow)
self.GB_01_Coordinate.setGeometry(QtCore.QRect(15, 160, 186, 131))
self.GB_01_Coordinate.setObjectName("GB_01_Coordinate")
self.DP_01_01_X = QtWidgets.QDoubleSpinBox(self.GB_01_Coordinate)
self.DP_01_01_X.setGeometry(QtCore.QRect(15, 25, 86, 22))
self.DP_01_01_X.setObjectName("SP_01_01_X")
self.DP_01_01_X.setMaximum(999999)
self.DP_01_01_X.setMinimum(-999999)
self.DP_01_01_X.setDecimals(4)
self.DP_01_01_X.setToolTip("The X value of the coordinate" + "\n"
"the default value is calculed" + "\n"
"by the X center BoundBox")
self.DP_01_01_X.valueChanged.connect(self.on_DP_01_01_X)
self.DP_01_02_Y = QtWidgets.QDoubleSpinBox(self.GB_01_Coordinate)
self.DP_01_02_Y.setGeometry(QtCore.QRect(15, 60, 86, 22))
self.DP_01_02_Y.setObjectName("SP_01_01_Y")
self.DP_01_02_Y.setMaximum(999999)
self.DP_01_02_Y.setMinimum(-999999)
self.DP_01_02_Y.setDecimals(4)
self.DP_01_02_Y.setToolTip("The Y value of the coordinate" + "\n"
"the default value is calculed" + "\n"
"by the Y center BoundBox")
self.DP_01_02_Y.valueChanged.connect(self.on_DP_01_02_Y)
self.DP_01_03_Z = QtWidgets.QDoubleSpinBox(self.GB_01_Coordinate)
self.DP_01_03_Z.setGeometry(QtCore.QRect(15, 95, 86, 22))
self.DP_01_03_Z.setObjectName("SP_01_01_Z")
self.DP_01_03_Z.setMaximum(999999)
self.DP_01_03_Z.setMinimum(-999999)
self.DP_01_03_Z.setDecimals(4)
self.DP_01_03_Z.setToolTip("The Z value of the coordinate" + "\n"
"the default value is calculed" + "\n"
"by the Z BoundBox minimum value")
self.DP_01_03_Z.valueChanged.connect(self.on_DP_01_03_Z)
self.Label_GB_01_01_X = QtWidgets.QLabel(self.GB_01_Coordinate)
self.Label_GB_01_01_X.setGeometry(QtCore.QRect(115, 30, 66, 13))
self.Label_GB_01_01_X.setObjectName("Label_GB_01_01_X")
self.Label_GB_01_02_Y = QtWidgets.QLabel(self.GB_01_Coordinate)
self.Label_GB_01_02_Y.setGeometry(QtCore.QRect(115, 65, 66, 13))
self.Label_GB_01_02_Y.setObjectName("Label_GB_01_02_Y")
self.Label_GB_01_03_Z = QtWidgets.QLabel(self.GB_01_Coordinate)
self.Label_GB_01_03_Z.setGeometry(QtCore.QRect(115, 100, 66, 13))
self.Label_GB_01_03_Z.setObjectName("Label_GB_01_03_Z")
####
self.GB_03_Options = QtWidgets.QGroupBox(MainWindow)
self.GB_03_Options.setGeometry(QtCore.QRect(15, 300, 186, 71))
self.GB_03_Options.setObjectName("GB_03_Options")
self.RB_03_00_BSpline = QtWidgets.QRadioButton(self.GB_03_Options)
self.RB_03_00_BSpline.setGeometry(QtCore.QRect(10, 20, 71, 18))
self.RB_03_00_BSpline.setChecked(True)
self.RB_03_00_BSpline.setToolTip("BSpline")
self.RB_03_00_BSpline.setObjectName("RB_03_00_BSpline")
self.RB_03_01_Wire = QtWidgets.QRadioButton(self.GB_03_Options)
self.RB_03_01_Wire.setGeometry(QtCore.QRect(100, 20, 71, 18))
self.RB_03_01_Wire.setToolTip("Wire")
self.RB_03_01_Wire.setObjectName("RB_03_01_Wire")
self.CB_03_00_Points = QtWidgets.QCheckBox(self.GB_03_Options)
self.CB_03_00_Points.setGeometry(QtCore.QRect(10, 45, 71, 18))
self.CB_03_00_Points.setToolTip("Create one Points in all coordinates")
self.CB_03_00_Points.setObjectName("CB_03_00_Points")
self.CB_03_01_Reverse = QtWidgets.QCheckBox(self.GB_03_Options)
self.CB_03_01_Reverse.setGeometry(QtCore.QRect(100, 45, 71, 18))
self.CB_03_01_Reverse.setToolTip("Reverse the direction" + "\n"
"Default = counter clockwise")
self.CB_03_01_Reverse.setObjectName("CB_03_01_Reverse")
self.CB_03_02_Update = QtWidgets.QCheckBox(self.GB_03_Options)
self.CB_03_02_Update.setGeometry(QtCore.QRect(170, 45, 18, 18))
self.CB_03_02_Update.setObjectName("CB_03_02_Update")
self.CB_03_02_Update.setToolTip("Display the progress of the operation in the 3D view")
####
self.GB_02_Command = QtWidgets.QGroupBox(MainWindow)
self.GB_02_Command.setGeometry(QtCore.QRect(15, 380, 186, 61))
self.GB_02_Command.setObjectName("GB_02_Command")
self.PB_02_01_Ok = QtWidgets.QPushButton(self.GB_02_Command)
self.PB_02_01_Ok.setGeometry(QtCore.QRect(100, 25, 75, 23))
self.PB_02_01_Ok.setObjectName("GB_02_01_Ok")
self.PB_02_01_Ok.setToolTip("Button Ok" + "\n"
"If on error is created" + "\n"
"the button is coloured in red" + "\n"
"if not the button is coloured in green")
self.PB_02_01_Ok.clicked.connect(self.on_PB_02_01_Ok)
self.PB_02_02_Quit = QtWidgets.QPushButton(self.GB_02_Command)
self.PB_02_02_Quit.setGeometry(QtCore.QRect(10, 25, 75, 23))
self.PB_02_02_Quit.setObjectName("GB_02_01_Quit")
self.PB_02_02_Quit.setToolTip("Quit FCSpring On Surface")
self.PB_02_02_Quit.clicked.connect(self.on_PB_Quit_clicked)
# section progressBar 1 Green
self.progressBar_1_Green = QtWidgets.QProgressBar(MainWindow)
self.progressBar_1_Green.setGeometry(QtCore.QRect(210, 30, 30, 411))
self.progressBar_1_Green.setValue(0)
self.progressBar_1_Green.setOrientation(QtCore.Qt.Vertical)
self.progressBar_1_Green.setAlignment(QtCore.Qt.AlignCenter)
self.progressBar_1_Green.setObjectName("progressBar_1_Green")
self.progressBar_1_Green.setToolTip("If the coordinate is erroneous the progressBar is coloured in red")
self.progressBar_1_Green.setStyleSheet("QProgressBar {color:black; }"
"QProgressBar:chunk {background-color: #00FF00;}") # modify the progressBar color
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
MainWindow.setWindowFlags(PySide2.QtCore.Qt.WindowStaysOnTopHint) # PySide2 cette fonction met la fenetre en avant
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(__title__+" ("+__version__+", "+__date__+")")
self.label_00_Title.setText(__title__+" ("+__version__+", "+__date__+")")
self.GB_00_Configuration.setTitle("Configuration")
self.Label_GB_00_01_Pas.setText("Pas")
self.label_GB_00_02_Hauteur.setText("Heigth")
self.label_GB_00_02_Precision.setText("Precision")
self.GB_01_Coordinate.setTitle("Coordinate Begin")
self.Label_GB_01_01_X.setText("X")
self.Label_GB_01_02_Y.setText("Y")
self.Label_GB_01_03_Z.setText("Z")
self.GB_03_Options.setTitle("Options")
self.RB_03_00_BSpline.setText("BSpline")
self.RB_03_01_Wire.setText("Wire")
self.CB_03_00_Points.setText("Points")
self.CB_03_01_Reverse.setText("Reverse")
self.GB_02_Command.setTitle("Options")
self.GB_02_Command.setTitle("Command")
self.PB_02_01_Ok.setText("Ok")
self.PB_02_02_Quit.setText("Quit")
def on_DS_GB_00_01_Pas(self, value):
self.Pas = value
self.DS_GB_00_01_Pas.setStyleSheet("QDoubleSpinBox {background-color: QPalette.Base}")
def on_DS_GB_00_02_Hauteur(self, value):
self.Hauteur = value
self.DS_GB_00_02_Hauteur.setStyleSheet("QDoubleSpinBox {background-color: QPalette.Base}")
def on_SP_GB_00_03_Precision(self, value):
self.Precision = value
self.steps = (360.0 / self.Precision)
self.SP_GB_00_03_Precision.setStyleSheet("QSpinBox {background-color: QPalette.Base}")
def on_DP_01_01_X(self, value):
self.coor_X = value
def on_DP_01_02_Y(self, value):
self.coor_Y = value
def on_DP_01_03_Z(self, value):
self.coor_Z = value
def on_PB_02_01_Ok(self):
global lineLength
global noPass
global sel
global depart
global arrivee
global detectFace
global objet
try:
if (self.Pas != 0) and (self.Hauteur != 0) and (self.Precision != 0) and (detectFace == 1):
chrono(0)
noPass = 0 # switch 0=nopass
#sel = FreeCADGui.Selection.getSelection()
objetName = sel[0].Name
objetLabel = sel[0].Label
objet = sel[0].Shape
z = 0.0
compteur = 0
lineDirectrice = Draft.makeWire([FreeCAD.Vector(0.0, 0.0, 0.0),FreeCAD.Vector(lineLength , 0.0, 0.0)])
#print(lineDirectrice.Name)
if self.CB_03_02_Update.isChecked():
FreeCADGui.ActiveDocument.getObject(lineDirectrice.Name).Visibility = True
else:
FreeCADGui.ActiveDocument.getObject(lineDirectrice.Name).Visibility = False
App.ActiveDocument.recompute()
pl=FreeCAD.Placement()
points = []
self.progressBar_1_Green.setValue(0)
progressMax = (self.Precision * int(self.Hauteur / self.Pas) + 1)
self.progressBar_1_Green.setMaximum(progressMax)
for sp in range(int(self.Hauteur / self.Pas) + 1): #nombre de tours
for i in range(0, (360*1000), int(self.steps*1000)): #
if self.CB_03_01_Reverse.isChecked():
i = -float(i/1000) ##Reverse
else:
i = float(i/1000) ##Normal
compteur += 1
pl=App.Placement(App.Vector(self.coor_X, self.coor_Y, z + self.coor_Z), App.Rotation(i,0.0,0.0), App.Vector(0,0,0))
lineDirectrice.Placement = pl
z += (self.Pas / self.Precision)
if z > self.Hauteur:
break
line = lineDirectrice.Shape
intersection = objet.common(line) # only for solid object not for face
try:
coorIntersec = intersection.Vertexes[1].Point
points += [FreeCAD.Vector(coorIntersec[0],coorIntersec[1],coorIntersec[2])]
if self.CB_03_00_Points.isChecked():
Draft.makePoint(coorIntersec[0],coorIntersec[1],coorIntersec[2])
except Exception:
self.progressBar_1_Green.setStyleSheet("QProgressBar {color:black; }"
"QProgressBar:chunk {background-color: #FF0000;}") # modify the progressBar color
self.progressBar_1_Green.setValue(progressMax)
####progressBar
self.progressBar_1_Green.setStyleSheet("QProgressBar {color:black; }"
"QProgressBar:chunk {background-color: green;}") # modify the progressBar color
self.progressBar_1_Green.setValue(compteur)
####progressBar
if self.CB_03_02_Update.isChecked():
Gui.updateGui()
App.ActiveDocument.recompute()
try:
App.ActiveDocument.removeObject(lineDirectrice.Name)
except Exception:
None
if len(points) != 0:
##Bspline
if self.RB_03_00_BSpline.isChecked():
BSpline = Draft.makeBSpline(points,closed=False)
#BSpline.Label = objetLabel + "_BSpline"
App.ActiveDocument.ActiveObject.Label = objetLabel + "_BSpline"
#self.longueurFil =
##Wire
if self.RB_03_01_Wire.isChecked():
Wire = Draft.makeWire(points,closed=False)
#Wire.Label = objetLabel + "_Wire"
App.ActiveDocument.ActiveObject.Label = objetLabel + "_Wire"
#self.longueurFil =
self.PB_02_01_Ok.setStyleSheet("QPushButton {background-color: green;\n"
"border:2px solid rgb( 0, 115,0);}")
else:
self.PB_02_01_Ok.setText("K-O")
self.PB_02_01_Ok.setStyleSheet("QPushButton {background-color: red;\n"
"border:2px solid rgb(115, 0, 0);}")
else:
self.PB_02_01_Ok.setStyleSheet("QPushButton {background-color: red;\n"
"border:2px solid rgb(115, 0, 0);}")
if (self.Pas == 0):
self.DS_GB_00_01_Pas.setStyleSheet("QDoubleSpinBox {border:2px solid rgb(115, 0, 0);}")
if (self.Hauteur == 0):
self.DS_GB_00_02_Hauteur.setStyleSheet("QDoubleSpinBox {border:2px solid rgb(115, 0, 0);}")
if (self.Precision == 0):
self.SP_GB_00_03_Precision.setStyleSheet("QSpinBox {border:2px solid rgb(115, 0, 0);}")
FreeCAD.Console.PrintMessage("Pas : " + str(self.Pas) + "\n")
FreeCAD.Console.PrintMessage("Hauteur : " + str(self.Hauteur) + "\n")
FreeCAD.Console.PrintMessage("Precision : " + str(self.Precision) + "\n")
FreeCAD.Console.PrintMessage("Coordinate : " + str(len(points)) + "\n")
#FreeCAD.Console.PrintMessage("Length : " + str(self.longueurFil) + "\n")
FreeCAD.Console.PrintMessage("coor_X : " + str(self.coor_X) + "\n")
FreeCAD.Console.PrintMessage("coor_Y : " + str(self.coor_Y) + "\n")
FreeCAD.Console.PrintMessage("coor_Z : " + str(self.coor_Z) + "\n")
chrono(1)
FreeCAD.Console.PrintMessage("______________________" + "\n")
points = []
except Exception:
self.PB_02_01_Ok.setStyleSheet("QSpinBox {background-color: red;\n"
"border:2px solid rgb(115, 0, 0);}")
App.ActiveDocument.recompute()
noPass = 1 # switch 1 = pass
####################################################################
def on_PB_Quit_clicked(self):
FreeCADGui.Selection.removeObserver(s) # Uninstalls resident function (desactivated for read after LeftDock RightDock)
self.window.hide() # hide the window and close the macro
FreeCAD.Console.PrintMessage("Quit " + __title__ + "\n\n")
##############################################################################
class SelObserver:
def addSelection(self,document, object, element, position): # Selection
global ui
global lineLength
global noPass
global sel
global detectFace
global objet
sel = ""
ui.progressBar_1_Green.setValue(0)
ui.PB_02_01_Ok.setStyleSheet("QPushButton {background-color: QPalette.Base}") # origin system
ui.PB_02_01_Ok.setText("Ok")
ui.DS_GB_00_01_Pas.setStyleSheet("QDoubleSpinBox {background-color: QPalette.Base}")
ui.DS_GB_00_02_Hauteur.setStyleSheet("QDoubleSpinBox {background-color: QPalette.Base}")
ui.SP_GB_00_03_Precision.setStyleSheet("QSpinBox {background-color: QPalette.Base}")
ui.Label_GB_01_01_X.setText("X")
ui.Label_GB_01_02_Y.setText("Y")
ui.Label_GB_01_03_Z.setText("Z")
detectFace = 0
if (noPass == 1):
try:
selEx = FreeCADGui.Selection.getSelectionEx()
if (noPass == 1) and (hasattr(selEx[0].SubObjects[0],"Surface")):
detectFace = 1
ui.DP_01_01_X.setValue(0.0)
ui.DP_01_02_Y.setValue(0.0)
ui.DP_01_03_Z.setValue(0.0)
sel = FreeCADGui.Selection.getSelection()
boundBoxLZ = sel[0].Shape.BoundBox.ZLength # Length z boundBox rectangle
####
boundBoxLL = sel[0].Shape.BoundBox.DiagonalLength # Length Diagonal rectangle
####
boundBoxZMin = sel[0].Shape.BoundBox.ZMin # coordonate ZMin
ui.Label_GB_01_03_Z.setText("Z ("+str(round(boundBoxZMin,4))+")")
####
boundBoxCenter = sel[0].Shape.BoundBox.Center # boundBox Center
####
ui.Label_GB_01_01_X.setText("X BBCenter")
ui.Label_GB_01_02_Y.setText("Y BBCenter")
ui.Label_GB_01_03_Z.setText("Z Lowermost")
ui.DP_01_01_X.setValue(boundBoxCenter[0]) # BBcenter X
ui.DP_01_02_Y.setValue(boundBoxCenter[1]) # BBcenter Y
ui.DP_01_03_Z.setValue(boundBoxZMin) # point le plus bas
self.Hauteur = boundBoxLZ
ui.DS_GB_00_02_Hauteur.setValue(self.Hauteur)
lineLength = boundBoxLL
except Exception:
None
##############################################################################
s=SelObserver()
FreeCADGui.Selection.addObserver(s) # install the function resident mode
MainWindow = QtWidgets.QWidget() #PySide2
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
@mario52a
Copy link
Author

This macro utility is intended for the use of the program FreeCAD http://www.freecadweb.org/
The icon for your toolbar, it is to place in your macros directory (all in the same location of the macro)

The wiki page https://www.freecadweb.org/wiki/Macro_FCSpring_On_Surface

FCSpring_On_Surface The icon for the toolbar Rename in FCSpring_On_Surface.png

@Anthony-Gaudino
Copy link

Hi @mario52a, I believe this macro is broken on FreeCAD 0.21.1

If I create a cylinder, select it's face and run this macro the OK button turns red and nothing happens.

@mario52a
Copy link
Author

mario52a commented Jan 13, 2024

Hi @Anthony-Gaudino

thanks for report i try with (below) and i do not have problem

try first create the cylinder and after:

  1. run the macro
  2. select the cylinder
  3. choice one option
  4. click the Ok button
  5. normally enjoy

(or if the macro is already active , click mouse in the 3Dview (for deselect all) and select the cylinder the height of the cylinder is displayed and click the Ok button)

Word size of FreeCAD: 64-bit
Version: 0.20.2.29177 +426 (Git)
Build type: Release
Branch: (HEAD detached from 0.20.2)
Hash: 930dd9a76203a3260b1e6256c70c1c3cad8c5cb8
Python 3.8.10, Qt 5.15.2, Coin 4.0.1, Vtk 8.2.0, OCC 7.6.3

OS: Windows 10 build 19045
Word size of FreeCAD: 64-bit
Version: 0.21.1.33668 +26 (Git)
Build type: Release
Branch: (HEAD detached at 0.21.1)
Hash: f6708547a9bb3f71a4aaade12109f511a72c207c
Python 3.8.10, Qt 5.15.2, Coin 4.0.1, Vtk 8.2.0, OCC 7.6.3

OS: Windows 10 build 19045
Word size of FreeCAD: 64-bit
Version: 0.22.0dev.35554 (Git)
Build type: Release
Branch: main
Hash: 8e2ab9f76888ac4da971f9d5069cec7bcc2b572f
Python 3.10.13, Qt 5.15.8, Coin 4.0.2, Vtk 9.2.6, OCC 7.6.3


PS: this text is diplayed in the report view ... not problem for the macro this is one advertisement with (with new Qt) for the styleSheet

11:27:12 Could not parse stylesheet of object QDoubleSpinBox(0x26307e068f0, name = "DS_GB_00_02_Hauteur")


thanks for report

mario

@Anthony-Gaudino
Copy link

@mario52a

Thank you!
I was able to use it following your steps. My mistake was selecting the face before running the macro.

@mario52a
Copy link
Author

Hi

@Anthony-Gaudino Ok good news

PS: i correct the styleSheet you will no longer see the warning:

11:27:12 Could not parse stylesheet of object QDoubleSpinBox(0x26307e068f0, name = "DS_GB_00_02_Hauteur")

thank for appreciate my little macro and your report

mario

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment