Macro Rotate To Point: Difference between revisions

From FreeCAD Documentation
m (ver 00.05.2)
(Marked this version for translation)
 
(43 intermediate revisions by 5 users not shown)
Line 1: Line 1:
<languages/>
<languages/>
<translate>
<translate>

<!--T:1-->
<!--T:1-->
{{Macro
{{Macro
|Name=Macro Rotate To Point
|Name=Macro Rotate To Point
|Icon=Macro_Rotate_To_Point.svg
|Icon=Macro_Rotate_To_Point.svg
|Description={{ColoredText|#ff0000|#ffffff|New version GUI modifyed for the HD dpi (QGridLayout) run only FC version 0.18 and more (PySide2 Qt5)}} <br/> <br/> Macro for rotate on object on itself with the axis of rotation the boundbox center, center of mass, direction of wire or last point clicked.<br/><br/>For the precedent version see [https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/9231d5b1d218357305cc0404e46bf6c107509a0e/Macro%2520Rotate%2520To%2520Point.FCMacro Macro_Rotate_To_Point] and install it manually. Macro_Rotate_To_Point] and install it manually.
|Description=Macro to rotate an object on itself with the axis of rotation the: boundbox center, center of mass, direction of wire, or last point clicked. You must save in a file all coordinate worked and save it in a file "Coordinate [(0.06,1.30,0.0),(85.0,0.0,0.0)]," or in a complete macro with different options (Create serial image) for create one animation, increase/decrease, pause, yoyo ....
|Author=Mario52
|Author=Mario52
|Version=00.05.2
|Version=00.11
|Date=2020/03/07
|Date=2022/10/17
|FCVersion=0.18 and more
|FCVersion=0.19 and more
|Download=[https://www.freecadweb.org/wiki/images/d/d1/Macro_Rotate_To_Point.svg ToolBar Icon]
|Download=[https://www.freecadweb.org/wiki/images/d/d1/Macro_Rotate_To_Point.svg ToolBar Icon]
}}
}}
Line 16: Line 17:


<!--T:3-->
<!--T:3-->
Macro for rotate on object on itself with the axis of rotation the boundbox center, center of mass, direction of wire or last point clicked
Macro to rotate an object on itself with the axis of rotation the: boundbox center, center of mass, direction, path of wire, or last point clicked. You must save in a file all coordinate worked and save it in a file "Coordinate [(0.06,1.30,0.0),(85.0,0.0,0.0)]," </br>or in a complete macro with different options (Create serial image) for create one animation, increase/decrease, pause, yoyo ....


==How To Use== <!--T:4-->

<!--T:5-->
Run the macro and select one object and choice:


</translate>
</translate>
{{Codeextralink|https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/d9419d4bb13e36940eb2f56c3c469ea4182827ee/Macro%2520Rotate%2520To%2520Point.FCMacro}}
[[File:Macro Rotate To Point 00.png|Interface Rotate to point ]]
{{clear}}
<translate>
<translate>


<!--T:6-->
==Usage== <!--T:4-->

*Point Rotation
<!--T:5-->
**Bounbox Center : Select the boundBox center to axis rotation
# Download the macro from the [[Std_AddonMgr|Addon Manager]]
**Center of Mass : Select the Center of Mass to axis rotation
# Execute the macro
**Point Clicked : Select the last point mouse to axis rotation 1: select the object 2: use the {{KEY|CTRL}} for choice point extra object
# Select one object
*Axis Rotation
# Choose one of the following orientations:
**Rotation(Z) Yaw : Yaw axis

**Rotation(Y) Pitch : Pitch axis
**Rotation(X) Roll : Roll axis
*Coordinates Point clicked
**DoubleSpinBox : Coordinate X on click mouse (modifiable only with the mode "Point Clicked")
**DoubleSpinBox : Coordinate Y on click mouse (modifiable only with the mode "Point Clicked")
**DoubleSpinBox : Coordinate Z on click mouse (modifiable only with the mode "Point Clicked")
*Position : If this checkBox is checked the rotation is disabled, the object placement is done on the axis seleted
*Point : If this checkBox is checked one point is created for visualise the point rotation axis : red X, green Y, blue Z
*Line Edit : The line edit display the original coordinate to axis selected + the input data give in the spinBox
*Free : If this checkBox is checked the {{KEY|Apply}} is switched ans the rotation or translation is executed in real time
*DoubleSpinBox : enter the modification
*{{KEY|Apply}} : Apply the modification to the object
*{{KEY|Quit}} : Quit the macro
*{{KEY|Original}} : After modify the data of the object you can return to the original placement, If you have not deselected the current object
*{{KEY| 0,0,0 }} : This option place the object in base coordinate 0, 0, 0
*{{KEY|Reset}} : Reset the data in the macro and deselect the current object (same click mouse in the 3DView)
</translate>
</translate>
[[File:Macro_Rotate_To_Point_00.png|Interface Rotate to point]]
<translate>
<translate>
==Script== <!--T:7-->
</translate>


===[1] Position Rotation=== <!--T:42-->
ToolBar Icon PNG [[File:Macro Rotate To Point.png]] SVG [[Image:Macro_Rotate_To_Point.svg]]


<!--T:43-->
'''Macro_Rotate_To_Point.FCMacro'''
''First operation''


<!--T:44-->
{{Code|code=
[[File:Macro_Rotate_To_Point_Position-Rotation00.png| [1] Position Rotation]]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
"""
***************************************************************************
* Copyright (c) 2017 2018 2019 2020 <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 *
***************************************************************************
"""
#
#
#OS: Windows 10 (10.0)
#Word size of OS: 64-bit
#Word size of FreeCAD: 64-bit
#Version: 0.19.19697 (Git)
#Build type: Release
#Branch: master
#Hash: 8832356802011bf5d70e9d6f0efa89c47bc70a91
#Python version: 3.6.8
#Qt version: 5.12.1
#Coin version: 4.0.0a
#OCC version: 7.3.0
#
#
__title__ = "Macro_Rotate_To_Point"
__author__ = "Mario52"
__url__ = "http://www.freecadweb.org/index-fr.html"
__Wiki__ = "https://www.freecadweb.org/wiki/Macro_Rotate_To_Point"
__version__ = "00.05.2"
__date__ = "2020/03/07" #YYYY/MM/DD
#


<!--T:45-->
#### Test FreeCAD.Version above 0.17 BEGIN ##########################################################################################################
*{{CheckBox|Translation}}: If this checkBox is {{CheckBox|TRUE|checked}} the rotation is disabled, the object placement is done on the axis selected.
import WebGui
#WebGui.openBrowser("http://www.freecadweb.org/")
try:
import PySide
from PySide import QtGui
import sys, os
def errorDialog(msg):
diag = QtGui.QMessageBox(QtGui.QMessageBox.Critical,u"Error FreeCAD Version",msg )
diag.setWindowFlags(PySide.QtCore.Qt.WindowStaysOnTopHint) # PySide #cette fonction met la fenetre en avant
diag.setStyleSheet("QLabel {color : #ffffff; background-color : #FF3300; font: bold}")
FreeCAD.Console.PrintMessage("If you have not redirect to the FreeCAD Web page (with header):" + "\n\n")
FreeCAD.Console.PrintError("* Copyright (c) 2017 2018 2019 <mario52> *" + "\n\n")
FreeCAD.Console.PrintMessage("Copy and paste this link in your Browser:" + "\n\n")
FreeCAD.Console.PrintMessage("https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/9231d5b1d218357305cc0404e46bf6c107509a0e/Macro%2520Rotate%2520To%2520Point.FCMacro" + "\n\n")
#WebGui.openBrowser("https://www.freecadweb.org/wiki/How_to_install_macros")
WebGui.openBrowser("https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/9231d5b1d218357305cc0404e46bf6c107509a0e/Macro%2520Rotate%2520To%2520Point.FCMacro" + "\n\n")
diag.exec_()
diag.setStyleSheet("Base")
Gui.runCommand('Std_DlgMacroExecute',0)
quit("None")
if int(FreeCAD.Version()[1]) < 18: # Version de FreeCAD
memo = PySide.QtGui.QClipboard()
memo.setText(__title__)
errorDialog("This version " + __title__ + " rmu work with the FreeCAD 0.18 or higher. " + "\n"
"PySide2 Qt version: 5" + "\n\n"
"This title name " + __title__ + " is copied in memory" + "\n"
"Quit this window, the macro editor is open automatically." + "\n\n"
"Click the Create button and paste the title name memorized in the dialog window." + "\n\n"
"Copy the code of the page in your FreeCAD browser open and paste it in the macro page." + "\n\n"
"or see the page:" + "\n\n"
"[https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/9231d5b1d218357305cc0404e46bf6c107509a0e/Macro%2520Rotate%2520To%2520Point.FCMacro]" + "\n")
except Exception:
None
#### Test FreeCAD.Version above 0.17 END ############################################################################################################


<!--T:46-->
import PySide2
''The SpinBox {{SpinBox|1,00000 Degrees}} is reinitialized to {{incode|0.0}} and coloured in red''
from PySide2 import (QtWidgets, QtCore, QtGui)
from PySide2.QtWidgets import (QWidget, QApplication, QSlider, QGraphicsView, QGraphicsScene, QVBoxLayout, QStyle)
from PySide2.QtGui import (QPainter, QColor, QIcon)
from PySide2.QtSvg import *


<!--T:47-->
import Draft, Part, PartGui, FreeCADGui, FreeCAD
*The time passed with your favourite macro is displayed.
from FreeCAD import Base
import DraftVecUtils
import time


===[2] Translation Rotation=== <!--T:48-->
Gui = FreeCADGui
App = FreeCAD


<!--T:49-->
global ui ; ui = ""
''Second operation''
global sourisPass ; sourisPass = 0
global positionMouse ; positionMouse = ""


<!--T:50-->
global originalObject; originalObject = ""
[[File:Macro_Rotate_To_Point_Translation-Rotation00.png|[2]Translation Rotation]]
global myObject ; myObject = ""
global originalPlacement; originalPlacement = ""
global valeur ; valeur = 0.0


===Point Rotation=== <!--T:6-->
global axisX ; axisX = 0.0
global axisY ; axisY = 0.0
global axisZ ; axisZ = 0.0


<!--T:21-->
global posX ; posX = 0.0
*Boundbox Center: Select the BoundBox center to axis rotation
global posY ; posY = 0.0
*Center of Mass: Select the Center of Mass to axis rotation
global posZ ; posZ = 0.0
*Point Clicked: Select the last mouse click as the point for axis rotation
** 1: select the object
** 2: use the {{KEY|CTRL}} key to choose an extra object


===Axis Rotation=== <!--T:22-->
global rotAngleX ; rotAngleX = 0.0
global rotAngleY ; rotAngleY = 0.0
global rotAngleZ ; rotAngleZ = 0.0


<!--T:23-->
try:
*Rotation(Z) Yaw: Yaw axis
_fromUtf8 = QtCore.QString.fromUtf8
*Rotation(Y) Pitch: Pitch axis
except AttributeError:
*Rotation(X) Roll: Roll axis
def _fromUtf8(s):
*Rotation(D) Direction: Rotate around line, wire selected
return s
*Follow the path: Follow the path created by the wire, line, edge.
**1: Select the object
class Ui_MainWindow(object):
**2: Select the path
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.vueActive = FreeCADGui.ActiveDocument.ActiveView
self.click = self.vueActive.addEventCallback("SoMouseButtonEvent",self.souris)


<!--T:51-->
def souris(self,info):
''The SpinBox {{SpinBox|1,00000 Degrees}} is reinitialized to {{incode|0.0}} and coloured in red''
global sourisPass
if (info["Button"] == "BUTTON1") and (info["State"] == "DOWN"):
time.sleep(0.02)
sourisPass = 0
#print("ok")


===Coordinates Point clicked=== <!--T:24-->
def setupUi(self, MainWindow):
self.window = MainWindow
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(360, 300)
# MainWindow.setMinimumSize(QtCore.QSize(330, 10))
# MainWindow.setMaximumSize(QtCore.QSize(330, 330))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))


<!--T:25-->
####
[[File:Macro_Rotate_To_Point_Coordinate-On-Point-Clicked_00.png|Rotate To Point Coordinate-On-Point-Clicked]]
self.groupBox_Rotation = QtWidgets.QGroupBox(self.centralwidget)
*DoubleSpinBox: Coordinate X on mouse click (modifiable only with the mode "Point Clicked")
self.groupBox_Rotation.setEnabled(False)
*DoubleSpinBox: Coordinate Y on mouse click (modifiable only with the mode "Point Clicked")
*DoubleSpinBox: Coordinate Z on mouse click (modifiable only with the mode "Point Clicked")


===[3] Work (Box : Cube)=== <!--T:26-->
self.RB_Bond_Box_Center = QtWidgets.QRadioButton()
self.RB_Bond_Box_Center.setChecked(True)
self.RB_Bond_Box_Center.clicked.connect(self.on_RB_CenterRot)


<!--T:52-->
self.RB_Center_Mass = QtWidgets.QRadioButton()
''Third operation''
self.RB_Center_Mass.clicked.connect(self.on_RB_CenterRot)


<!--T:55-->
self.RB_Point_Clicked = QtWidgets.QRadioButton()
[[File:Macro Rotate To Point Work 00.png|Macro Rotate To Point Work]]
self.RB_Point_Clicked.clicked.connect(self.on_RB_CenterRot)


<!--T:27-->
####
*{{CheckBox|View}}: If checked, the view return on latest view of the object selected (work with comboBox below it) and all parameters restored.
*{{Button|Point}}: One point is created for visualise the point rotation axis: red X, green Y, blue Z.
*{{Button|Center}}: One point is created on center of circle.
*{{ComboBox|Box}}: List of all objects used. The choice of the object here, the zoom ''(if checkBox view is checked)'' is returned and all parameters restored.
*{{ComboBox|0}}: Select one predefined value.
*{{ComboBox|1.0}}: Select the saved value used.
*{{Button|- Invert}}: Invert the sign Positif/Negatif of the value displayed.
*{{SpinBox|1,00000 Degrees}}: Select the value.
*{{KEY|Apply}}: Apply the modification to the object.
*Line Edit: The line edit displays the original coordinate to axis selected + the input data given in the spinBox.
*The coordinate is displayed


===Data to save=== <!--T:28-->
self.groupBox_Axis = QtWidgets.QGroupBox()
self.groupBox_Axis.setEnabled(False)


<!--T:56-->
self.RB_Rotation_0 = QtWidgets.QRadioButton()
[[File:Macro Rotate To Point Data-To-Save 00.png|Rotate To Point Data-To-Save]]
self.RB_Rotation_0.setVisible(False)
# self.RB_Rotation_0.clicked.connect(self.on_RB_Rotation_0)


<!--T:29-->
self.RB_Rotation_X = QtWidgets.QRadioButton()
*Window for display the coordinates stored.
self.RB_Rotation_X.setChecked(True)
*{{Button|Clear}}: Delete and clean the text editor.
self.RB_Rotation_X.clicked.connect(self.on_RB_Rotation_X)
*{{Button|Delete}}: Delete the selected line in the window.
*{{CheckBox|Memo on Click}}: If it is checked, the placement is automatically stored in the window with the "Apply" button.
*{{Button|Memorize}}: Store and display the coordinate in the window, the number of coordinate stored is displayed on this button.
*{{Button|Save}}: Save the data in file
*{{CheckBox|Macro}}:
**Mode normal {{CheckBox|Macro}} the coordinate is saved in this mode : {{incode|["Body004001",(0.0,0.0,-1.5),(0.0,0.0,0.0)],}}
**Mode macro {{CheckBox|TRUE|0,0 Coordinate}} the coordinate is saved (one object or many objects worked)</br> in a complete macro directly in your macros directory with the same name of the document with extension .FCMacro
*** '''Options of the macro'''
***'''__pompe____engrenage__''' : Name of document
***'''__22 Coordinates__''' : number of coordinates
***'''Type Key Q to Quit''' : Quit the macro
***'''Type Key A to Create serial image''' : for create serial usage to create Animate GIF (with Gimp or other)
***'''Type Key D to Decrease speed''' : Decrease the speed of the animation
***'''Type Key I to Increase speed''' : Increase the speed of the animation
***'''Type Key P to Pause/Continue or key RETURN or ESCAPE''' : Pause / Anime
***'''Type Key S to Step by Step (key RETURN or ESCAPE to continue)''' : Step by Step
***'''Type Key V to reVerse''' : reVerse the video
***'''Type Key Y to YoYo''' : begin to end reverse end to begin
***'''Type Key M for this message''' : Display this Memo
***For use this options click mouse in the 3D view and type the key desidered
***____________________________
**Mode normal {{CheckBox|Memo on Click}} : The data is not saved on window, you must push the {{Button|Memo (2)}} button for save the coordinate
**Mode Memo on Click {{CheckBox|TRUE|Memo on Demand}} : The data is automaticly saved with all click op the {{Button|Apply}} button
*{{Button|Copy}}: Memorize the content of the window in a Rotate_To_Point format : {{incode|["Body004001",(0.0,0.0,-1.5),(0.0,0.0,0.0)],}}


===Command=== <!--T:30-->
self.RB_Rotation_Y = QtWidgets.QRadioButton()
self.RB_Rotation_Y.clicked.connect(self.on_RB_Rotation_Y)


<!--T:57-->
self.RB_Rotation_Z = QtWidgets.QRadioButton()
[[File:Macro Rotate To Point Command 00.png|Rotate To Point Command]]
self.RB_Rotation_Z.clicked.connect(self.on_RB_Rotation_Z)


<!--T:31-->
self.RB_Direction_D = QtWidgets.QRadioButton()
*{{KEY|Quit}}: Quit the macro
self.RB_Direction_D.clicked.connect(self.on_RB_Direction_D)
*{{KEY|Original}}: After modifying the data of the object you can return to the original placement, If you have not deselected the current object.
####
*{{KEY| 0,0,0 }}: This option places the object in base coordinate {{incode|0, 0, 0}}.
*{{KEY|Reset}}: Reset the data in the macro and deselect the current object.


<!--T:53-->
self.groupBox_Pos_Mouse = QtWidgets.QGroupBox()
ToolBar PNG Icon [[File:Macro_Rotate_To_Point.png]] and ToolBar SVG Icon [[Image:Macro_Rotate_To_Point.svg]]
self.groupBox_Pos_Mouse.setEnabled(False)


==Example== <!--T:9-->
self.DS_Pos_Mouse_X = QtWidgets.QDoubleSpinBox()
self.DS_Pos_Mouse_X.setDecimals(6)
self.DS_Pos_Mouse_X.setSuffix(" X")
self.DS_Pos_Mouse_X.valueChanged.connect(self.on_DS_Pos_Mouse_X)


</translate>
self.DS_Pos_Mouse_Y = QtWidgets.QDoubleSpinBox()
[[File:Macro Rotate To Point 01.gif]]
self.DS_Pos_Mouse_Y.setDecimals(6)
<translate>
self.DS_Pos_Mouse_Y.setSuffix(" Y")
self.DS_Pos_Mouse_Y.valueChanged.connect(self.on_DS_Pos_Mouse_Y)


==Links== <!--T:41-->
self.DS_Pos_Mouse_Z = QtWidgets.QDoubleSpinBox()
self.DS_Pos_Mouse_Z.setDecimals(6)
self.DS_Pos_Mouse_Z.setSuffix(" Z")
self.DS_Pos_Mouse_Z.valueChanged.connect(self.on_DS_Pos_Mouse_Z)


<!--T:10-->
####
The forum [http://forum.freecadweb.org/viewtopic.php?f=8&t=20925 feature req: placement - rotate part around its midpoint]


<!--T:11-->
self.SC_Slider_Bar = QtWidgets.QSlider()
My macro on Gist [https://gist.github.com/mario52a mario52a]
self.SC_Slider_Bar.setMinimum(-360.0)
self.SC_Slider_Bar.setMaximum(360.0)
self.SC_Slider_Bar.setValue(0.0)
self.SC_Slider_Bar.setSliderPosition(0)
self.SC_Slider_Bar.setOrientation(QtCore.Qt.Horizontal)
self.SC_Slider_Bar.valueChanged.connect(self.on_SC_Slider_Bar)


==Version== <!--T:12-->
self.LE_Increment = QtWidgets.QLineEdit()
self.LE_Increment.setReadOnly(True)
self.LE_Increment.setText(str(0.0))
#self.LE_Increment.returnPressed.connect(self.on_LE_Increment_Pressed)
self.LE_Increment.textChanged.connect(self.on_LE_Increment_Pressed)


<!--T:54-->
self.DS_Scroll_Bar = QtWidgets.QDoubleSpinBox()
2022/10/17 Version=00.11 : new organization GUI, Follow the path, View on object, Button Copy, adding menu Image on macro saved, add "QtWidgets.QScrollArea()"
self.DS_Scroll_Bar.setMinimum(-360.0)
self.DS_Scroll_Bar.setMaximum(360.0)
self.DS_Scroll_Bar.setDecimals(4)
self.DS_Scroll_Bar.valueChanged.connect(self.on_DS_Scroll_Bar)


<!--T:38-->
self.PB_Apply = QtWidgets.QPushButton()
2021/03/08 Version=00.10 : adding zoom on object clicked, memory value, imposted values
self.PB_Apply.clicked.connect(self.on_PB_Apply_clicked)


<!--T:37-->
self.CB_Position = QtWidgets.QCheckBox()
2021/02/25 Version=00.09 : correct the macro : cause multi object possible
self.CB_Position.setEnabled(False)
self.CB_Position.clicked.connect(self.on_CB_Position)


</translate>
# self.CB_Point = QtWidgets.QCheckBox()
{{Code|
# self.CB_Point.setEnabled(False)
App.ActiveDocument.getObject(p[0]).Placement
# self.CB_Point.clicked.connect(self.on_CB_Point)
}}
self.PB_Point = QtWidgets.QPushButton()
<translate>
self.PB_Point.setEnabled(False)
<!--T:58-->
self.PB_Point.clicked.connect(self.on_CB_Point)
instead
</translate>
{{Code|
myObject.Placement
}}
<translate>


<!--T:36-->
self.CB_Free = QtWidgets.QCheckBox()
2021/02/22 Version=00.08c : correct the center facePoint (19h26 Paris)
self.CB_Free.setEnabled(False)
# self.CB_Free.clicked.connect(self.on_CB_Free)


<!--T:35-->
self.label_00 = QtWidgets.QLabel()
2021/02/22 Version=00.08b : correct the center facePoint (17h23 Paris)
self.label_00.setStyleSheet("color : #ffffff; background-color: red; font: bold 10px;") # white red bold
#self.label_00.setToolTip("Display the modification Axis and Rotation or Position")


<!--T:34-->
self.PB_Quit = QtWidgets.QPushButton()
2021/02/22 Version=00.08 : adding save macro with multi objects moved
self.PB_Quit.clicked.connect(self.on_PB_Quit_clicked)


<!--T:33-->
self.PB_Original = QtWidgets.QPushButton()
2021/01/24 Version=00.07 : adding option R: reverse
self.PB_Original.clicked.connect(self.on_PB_Original_clicked)


<!--T:32-->
self.PB_Zero = QtWidgets.QPushButton()
2021/01/12 ver 00.06 : adding the Data section and more options
self.PB_Zero.clicked.connect(self.on_PB_Zero_clicked)

self.PB_Reset = QtWidgets.QPushButton()
self.PB_Reset.clicked.connect(self.on_PB_Reset_clicked)

#### Gridlayout Header
self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.gridLayout_00_00 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_00_00.setContentsMargins(10, 10, 10, 10)#Gauche Haut Droit Bas
#### Gridlayout Header
#### Gridlayout BEGIN
self.grid_00_01 = QtWidgets.QGridLayout()
# self.gridLayoutWidget_3 = QtWidgets.QWidget(self.groupBox_Rotation)
self.grid_00_01.addWidget(self.groupBox_Rotation, 0, 0, 1, 1)
self.grid_00_01.setContentsMargins(0, 0, 0, 0) #Gauche Haut Droite Bas
self.grid_00_01_00 = QtWidgets.QGridLayout(self.groupBox_Rotation)
self.grid_00_01_00.setContentsMargins(10, 10, 0, 10)
self.grid_00_01_00.addWidget(self.RB_Bond_Box_Center, 0, 0, 1, 1)
self.grid_00_01_00.addWidget(self.RB_Center_Mass, 1, 0, 1, 1)
self.grid_00_01_00.addWidget(self.RB_Point_Clicked, 2, 0, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_01, 0, 0, 1, 1)
####
self.grid_00_02 = QtWidgets.QGridLayout()
self.grid_00_02.addWidget(self.groupBox_Axis, 0, 0, 1, 1)
self.grid_00_02.setContentsMargins(0, 0, 0, 0)
self.grid_00_02_00 = QtWidgets.QGridLayout(self.groupBox_Axis)
self.grid_00_02_00.setContentsMargins(10, 10, 0, 10)
self.grid_00_02_00.addWidget(self.RB_Rotation_X, 0, 0, 1, 1)
self.grid_00_02_00.addWidget(self.RB_Rotation_Y, 1, 0, 1, 1)
self.grid_00_02_00.addWidget(self.RB_Rotation_Z, 2, 0, 1, 1)
self.grid_00_02_00.addWidget(self.RB_Direction_D, 3, 0, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_02, 0, 1, 1, 1)
####
self.grid_00_03 = QtWidgets.QGridLayout()
self.grid_00_03.addWidget(self.groupBox_Pos_Mouse, 2, 0, 1, 1)
self.grid_00_03.setContentsMargins(0, 0, 0, 0)
self.grid_00_03_00 = QtWidgets.QGridLayout(self.groupBox_Pos_Mouse)
self.grid_00_03_00.setContentsMargins(10, 10, 10, 10)
self.grid_00_03_00.addWidget(self.DS_Pos_Mouse_X, 0, 0, 1, 1)
self.grid_00_03_00.addWidget(self.DS_Pos_Mouse_Y, 0, 1, 1, 1)
self.grid_00_03_00.addWidget(self.DS_Pos_Mouse_Z, 0, 2, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_03, 1, 0, 1, 2)
####
self.grid_00_04 = QtWidgets.QGridLayout()
self.grid_00_04.setContentsMargins(0, 10, 0, 0)
self.grid_00_04.addWidget(self.CB_Position, 0, 0, 1, 1)
# self.grid_00_04.addWidget(self.CB_Point, 0, 1, 1, 1)
self.grid_00_04.addWidget(self.PB_Point, 0, 1, 1, 1)
self.grid_00_04.addWidget(self.CB_Free, 0, 2, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_04, 2, 0, 1, 2)
####
self.grid_00_05 = QtWidgets.QGridLayout()
self.grid_00_05.setContentsMargins(0, 10, 0, 0)
self.grid_00_05.addWidget(self.LE_Increment, 0, 0, 1, 1)
self.grid_00_05.addWidget(self.DS_Scroll_Bar, 0, 1, 1, 1)
self.grid_00_05.addWidget(self.PB_Apply, 0, 2, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_05, 3, 0, 1, 2)
####
self.grid_00_06 = QtWidgets.QGridLayout()
self.grid_00_06.setContentsMargins(0, 0, 0, 0)
self.grid_00_06.addWidget(self.SC_Slider_Bar, 0, 0, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_06, 4, 0, 1, 2)
####
self.grid_00_07 = QtWidgets.QGridLayout()
self.grid_00_07.setContentsMargins(0, 0, 0, 0)
self.grid_00_07.addWidget(self.label_00, 0, 0, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_07, 5, 0, 1, 2)
####
self.grid_00_08 = QtWidgets.QGridLayout()
self.grid_00_08.setContentsMargins(0, 0, 0, 0)
self.grid_00_08.addWidget(self.PB_Quit, 0, 0, 1, 1)
self.grid_00_08.addWidget(self.PB_Original, 0, 1, 1, 1)
self.grid_00_08.addWidget(self.PB_Zero, 0, 2, 1, 1)
self.grid_00_08.addWidget(self.PB_Reset, 0, 3, 1, 1)
self.gridLayout_00_00.addLayout(self.grid_00_08, 6, 0, 1, 2)
#### Gridlayout END

MainWindow.setCentralWidget(self.centralwidget)

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

def retranslateUi(self, MainWindow):
MainWindow.setWindowFlags(PySide2.QtCore.Qt.WindowStaysOnTopHint) # this function turns the front window (stay to hint)
MainWindow.setWindowTitle(__title__ + " rmu (" + __version__ + ")")

_translate = QtCore.QCoreApplication.translate
self.groupBox_Rotation.setTitle(_translate("MainWindow", "Point Rotation"))
self.RB_Bond_Box_Center.setText(_translate("MainWindow", "Bounbox Center"))
self.RB_Bond_Box_Center.setToolTip(_translate("MainWindow", "Point rotation on BoundBox Center"))
self.RB_Center_Mass.setText(_translate("MainWindow", "Center of Mass"))
self.RB_Center_Mass.setToolTip(_translate("MainWindow", "Point rotation on Center Mass"))
self.RB_Point_Clicked.setText(_translate("MainWindow", "Point clicked"))
self.RB_Point_Clicked.setToolTip(_translate("MainWindow", "Point rotation on Point Mouse clicked on the object"+"\n"
"If twoo points are clicked, the second point is used for axis rotation"+"\n"
"The point axis rotation Can be changed during the work as long as the object is selected"+"\n"
"For this press the CTRL KEY and click the new point rotation"))

self.groupBox_Axis.setTitle(_translate("MainWindow", "Axis Rotation"))
self.RB_Rotation_X.setText(_translate("MainWindow", "Rotation(Z) Yaw"))
self.RB_Rotation_X.setToolTip(_translate("MainWindow", "Rotation on Axis Yaw (Z)"))
self.RB_Rotation_Y.setText(_translate("MainWindow", "Rotation(Y) Pitch"))
self.RB_Rotation_Y.setToolTip(_translate("MainWindow", "Rotation on Axis Pitch (Y)"))
self.RB_Rotation_Z.setText(_translate("MainWindow", "Rotation(X) Roll"))
self.RB_Rotation_Z.setToolTip(_translate("MainWindow", "Rotation on Axis Roll (X)"))
self.RB_Direction_D.setText(_translate("MainWindow", "Direction"))
self.RB_Direction_D.setToolTip(_translate("MainWindow", "Rotation or Translation on Direction" + "\n"
"For use the Direction option:" + "\n"
"Select First: the object to Rotate/Translate" + "\n"
"Second: the path: Line, Wire or Edge"))
self.groupBox_Pos_Mouse.setTitle(_translate("MainWindow", "Coordinates Point clicked"))
self.groupBox_Pos_Mouse.setToolTip(_translate("MainWindow", "Position click mouse modification possible only with mode Point clicked"))
self.DS_Pos_Mouse_X.setToolTip(_translate("MainWindow", "Position click mouse X" + "\n" +
"modification only with mode Point clicked"))
self.DS_Pos_Mouse_Y.setToolTip(_translate("MainWindow", "Position click mouse Y" + "\n" +
"modification only with mode Point clicked"))
self.DS_Pos_Mouse_Z.setToolTip(_translate("MainWindow", "Position click mouse Z" + "\n" +
"modification only with mode Point clicked"))
self.CB_Position.setText(_translate("MainWindow", "Translation"))
self.CB_Position.setToolTip(_translate("MainWindow", "Move the object to axis choice X, Y or Z"))
# self.CB_Point.setText(_translate("MainWindow", "Point"))
# self.CB_Point.setToolTip(_translate("MainWindow", "If checked, create one point to visualise the point rotation"))
self.PB_Point.setText(_translate("MainWindow", "Point"))
self.PB_Point.setToolTip(_translate("MainWindow", "Create one point to visualise the point rotation"))
self.CB_Free.setText(_translate("MainWindow", "Free"))
self.CB_Free.setToolTip(_translate("MainWindow", "This checkBox switch the Application button"))
self.LE_Increment.setToolTip(_translate("MainWindow", "Display the original Data + the modification"))
self.DS_Scroll_Bar.setToolTip(_translate("MainWindow", "Enter the modification"))
self.PB_Apply.setToolTip(_translate("MainWindow", "Apply the modification"))
self.PB_Apply.setText(_translate("MainWindow", "Apply"))
self.label_00.setText(_translate("MainWindow", " Select one Object"))
self.PB_Quit.setText(_translate("MainWindow", "Quit"))
self.PB_Quit.setToolTip(_translate("MainWindow", "Quite the macro"))
self.PB_Original.setText(_translate("MainWindow", "Original"))
self.PB_Original.setToolTip(_translate("MainWindow", "Move the object to the original position"))
self.PB_Reset.setText(_translate("MainWindow", "Reset"))
self.PB_Reset.setToolTip(_translate("MainWindow", "Reset the complete data macro"))
self.PB_Zero.setText(_translate("MainWindow", "0,0,0"))
self.PB_Zero.setToolTip(_translate("MainWindow", "Move the object to the base coordinates 0, 0, 0"))


def on_DS_Pos_Mouse_X(self,val):
global positionMouse
global axisX
positionMouse = [val, positionMouse[1], positionMouse[2]]
axisX = positionMouse[0]
# print("on_DS_Pos_Mouse_X ", val)

def on_DS_Pos_Mouse_Y(self,val):
global positionMouse
global axisY
positionMouse = [positionMouse[0], val, positionMouse[2]]
axisY = positionMouse[1]
# print("on_DS_Pos_Mouse_Y ", val)

def on_DS_Pos_Mouse_Z(self,val):
global positionMouse
global axisZ
positionMouse = [positionMouse[0], positionMouse[1], val]
axisZ = positionMouse[2]
# print("on_DS_Pos_Mouse_Z ", val)

def on_SC_Slider_Bar(self,val):
global ui
global valeur
global myObject

if myObject != "":
valeur = val
self.DS_Scroll_Bar.setValue(valeur)
self.SC_Slider_Bar.setValue(valeur)

if self.CB_Free.isChecked():
ff = ui
ff.on_PB_Apply_clicked()
else:
self.DS_Scroll_Bar.setValue(0.0)
self.SC_Slider_Bar.setValue(0.0)
# print("on_SC_Scroll_Bar ", valeur)

def on_DS_Scroll_Bar(self,val):
global valeur
global myObject
global axisX, axisY, axisZ
global posX, posY, posZ
global rotAngleX, rotAngleY, rotAngleZ

if myObject == "":
self.DS_Scroll_Bar.setValue(0.0)
self.SC_Slider_Bar.setValue(0.0)
None
else:
valeur = val
self.SC_Slider_Bar.setValue(valeur)
if self.CB_Position.isChecked(): # translate

if self.RB_Rotation_X.isChecked():
posX = valeur
posY = posZ = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Base[0],4) + valeur))
elif self.RB_Rotation_Y.isChecked():
posY = valeur
posX = posZ = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Base[1],4) + valeur))
elif self.RB_Rotation_Z.isChecked():
posZ = valeur
posX = posY = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Base[2],4) + valeur))
elif self.RB_Direction_D.isChecked():
posZ = valeur
posX = posY = 0.0
xD = str(round(myObject.Placement.Base[0],4))
yD = str(round(myObject.Placement.Base[1],4))
zD = str(round(myObject.Placement.Base[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")

self.label_00.setText("[Pos=(" + str(round(myObject.Placement.Base[0],2))+" , " +
str(round(myObject.Placement.Base[1],2))+" , " +
str(round(myObject.Placement.Base[2],2))+")] " +
"[Axis=("+ str(round(axisX,2)) + " , " + str(round(axisY,2)) + " , " + str(round(axisZ,2)) + ")]")

else: # rotation

if self.RB_Rotation_X.isChecked():
rotAngleX = valeur
rotAngleY = rotAngleZ = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4) + valeur))
elif self.RB_Rotation_Y.isChecked():
rotAngleY = valeur
rotAngleZ = rotAngleX = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4) + valeur))
elif self.RB_Rotation_Z.isChecked():
rotAngleZ = valeur
rotAngleX = rotAngleY = 0.0
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4) + valeur))
elif self.RB_Direction_D.isChecked():
rotAngleZ = valeur
rotAngleX = rotAngleY = 0.0
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")

