Macro View Rotation: Difference between revisions
mNo edit summary |
Galou breizh (talk | contribs) (Remove inlined script) |
||
Line 14: | Line 14: | ||
Three icons are referred to to symbolise the rotation directions. A zip file containing these icons can be found [http://forum.freecadweb.org/download/file.php?id=453 here], the images should be placed in the folder containing your macros. Please feel free to contribute better ones! |
Three icons are referred to to symbolise the rotation directions. A zip file containing these icons can be found [http://forum.freecadweb.org/download/file.php?id=453 here], the images should be placed in the folder containing your macros. Please feel free to contribute better ones! |
||
== |
==Code== <!--T:6--> |
||
</translate> |
</translate> |
||
'''Macro_View_Rotation.FCMacro''' |
|||
The lastest version of the macro is to be found at [https://github.com/FreeCAD/FreeCAD-macros/blob/master/PureGui/ViewRotation.FCMacro ViewRotation.FCMacro] but the easiest way to install this macro is through the [[AddonManager|Addon Manager]]. |
|||
{{Code|code= |
|||
import PySide |
|||
from PySide import QtGui, QtCore |
|||
from pivy import coin |
|||
from math import pi |
|||
def find_centre(): |
|||
xmax = xmin = ymax = ymin = zmax = zmin = 0 |
|||
for obj in App.ActiveDocument.Objects: |
|||
if obj.TypeId[:4] == "Mesh": |
|||
box = obj.Mesh.BoundBox |
|||
elif obj.TypeId[:6] == "Points": |
|||
box = obj.Points.BoundBox |
|||
elif obj.TypeId[:4] == "Part": |
|||
box = obj.Shape.BoundBox |
|||
else: |
|||
continue |
|||
xmax = max(xmax, box.XMax) |
|||
xmin = min(xmin, box.XMin) |
|||
ymax = max(ymax, box.YMax) |
|||
ymin = min(ymin, box.YMin) |
|||
zmax = max(zmax, box.ZMax) |
|||
zmin = min(zmin, box.ZMin) |
|||
centre = FreeCAD.Vector((xmax+xmin)/2.0, (ymax+ymin)/2.0, (zmax+zmin)/2.0) |
|||
return centre |
|||
class rotate_gui(QtGui.QWidget): |
|||
def __init__(self): |
|||
super(rotate_gui, self).__init__() |
|||
self.initUI() |
|||
self.initRotate() |
|||
def initUI(self): |
|||
self.sld = [0,1,2] |
|||
self.tbox = [0,1,2] |
|||
path = FreeCAD.ConfigGet("UserAppData") |
|||
icon = [0,1,2] |
|||
icons = ('right.png', 'up.png', 'out.png') |
|||
for i in range(3): |
|||
self.sld[i] = QtGui.QSlider(QtCore.Qt.Horizontal, self) |
|||
self.sld[i].setFocusPolicy(QtCore.Qt.NoFocus) |
|||
self.sld[i].setSingleStep(5) |
|||
self.sld[i].setPageStep(15) |
|||
self.sld[i].setValue(0) |
|||
self.sld[i].setMaximum(180) |
|||
self.sld[i].setMinimum(-180) |
|||
self.tbox[i] = QtGui.QLineEdit(self) |
|||
self.tbox[i].setText("0") |
|||
self.tbox[i].setAlignment(QtCore.Qt.AlignRight) |
|||
icon[i] = QtGui.QLabel(self) |
|||
icon[i].setPixmap(QtGui.QPixmap(path + icons[i])) |
|||
self.sld[i].valueChanged[int].connect(self.valueChange) |
|||
self.tbox[i].returnPressed.connect(self.valueEntered) |
|||
resetButton = QtGui.QPushButton("Reset") |
|||
resetButton.clicked.connect(self.reset) |
|||
okButton = QtGui.QPushButton("OK") |
|||
okButton.clicked.connect(self.close) |
|||
cancelButton = QtGui.QPushButton("Cancel") |
|||
cancelButton.clicked.connect(self.cancel) |
|||
hbox = [0,1,2,3] |
|||
vbox = QtGui.QVBoxLayout() |
|||
for i in range(3): |
|||
hbox[i] = QtGui.QHBoxLayout() |
|||
hbox[i].addWidget(icon[i],1, QtCore.Qt.AlignCenter) |
|||
hbox[i].addWidget(self.sld[i],4) |
|||
hbox[i].addWidget(self.tbox[i],1) |
|||
vbox.addLayout(hbox[i]) |
|||
hbox[3] = QtGui.QHBoxLayout() |
|||
hbox[3].addWidget(resetButton,1) |
|||
hbox[3].addWidget(okButton,1) |
|||
hbox[3].addWidget(cancelButton,1) |
|||
vbox.addStretch(1) |
|||
vbox.addLayout(hbox[3]) |
|||
self.setLayout(vbox) |
|||
a = QtGui.QDesktopWidget() |
|||
right = a.availableGeometry().width() |
|||
self.setGeometry(right-300, 0, 300, 150) |
|||
self.setWindowTitle('Rotate view...') |
|||
self.show() |
|||
def initRotate(self): |
|||
self.internal = False |
|||
self.current = 0 |
|||
self.cam = Gui.ActiveDocument.ActiveView.getCameraNode() |
|||
self.centre = coin.SbVec3f(find_centre()) |
|||
self.view = self.cam.orientation.getValue() |
|||
self.pos = self.cam.position.getValue() |
|||
#store a copy of the original view to be restored in the case of user selecting Reset or Cancel |
|||
self.original_view = coin.SbRotation(self.view.getValue()) |
|||
self.original_pos = coin.SbVec3f(self.pos.getValue()) |
|||
self.config_direction(0) |
|||
def reset(self): |
|||
#reset the view to the original one |
|||
self.cam.orientation = self.original_view |
|||
self.cam.position = self.original_pos |
|||
self.internal = True |
|||
for sld in self.sld: |
|||
sld.setValue(0) |
|||
self.internal = False |
|||
for tbox in self.tbox: |
|||
tbox.setText("0") |
|||
self.config_direction(0) |
|||
def cancel(self): |
|||
self.reset() |
|||
self.close() |
|||
def config_direction(self, i): |
|||
#evaluate the vectors corresponding to the three directions for the current view, and assign the i-th one to self.direction |
|||
self.view = self.cam.orientation.getValue() |
|||
self.view = coin.SbRotation(self.view.getValue()) |
|||
self.pos = self.cam.position.getValue() |
|||
self.pos = coin.SbVec3f(self.pos.getValue()) |
|||
up = coin.SbVec3f(0,1,0) |
|||
self.up = self.view.multVec(up) |
|||
out = coin.SbVec3f(0,0,1) |
|||
self.out = self.view.multVec(out) |
|||
u = self.up.getValue() |
|||
o = self.out.getValue() |
|||
r = (u[1]*o[2]-u[2]*o[1], u[2]*o[0]-u[0]*o[2], u[0]*o[1]-u[1]*o[0]) |
|||
self.right = coin.SbVec3f(r) |
|||
self.direction = [self.right, self.up, self.out][i] |
|||
def check(self, i): |
|||
#check if the direction of rotation has changed, if so then set previous slider & textbox to zero, and setup the new direction |
|||
if i <> self.current: |
|||
self.internal = True |
|||
self.sld[self.current].setValue(0) |
|||
self.tbox[self.current].setText("0") |
|||
self.internal = False |
|||
self.current = i |
|||
self.config_direction(i) |
|||
def rotate(self, value): |
|||
#carry out the desired rotation about self.direction |
|||
val = value*pi/180.0 |
|||
rot = coin.SbRotation(self.direction, -val) |
|||
nrot = self.view*rot |
|||
prot = rot.multVec(self.pos - self.centre) + self.centre |
|||
self.cam.orientation = nrot |
|||
self.cam.position = prot |
|||
def valueChange(self, value): |
|||
#respond to the change in value of a slider, update the corresponding text box, check for a direction change then rotate |
|||
#if the value was changed internally, ignore event. |
|||
if self.internal: |
|||
return |
|||
sender = self.sender() |
|||
for i in range(3): |
|||
if sender == self.sld[i]: |
|||
break |
|||
self.tbox[i].setText(str(value)) |
|||
self.check(i) |
|||
self.rotate(value) |
|||
def valueEntered(self): |
|||
#respond to a value being entered in a text box, updating the corresponding slider, check for direction change then rotate |
|||
sender = self.sender() |
|||
for i in range(3): |
|||
if sender == self.tbox[i]: |
|||
break |
|||
value = int(self.tbox[i].text()) |
|||
self.internal = True |
|||
self.sld[i].setValue(value) |
|||
self.internal = False |
|||
self.check(i) |
|||
self.rotate(value) |
|||
rotate = rotate_gui() |
|||
}} |
|||
{{clear}} |
|||
<translate> |
<translate> |
Revision as of 20:46, 22 October 2018
File:Text-x-python View Rotation |
Description |
---|
Macro provides a GUI to permit precise rotation of the objects in the view. Macro version: 1.0 Last modified: 2012-01-04 Author: Joe Dowsett |
Author |
Joe Dowsett |
Download |
None |
Links |
Macros recipes How to install macros How to customize toolbars |
Macro Version |
1.0 |
Date last modified |
2012-01-04 |
FreeCAD Version(s) |
None |
Default shortcut |
None |
See also |
None |
Description
This GUI allows the view to be rotated with more precision than when using the mouse. Rotation is according to axes fixed with respect to the user and not the objects, though the aim is that the objects rotate about their approximate shared centre rather than the view centre.
The GUI defaults to the top right of the screen, this behaviour can be changed by editing
Three icons are referred to to symbolise the rotation directions. A zip file containing these icons can be found here, the images should be placed in the folder containing your macros. Please feel free to contribute better ones!
Code
The lastest version of the macro is to be found at ViewRotation.FCMacro but the easiest way to install this macro is through the Addon Manager.
Option
at the end of the function 'initUI'. The first two arguments (right-300, 0) (line 91) provide the position for the top left corner of the window - my experience is that the behaviour was as intended on Ubuntu but Vista positioned the window too high and the 0 needed to be changed to ~30.
self.setGeometry(right-300, 0, 300, 150)