self.label_00.setText("[Rot=(" + str(round(rotAngleX,2)) + " , " + str(round(rotAngleY,2)) + " , " + str(round(rotAngleZ,2)) + ")] " +
"[Axis=("+ str(round(axisX,2)) + " , " + str(round(axisY,2)) + " , " + str(round(axisZ,2)) + ")]")
# print("on_DS_Scroll_Bar ", valeur)

def on_LE_Increment_Pressed(self,text):
None
# print("on_lineEdit_1_Pressed")

def on_PB_Apply_clicked(self):
global valeur
global myObject
global positionMouse
global originalPlacement
global originalObject

global axisX, axisY, axisZ
global posX, posY, posZ
global rotAngleX, rotAngleY, rotAngleZ

if (myObject == "") :
self.label_00.setStyleSheet("color : #ffffff; background-color: red; font: bold 10px;") # white red bold
self.label_00.setText(" Select one Object")
FreeCAD.Console.PrintError("Select one Object" + "\n")
else:
if self.CB_Position.isChecked(): # translate

if self.RB_Direction_D.isChecked(): # direction
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0] # select one element and axis second object (2 selections)
except Exception:
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[1] # select one element and axis same object (2 selections)
except Exception:
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0] # select one element and axis same object (1 selection)
except Exception:
None
pointsTrajet = []
try:
pointsTrajet = selectedEdge.discretize(Distance = 1.0) # discretize the element
except Exception:
direction = myObject.Shape.Vertexes[0].Point
pointsTrajet = direction
None
try:
direction = pointsTrajet[1].sub(pointsTrajet[0]) # search the direction line or sub
except Exception:
try:
direction = myObject.Shape.Vertexes[0].Point # direction point
except Exception:
direction = App.Vector(0.0,0.0,0.0)
myObject.Placement.Base = myObject.Placement.Base + App.Vector(direction).scale(valeur, valeur, valeur)
else:
myObject.Placement = App.Placement(App.Vector(posX, posY, posZ), App.Rotation(0.0,0.0,0.0), App.Vector(0.0,0.0,0.0)).multiply(App.ActiveDocument.getObject(myObject.Name).Placement)

if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[0],4)))
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[1],4)))
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[2],4)))
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Base[0],4))
yD = str(round(myObject.Placement.Base[1],4))
zD = str(round(myObject.Placement.Base[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")

self.label_00.setText("[Pos=(" + str(round(myObject.Placement.Base[0],2))+" , " +
str(round(myObject.Placement.Base[1],2))+" , " +
str(round(myObject.Placement.Base[2],2))+")] " +
"[Axis=("+ str(round(axisX,2)) + " , " + str(round(axisY,2)) + " , " + str(round(axisZ,2)) + ")]")

else: # rotation
if self.RB_Direction_D.isChecked(): # direction
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0] # select one element and axis second object (2 selections)
except Exception:
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[1] # select one element and axis same object (2 selections)
except Exception:
try:
selectedEdge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0] # select one element and axis same object (1 selection)
except Exception:
None
try:
direction = selectedEdge.Vertexes[1].Point.sub(selectedEdge.Vertexes[0].Point)# search the direction line or sub
except Exception:
try:
direction = objectRotation.Vertexes[0].Point
except Exception:
direction = App.Vector(0.0,0.0,0.0)
myObject.Placement = App.Placement(App.Vector(0.0,0.0,0.0), App.Rotation(App.Vector(direction), valeur), App.Vector(axisX, axisY, axisZ)).multiply(App.ActiveDocument.getObject(myObject.Name).Placement)
else:
myObject.Placement = App.Placement(App.Vector(0.0,0.0,0.0), App.Rotation(rotAngleX, rotAngleY, rotAngleZ), App.Vector(axisX, axisY, axisZ)).multiply(App.ActiveDocument.getObject(myObject.Name).Placement) # other method

if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4)))
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4)))
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4)))
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")

self.label_00.setText("[Rot=(" + str(round(myObject.Placement.Rotation.toEuler()[0],2)) + " , " +
str(round(myObject.Placement.Rotation.toEuler()[1],2)) + " , " +
str(round(myObject.Placement.Rotation.toEuler()[2],2)) + ")] " +
"[Axis=("+ str(round(axisX,2))+" , "+ str(round(axisY,2))+" , "+ str(round(axisZ,2))+")]")
# FreeCAD.ActiveDocument.recompute()
# print("on_PB_Apply_clicked")

def on_RB_Rotation_0(self):
None
# print("on_RB_Rotation_0")

def on_RB_Rotation_X(self):
global myObject
if self.CB_Position.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[0],4))) # pos X
else:
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4))) # yaw = Z
self.DS_Scroll_Bar.setValue(0.0)
# print("on_RB_Rotation_X")

def on_RB_Rotation_Y(self):
global myObject
if self.CB_Position.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[1],4))) # pos Y
else:
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4))) # pitch= Y
self.DS_Scroll_Bar.setValue(0.0)
# print("on_RB_Rotation_Y")

def on_RB_Rotation_Z(self):
global myObject
if self.CB_Position.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[2],4))) # pos Z
else:
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4))) # roll = X
self.DS_Scroll_Bar.setValue(0.0)
# print("on_RB_Rotation_Z")

def on_RB_Direction_D(self):
global myObject
if self.CB_Position.isChecked():
xD = str(round(myObject.Placement.Base[0],4))
yD = str(round(myObject.Placement.Base[1],4))
zD = str(round(myObject.Placement.Base[2],4))
else:
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")
self.DS_Scroll_Bar.setValue(0.0)
# print("on_RB_Direction_D")

def on_RB_CenterRot(self): # zero
global myObject
global positionMouse
global axisX, axisY, axisZ
try:
self.groupBox_Pos_Mouse.setEnabled(False)
if self.RB_Bond_Box_Center.isChecked(): # axis
axisX = myObject.Shape.BoundBox.Center.x
axisY = myObject.Shape.BoundBox.Center.y
axisZ = myObject.Shape.BoundBox.Center.z
self.label_00.setToolTip("Axis BoundBox.Center")
elif self.RB_Center_Mass.isChecked():
axisX = myObject.Shape.CenterOfMass.x
axisY = myObject.Shape.CenterOfMass.y
axisZ = myObject.Shape.CenterOfMass.z
self.label_00.setToolTip("Axis Center Of Mass")
elif self.RB_Point_Clicked.isChecked():
axisX = positionMouse[0]
axisY = positionMouse[1]
axisZ = positionMouse[2]
self.groupBox_Pos_Mouse.setEnabled(True)
self.label_00.setToolTip("Point Mouse")
except Exception:
self.label_00.setText("Error CenterRot_0")
FreeCAD.Console.PrintError("Error CenterRot_0" + "\n" + "or Bad selection" + "\n")
# print("on_RB_CenterRot")

def on_CB_Position(self):
global myObject
global posX, posY, posZ
global axisX, axisY, axisZ

if self.CB_Position.isChecked():
self.groupBox_Rotation.setEnabled(False)
self.RB_Bond_Box_Center.setChecked(True)
self.SC_Slider_Bar.setMinimum(-1000)
self.SC_Slider_Bar.setMaximum(1000)
self.DS_Scroll_Bar.setMinimum(-1000)
self.DS_Scroll_Bar.setMaximum(1000)

self.groupBox_Axis.setTitle("Axis Translation")
self.RB_Rotation_Z.setText("Translation Z ") # translate
self.RB_Rotation_Y.setText("Translation Y ")
self.RB_Rotation_X.setText("Translation X ")
self.RB_Direction_D.setText("Translation D ")

try:
self.label_00.setText("[Pl.Base=(" + str(round(myObject.Placement.Base[0],2)) + " , " +
str(round(myObject.Placement.Base[1],2)) + " , " +
str(round(myObject.Placement.Base[2],2)) + ")] " +
"[Axis=("+ str(round(axisX,2)) + " , " + str(round(axisY,2)) + " , " + str(round(axisZ,2)) + ")]")
if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[0],4)))
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[1],4)))
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Base[2],4)))
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Base[0],4))
yD = str(round(myObject.Placement.Base[1],4))
zD = str(round(myObject.Placement.Base[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")
except Exception:
self.label_00.setText("Error Position_0")
FreeCAD.Console.PrintError("Error Position_0" + "\n" + "or Bad selection" + "\n")
else:
self.groupBox_Rotation.setEnabled(True)
self.SC_Slider_Bar.setMinimum(-360)
self.SC_Slider_Bar.setMaximum(360)
self.DS_Scroll_Bar.setMinimum(-360)
self.DS_Scroll_Bar.setMaximum(360)

self.groupBox_Axis.setTitle("Axis Rotation")
self.RB_Rotation_Z.setText("Rotation(X) Roll") # rotation
self.RB_Rotation_Y.setText("Rotation(Y) Pitch")
self.RB_Rotation_X.setText("Rotation(Z) Yaw")
self.RB_Direction_D.setText("Rotation(D)")

try:
self.label_00.setText("[Rot=(" + str(round(myObject.Placement.Rotation.toEuler()[0],2)) + " , " +
str(round(myObject.Placement.Rotation.toEuler()[1],2)) + " , " +
str(round(myObject.Placement.Rotation.toEuler()[2],2)) + ")] " +
"[Axis=("+str(round(axisX,2))+" , "+ str(round(axisY,2))+" , "+ str(round(axisZ,2))+")]")
if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4)))
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4)))
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4)))
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")
except Exception:
self.label_00.setText("Error Position_1")
FreeCAD.Console.PrintError("Error Position_0" + "\n" + "or Bad selection" + "\n")

self.DS_Scroll_Bar.setValue(0.0)
# print("on_CB_Position")

def on_CB_Point(self):
global ui
global myObject
global positionMouse
if self.RB_Bond_Box_Center.isChecked(): # axis
# if self.CB_Point.isChecked():
point = Draft.makePoint(myObject.Shape.BoundBox.Center.x, myObject.Shape.BoundBox.Center.y, myObject.Shape.BoundBox.Center.z)
point.ViewObject.PointColor = (1.0,0.0,0.0)
point.Label = "Point_BoundBox_Center"
elif self.RB_Center_Mass.isChecked():
# if self.CB_Point.isChecked():
point = Draft.makePoint(myObject.Shape.CenterOfMass.x, myObject.Shape.CenterOfMass.y, myObject.Shape.CenterOfMass.z)
point.ViewObject.PointColor = (0.0,1.0,0.0)
point.Label = "Point_CenterOfMass"
elif self.RB_Point_Clicked.isChecked():
# if self.CB_Point.isChecked():
point = Draft.makePoint(positionMouse[0], positionMouse[1], positionMouse[2])
point.ViewObject.PointColor = (0.0,0.0,1.0)
point.Label = "Point_positionMouse"
Gui.Selection.addSelection(App.ActiveDocument.getObject(myObject.Name))
FreeCAD.ActiveDocument.recompute()
# ff = ui
# ff.on_RB_CenterRot()
# print("on_CB_Point")

def on_PB_Zero_clicked(self):
global myObject

if (myObject != ""):
try:
pl = App.Placement(App.Vector(0.0,0.0,0.0), App.Rotation(0.0, 0.0, 0.0), App.Vector(0.0, 0.0, 0.0))
myObject.Placement = pl
#FreeCAD.ActiveDocument.recompute()
if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4)))
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4)))
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4)))
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")
self.label_00.setText("[Rot=(" +str(round(myObject.Placement.Rotation.toEuler()[0],2))+" , "+str(round(myObject.Placement.Rotation.toEuler()[1],2))+" , "+ str(round(myObject.Placement.Rotation.toEuler()[2],2))+")] "+
"[Axis=("+str(round(myObject.Placement.Base.x,2))+" , "+ str(round(myObject.Placement.Base.y,2))+" , "+ str(round(myObject.Placement.Base.z,2))+")]")
self.DS_Scroll_Bar.setValue(0.0)
self.LE_Increment.setText(str(0.0))
#FreeCAD.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewTop()
Gui.SendMsgToActiveView("ViewFit")
except Exception:
self.label_00.setText("Error Zero_0")
FreeCAD.Console.PrintError("Error Zero_0" + "\n" + "or Bad selection" + "\n")
else:
self.label_00.setStyleSheet("color : #ffffff; background-color: red; font: bold 10px;") # white red bold
self.label_00.setText(" Select one Object")
FreeCAD.Console.PrintError("Select one Object" + "\n")
# print("on_PB_Zero_clicked")

def on_PB_Original_clicked(self):
global ui
global myObject
global originalPlacement
global axisX, axisY, axisZ
global rotAngleX, rotAngleY, rotAngleZ

if (myObject != ""):
try:
rotAngleX = rotAngleY = rotAngleZ = 0.0
myObject.Placement = originalPlacement
self.DS_Scroll_Bar.setValue(0.0)
if self.RB_Rotation_X.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[0],4))) # yaw Z
elif self.RB_Rotation_Y.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[1],4))) # pitch Y
elif self.RB_Rotation_Z.isChecked():
self.LE_Increment.setText(str(round(myObject.Placement.Rotation.toEuler()[2],4))) # roll Z
elif self.RB_Direction_D.isChecked():
xD = str(round(myObject.Placement.Rotation.toEuler()[0],4))
yD = str(round(myObject.Placement.Rotation.toEuler()[1],4))
zD = str(round(myObject.Placement.Rotation.toEuler()[2],4))
self.LE_Increment.setText("(" + xD + ", " + yD + ", " + zD + ")")
ff = ui
ff.on_RB_CenterRot()
self.label_00.setText("[Rot=(" +str(round(myObject.Placement.Rotation.toEuler()[0],2))+" , "+str(round(myObject.Placement.Rotation.toEuler()[1],2))+" , "+ str(round(myObject.Placement.Rotation.toEuler()[2],2))+")] "+
"[Axis=("+str(round(axisX,2))+" , "+ str(round(axisY,2))+" , "+ str(round(axisZ,2))+")]")
#FreeCAD.ActiveDocument.recompute()
except Exception:
self.label_00.setText("Error Original_0")
FreeCAD.Console.PrintError("Error Original_0" + "\n" + "or Bad selection" + "\n")
else:
self.label_00.setStyleSheet("color : #ffffff; background-color: red; font: bold 10px;") # white red bold
self.label_00.setText(" Select one Object")
FreeCAD.Console.PrintError("Select one Object" + "\n")
# print("on_PB_Original_clicked")

def on_PB_Reset_clicked(self):
global originalObject
global myObject
global valeur
global posX, posY, posZ
global rotAngleX, rotAngleY, rotAngleZ
global axisX, axisY, axisZ

try:
for obj in FreeCAD.ActiveDocument.Objects: # deslectionne
FreeCADGui.Selection.removeSelection(obj)
except Exception:
None

originalObject = myObject = ""
posX = posY = posZ = rotAngleX = rotAngleY = rotAngleZ = 0.0
axisX = axisY = axisZ = 0.0
valeur = 0.0

self.DS_Scroll_Bar.setValue(0.0)
self.LE_Increment.setText(str(0.0))

self.groupBox_Axis.setTitle("Axis Rotation")
self.RB_Rotation_Z.setText("Rotation(X) Roll")
self.RB_Rotation_Y.setText("Rotation(Y) Pitch")
self.RB_Rotation_X.setText("Rotation(Z) Yaw")
self.RB_Direction_D.setText("Rotation(D) Direction")

self.groupBox_Rotation.setEnabled(False)
self.groupBox_Axis.setEnabled(False)
self.groupBox_Pos_Mouse.setEnabled(False)

self.DS_Pos_Mouse_X.setValue(0.0)
self.DS_Pos_Mouse_Y.setValue(0.0)
self.DS_Pos_Mouse_Z.setValue(0.0)

self.CB_Position.setEnabled(False)
self.CB_Position.setChecked(False)
# self.CB_Point.setEnabled(False)
# self.CB_Point.setChecked(False)
self.PB_Point.setEnabled(False)
self.CB_Free.setEnabled(False)
self.CB_Free.setChecked(False)

self.label_00.setStyleSheet("color : #ffffff; background-color: red; font: bold 10px;") # white red bold
self.label_00.setText(" Select one Object")
FreeCAD.Console.PrintError("Select one Object" + "\n")
FreeCAD.Console.PrintMessage("Reset" + "\n")

def on_PB_Quit_clicked(self):
self.vueActive.removeEventCallback("SoMouseButtonEvent",self.click) # desinstalle la fonction souris
FreeCADGui.Selection.removeObserver(s) # desinstalle la fonction residente
self.window.hide() # hide the window and close the macro
FreeCAD.Console.PrintMessage("Quit Rotate_To_Point" + "\n")

###################################################################################################
class SelObserver:
def addSelection(self, document, object, element, position): # Selection
global ui
global sourisPass
global positionMouse
global originalObject
global myObject
global originalPlacement

global posX, posY, posZ
global rotAngleX, rotAngleY, rotAngleZ
global axisX, axisY, axisZ

if sourisPass == 0: # pour un seul passage
sourisPass == 1

sel = FreeCADGui.Selection.getSelection()[0] # select object with getSelection()
positionMouse = position
originalObject = myObject = sel
originalPlacement = sel.Shape.Placement

#longueur = (myObject.Shape.BoundBox.XLength * 0.5) # pour Axis
positionBase = originalObject.Shape.Placement.Base # Placement Vector XYZ
posX = positionBase.x
posY = positionBase.y
posZ = positionBase.z
Yaw = originalObject.Shape.Placement.Rotation.toEuler()[0] # decode angle Euler Yaw
Pitch = originalObject.Shape.Placement.Rotation.toEuler()[1] # decode angle Euler Pitch
Roll = originalObject.Shape.Placement.Rotation.toEuler()[2] # decode angle Euler Roll
rotAngleX = Yaw
rotAngleY = Pitch
rotAngleZ = Roll
axisX = axisY = axisZ = 0.0

ff = ui
ff.DS_Pos_Mouse_X.setValue(positionMouse[0])
ff.DS_Pos_Mouse_Y.setValue(positionMouse[1])
ff.DS_Pos_Mouse_Z.setValue(positionMouse[2])

ff.on_RB_CenterRot()
if ff.CB_Position.isChecked():
ff.groupBox_Rotation.setEnabled(False)
else:
ff.groupBox_Rotation.setEnabled(True)
ff.groupBox_Axis.setEnabled(True)
#ff.groupBox_Pos_Mouse.setEnabled(True)
ff.CB_Position.setEnabled(True)
# ff.CB_Point.setEnabled(True)
ff.PB_Point.setEnabled(True)
ff.CB_Free.setEnabled(True)
ff.label_00.setStyleSheet("Base") # origin system
ff.label_00.setText("[Rot =(" + str(round(rotAngleX,2))+ " , " + str(round(rotAngleY,2)) + " , " + str(round(rotAngleZ,2)) + ")] " +
"[Axis=("+ str(round(axisX,2)) + " , " + str(round(axisY,2)) + " , " + str(round(axisZ,2)) + ")]")

def clearSelection(self,doc): # Si clic sur l'ecran, effacer la selection
global ui
ff = ui
ff.on_PB_Reset_clicked()

###################################################################################################

doc = FreeCAD.ActiveDocument
if doc == None:
doc = FreeCAD.newDocument()

try:
for obj in FreeCAD.ActiveDocument.Objects: # deselectionne
FreeCADGui.Selection.removeSelection(obj)
except Exception:
None

s=SelObserver()
FreeCADGui.Selection.addObserver(s) # installe la fonction en mode resident

if __name__ == "__main__":
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("__title__") # macro internal Name
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
}}
<translate>
==Example:== <!--T:9-->
</translate>
[[File:Macro Rotate To Point 01.gif ]]
<translate>
==Links== <!--T:10-->
</translate>
The forum [http://forum.freecadweb.org/viewtopic.php?f=8&t=20925 feature req: placement - rotate part around its midpoint]
<translate>
<!--T:11-->
My macro to Gist [https://gist.github.com/mario52a mario52a ]
</translate>
<translate>
==Version== <!--T:12-->
</translate>
<translate>


<!--T:20-->
2020/03/07 ver 00.05.2 : correct the bug translation delete "direction = myObject.Placement.Rotation.multVec(direction)"
2020/03/07 ver 00.05.2 : correct the bug translation delete "direction = myObject.Placement.Rotation.multVec(direction)"


Line 1,130: Line 233:
<!--T:14-->
<!--T:14-->
05/03/2017 ver 00.01 : add 3 spinbox for displayed the coordinates X Y Z on click mouse
05/03/2017 ver 00.01 : add 3 spinbox for displayed the coordinates X Y Z on click mouse
</translate>


<translate>
<!--T:13-->
<!--T:13-->
04/03/2017 ver 00.00
04/03/2017 ver 00.00

Latest revision as of 10:12, 29 December 2023

Other languages:

Macro Rotate To Point

Description
Macro to rotate an object on itself with the axis of rotation the: boundbox center, center of mass, direction of wire, or last point clicked. You must save in a file all coordinate worked and save it in a file "Coordinate [(0.06,1.30,0.0),(85.0,0.0,0.0)]," or in a complete macro with different options (Create serial image) for create one animation, increase/decrease, pause, yoyo ....

Macro version: 00.11
Last modified: 2022/10/17
FreeCAD version: 0.19 and more
Download: ToolBar Icon
Author: Mario52
Author
Mario52
Download
ToolBar Icon
Links
Macro Version
00.11
Date last modified
2022/10/17
FreeCAD Version(s)
0.19 and more
Default shortcut
None
See also
None

Description

Macro to rotate an object on itself with the axis of rotation the: boundbox center, center of mass, direction, path of wire, or last point clicked. You must save in a file all coordinate worked and save it in a file "Coordinate [(0.06,1.30,0.0),(85.0,0.0,0.0)],"
or in a complete macro with different options (Create serial image) for create one animation, increase/decrease, pause, yoyo ....


Temporary code for external macro link. Do not use this code. This code is used exclusively by Addon Manager. Link for optional manual installation: Macro


# This code is copied instead of the original macro code
# to guide the user to the online download page.
# Use it if the code of the macro is larger than 64 KB and cannot be included in the wiki
# or if the RAW code URL is somewhere else in the wiki.

from PySide import QtGui, QtCore

diag = QtGui.QMessageBox(QtGui.QMessageBox.Information,
    "Information",
    "This macro must be downloaded from this link\n"
    "\n"
    "https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/d9419d4bb13e36940eb2f56c3c469ea4182827ee/Macro%2520Rotate%2520To%2520Point.FCMacro" + "\n"
    "\n"
    "Quit this window to access the download page")

diag.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
diag.setWindowModality(QtCore.Qt.ApplicationModal)
diag.exec_()

import webbrowser 
webbrowser.open("https://gist.githubusercontent.com/mario52a/2fc48333deca5a31e6232c29a9db5e4c/raw/d9419d4bb13e36940eb2f56c3c469ea4182827ee/Macro%2520Rotate%2520To%2520Point.FCMacro")


Usage

  1. Download the macro from the Addon Manager
  2. Execute the macro
  3. Select one object
  4. Choose one of the following orientations:

Interface Rotate to point

[1] Position Rotation

First operation

[1] Position Rotation

  • Translation: If this checkBox is checked the rotation is disabled, the object placement is done on the axis selected.

The SpinBox 1,00000 Degrees is reinitialized to 0.0 and coloured in red

  • The time passed with your favourite macro is displayed.

[2] Translation Rotation

Second operation

[2]Translation Rotation

Point Rotation

  • Boundbox Center: Select the BoundBox center to axis rotation
  • Center of Mass: Select the Center of Mass to axis rotation
  • Point Clicked: Select the last mouse click as the point for axis rotation
    • 1: select the object
    • 2: use the CTRL key to choose an extra object

Axis Rotation

  • Rotation(Z) Yaw: Yaw axis
  • Rotation(Y) Pitch: Pitch axis
  • Rotation(X) Roll: Roll axis
  • Rotation(D) Direction: Rotate around line, wire selected
  • Follow the path: Follow the path created by the wire, line, edge.
    • 1: Select the object
    • 2: Select the path

The SpinBox 1,00000 Degrees is reinitialized to 0.0 and coloured in red

Coordinates Point clicked

Rotate To Point Coordinate-On-Point-Clicked

  • DoubleSpinBox: Coordinate X on mouse click (modifiable only with the mode "Point Clicked")
  • DoubleSpinBox: Coordinate Y on mouse click (modifiable only with the mode "Point Clicked")
  • DoubleSpinBox: Coordinate Z on mouse click (modifiable only with the mode "Point Clicked")

[3] Work (Box : Cube)

Third operation

Macro Rotate To Point Work

  • View: If checked, the view return on latest view of the object selected (work with comboBox below it) and all parameters restored.
  • Point: One point is created for visualise the point rotation axis: red X, green Y, blue Z.
  • Center: One point is created on center of circle.
  • Box : List of all objects used. The choice of the object here, the zoom (if checkBox view is checked) is returned and all parameters restored.
  • 0 : Select one predefined value.
  • 1.0 : Select the saved value used.
  • - Invert: Invert the sign Positif/Negatif of the value displayed.
  • 1,00000 Degrees : Select the value.
  • Apply: Apply the modification to the object.
  • Line Edit: The line edit displays the original coordinate to axis selected + the input data given in the spinBox.
  • The coordinate is displayed

Data to save

Rotate To Point Data-To-Save

  • Window for display the coordinates stored.
  • Clear: Delete and clean the text editor.
  • Delete: Delete the selected line in the window.
  • Memo on Click: If it is checked, the placement is automatically stored in the window with the "Apply" button.
  • Memorize: Store and display the coordinate in the window, the number of coordinate stored is displayed on this button.
  • Save: Save the data in file
  • Macro:
    • Mode normal Macro the coordinate is saved in this mode : ["Body004001",(0.0,0.0,-1.5),(0.0,0.0,0.0)],
    • Mode macro 0,0 Coordinate the coordinate is saved (one object or many objects worked)
      in a complete macro directly in your macros directory with the same name of the document with extension .FCMacro
      • Options of the macro
      • __pompe____engrenage__ : Name of document
      • __22 Coordinates__ : number of coordinates
      • Type Key Q to Quit : Quit the macro
      • Type Key A to Create serial image : for create serial usage to create Animate GIF (with Gimp or other)
      • Type Key D to Decrease speed : Decrease the speed of the animation
      • Type Key I to Increase speed : Increase the speed of the animation
      • Type Key P to Pause/Continue or key RETURN or ESCAPE : Pause / Anime
      • Type Key S to Step by Step (key RETURN or ESCAPE to continue) : Step by Step
      • Type Key V to reVerse : reVerse the video
      • Type Key Y to YoYo : begin to end reverse end to begin
      • Type Key M for this message : Display this Memo
      • For use this options click mouse in the 3D view and type the key desidered
      • ____________________________
    • Mode normal Memo on Click : The data is not saved on window, you must push the Memo (2) button for save the coordinate
    • Mode Memo on Click Memo on Demand : The data is automaticly saved with all click op the Apply button
  • Copy: Memorize the content of the window in a Rotate_To_Point format : ["Body004001",(0.0,0.0,-1.5),(0.0,0.0,0.0)],

Command

Rotate To Point Command

  • Quit: Quit the macro
  • Original: After modifying the data of the object you can return to the original placement, If you have not deselected the current object.
  • 0,0,0 : This option places the object in base coordinate 0, 0, 0.
  • Reset: Reset the data in the macro and deselect the current object.

ToolBar PNG Icon and ToolBar SVG Icon

Example

Links

The forum feature req: placement - rotate part around its midpoint

My macro on Gist mario52a

Version

2022/10/17 Version=00.11 : new organization GUI, Follow the path, View on object, Button Copy, adding menu Image on macro saved, add "QtWidgets.QScrollArea()"

2021/03/08 Version=00.10 : adding zoom on object clicked, memory value, imposted values

2021/02/25 Version=00.09 : correct the macro : cause multi object possible

App.ActiveDocument.getObject(p[0]).Placement

instead

myObject.Placement

2021/02/22 Version=00.08c : correct the center facePoint (19h26 Paris)

2021/02/22 Version=00.08b : correct the center facePoint (17h23 Paris)

2021/02/22 Version=00.08 : adding save macro with multi objects moved

2021/01/24 Version=00.07 : adding option R: reverse

2021/01/12 ver 00.06 : adding the Data section and more options

2020/03/07 ver 00.05.2 : correct the bug translation delete "direction = myObject.Placement.Rotation.multVec(direction)"

2020/03/01 ver 00.05.1 : correct the position of the test "FreeCAD version"

2020/02/29 ver 00.05 : convert to Hdpi (Layout) and add Direction

06/04/2019 ver 00.04 : Python 3

29/03/2018 ver 00.03 : comment the "FreeCAD.ActiveDocument.recompute()" the change value are too slow with complex element in FreeCAD 0.17.... see FC0.17 recompute strange behaviour (regression)

27/03/2017 ver 00.02 : modify the spinbox "Pos" now accept the negative values

05/03/2017 ver 00.01 : add 3 spinbox for displayed the coordinates X Y Z on click mouse

04/03/2017 ver 00.00