# -*- coding: utf-8 -*- | |
""" | |
*************************************************************************** | |
* Copyright (c) 2015 2016 2017 2018 2019 2020 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 * | |
*************************************************************************** | |
""" | |
# FCCamera 0.5 18/03/2015 28/02/2016 06/09/2016 06_13/12/2016 07_03/01/2018 08_08/01/2018 09_08/01/2018 10+11_13/01/2018 12_01/08/2019 | |
# 12.1_12/02/2020 13_2020/06/28 14_2020/10/20 15_17/12/2024 15b_19/12/2024 | |
# | |
#OS: Windows 10 build 19045 | |
#Architecture: x86_64 | |
#Version: 1.1.0dev.39240 (Git) Conda | |
#Build type: Release | |
#Branch: main | |
#Hash: f9ba94c70b139ece6ba5ffba47632d91b5c9c645 | |
#Python 3.11.10, Qt 5.15.15, Coin 4.0.3, Vtk 9.3.0, OCC 7.8.1 | |
#Locale: French/Mars (fr_MA) | |
############################################################################################################################### | |
# | |
# | |
__title__ = "FCCamera" | |
__author__ = "Mario52" | |
__url__ = "http://www.freecadweb.org/wiki/index.php?title=Macro_FCCamera" | |
__version__ = "0.15b" | |
__date__ = "2024/12/19" #YYYY/MM/DD | |
__Web__ = "https://gist.github.com/mario52a/4aa545c23b323cf68824" | |
# | |
## Icon easyw-fc method | |
## https://forum.freecadweb.org/viewtopic.php?f=9&t=24742&start=100#p363271 | |
import base64 | |
FCCamera_Axis_rotation_X_BMP=\ | |
""" | |
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 | |
""" | |
FCCamera_Axis_rotation_Y_BMP=\ | |
""" | |
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 | |
""" | |
FCCamera_Axis_rotation_Z_BMP=\ | |
""" | |
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 | |
""" | |
FCCamera_Axis_rotation_D_BMP=\ | |
""" | |
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 | |
""" | |
helpIcon = [ | |
"24 24 4 1", | |
" c None", | |
". c #016AC5", | |
"+ c #F8F8FF", | |
"@ c #FFFFFF", | |
"........................", | |
".++++++++++++++++++++++.", | |
".++++++++++++++++++++++.", | |
".++..................++.", | |
".++..................++.", | |
".++......@@@@@@......++.", | |
".++.....@@@@@@@@.....++.", | |
".++.....@@@..@@@.....++.", | |
".++.....@@....@@.....++.", | |
".++.....@@....@@.....++.", | |
".++...........@@.....++.", | |
".++..........@@@.....++.", | |
".++.........@@@......++.", | |
".++........@@@.......++.", | |
".++........@@........++.", | |
".++........@@........++.", | |
".++..................++.", | |
".++........@@........++.", | |
".++........@@........++.", | |
".++..................++.", | |
".++..................++.", | |
".++++++++++++++++++++++.", | |
".++++++++++++++++++++++.", | |
"........................"] | |
executeIcon = [ | |
"24 24 3 1", | |
" c None", | |
". c #4E9A06", | |
"+ c #000000", | |
" ", | |
" ", | |
" ", | |
" . ", | |
" .+. ", | |
" .+.+. ", | |
" .+...+. ", | |
" .+.....+. ", | |
" . .+.......+.", | |
" .+. .+.......+. ", | |
" .+.+. .+.......+. ", | |
" .+...+. .+.......+. ", | |
" .+.....+.+.......+. ", | |
".+.......+.......+. ", | |
" .+.............+. ", | |
" .+...........+. ", | |
" .+.........+. ", | |
" .+.......+. ", | |
" .+.....+. ", | |
" .+...+. ", | |
" .+.+. ", | |
" .+. ", | |
" . ", | |
" "] | |
quitIcon = [ | |
"24 24 3 1", | |
" c None", | |
". c #FFFFFF", | |
"+ c #CC0000", | |
" .... ", | |
"++++++++++....++++++++++", | |
"+.......++....++.......+", | |
"+.......++....++.......+", | |
"+.......++....++.......+", | |
"+...++++++....++++++...+", | |
"+...++++++....++++++...+", | |
"+...+++++......+++++...+", | |
"+...+++++......+++++...+", | |
"+...+++++......+++++...+", | |
"+...+++++......+++++...+", | |
"+...+++++......+++++...+", | |
"+...+++++......+++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+...++++++++++++++++...+", | |
"+......................+", | |
"+......................+", | |
"+......................+", | |
"++++++++++++++++++++++++"] | |
resetIcon = [ | |
"24 24 3 1", | |
" c None", | |
". c #3465A4", | |
"+ c #888A85", | |
" ", | |
" ........ ", | |
" .++++++++. ", | |
" .++..+....+. ..... ", | |
" .+.. .+....+. .+++. ", | |
" .+. .+....+..+.+. ", | |
" ... .+....+.+.+. ", | |
" .+....+..+. ", | |
" .+......+. ", | |
" .+.....+. ", | |
" .+....+. ", | |
" ...... .+...+. ", | |
" .++++. .++++. ", | |
" .+...+. ...... ", | |
" .+....+. ", | |
" .+.....+. ", | |
" .+......+. ", | |
" .+..+....+. ", | |
" .+.+.+....+. ... ", | |
" .+.+..+....+. .+. ", | |
" .+++. .+....+. ..+. ", | |
" ..... .+....+..++. ", | |
" .++++++++. ", | |
" ........ "] | |
DetectCamera = [ | |
"24 24 17 1", | |
" c None", | |
". c #444453", | |
"+ c #4245AE", | |
"@ c #4247D9", | |
"# c #4F4F8E", | |
"$ c #5B5A52", | |
"% c #676625", | |
"& c #6468EA", | |
"* c #7E81BC", | |
"= c #8C8B3B", | |
"- c #8183EE", | |
"; c #909074", | |
"> c #B8B859", | |
", c #B4B4DE", | |
"' c #CDCECE", | |
") c #F5F57D", | |
"! c #F8F86B", | |
" ", | |
" @@@@ @@@@ ", | |
" @---@ @---@ ", | |
" @@----@ @----@@ ", | |
" @------&@@@&------@ ", | |
" @-----&@@&@@&-----@ ", | |
" @----&@@&&&@@&----@ ", | |
" @---&@&&&&&&&@&---@ ", | |
" @&&&@#########@&&&@ ", | |
" ++#$%%%%%%%%%$#++ ", | |
" .===============. ", | |
" >>>>>>==%%%%%==>>>>>> ", | |
">>!!!!>>=$$$$$=>>!!!!>> ", | |
">!!!!!!>=$...$=>!!!!!!> ", | |
">!!!!!!>=$@@@$=>!!!!!!> ", | |
">!!!!!!>=#@-@#=>!!!!!!> ", | |
">!!!!!!>=@---@=>!!!!!!> ", | |
">!!!!!!>=-----=>!!!!!!> ", | |
">>!!!!>>=-----=>>!!!!>> ", | |
" >>>>>> +-----+ >>>>>> ", | |
" +---+ ", | |
" +-+ ", | |
" + ", | |
" "] | |
CameraToFace = [ | |
"24 24 9 1", | |
" c None", | |
". c #05268B", | |
"+ c #162567", | |
"@ c #821E25", | |
"# c #3A355C", | |
"$ c #C62921", | |
"% c #4D69A2", | |
"& c #956F83", | |
"* c #6AA4EC", | |
" ", | |
" ", | |
" ", | |
" +++++++++++++++ ", | |
" ++%%%%%%%%%%%%++ ", | |
" ++%%%%%%%%%%%%+++ ", | |
" ++++++++++++++++.+ ", | |
" +**************+.+ ", | |
" +**************+.+ ", | |
" +**************+.+ ", | |
" +**************+.+ ", | |
" +*****$$$******+.+ ", | |
" +****$$$$$*****+.+ ", | |
" +***$$$$$$$****+.+ ", | |
" +***$$$$$$$****+.+ ", | |
" +***$$$$$$$****+.+ ", | |
" +****$$$$$*****+.+ ", | |
" +***$*$$$******+.+ ", | |
" +*$$$**********+++ ", | |
" +$$************++ ", | |
" $$++++++++++++++ ", | |
" $$$ ", | |
" $$ ", | |
" "] | |
CameraToAxis = [ | |
"24 24 9 1", | |
" c None", | |
". c #FF0000", | |
"+ c #A9352E", | |
"@ c #7B624B", | |
"# c #000000", | |
"$ c #B1AAA0", | |
"% c #F3A500", | |
"& c #DEBF17", | |
"* c #ECEDE9", | |
" .. ", | |
" .. ", | |
" ###..####### ", | |
" ###&&&..&&%%%## ", | |
" ##&&&&&&&&%%%%#%# ", | |
" ###############%%# ", | |
" #&&&&&&&%%%%%%#%%# ", | |
" #&&&&&&&%%%%%%#%%# ", | |
" #&&&&&&&%%%%%%#%%# ", | |
"...#&&&&&&&%%%%%%#%%# ", | |
"...#&&&&&&.%%%%%%#%.....", | |
" #&&&&&..%%%%%%#%.....", | |
" #&&&&..%%%%%%%#%%# ", | |
" #&&&..&%%%%%%%#%%# ", | |
" #&&..&%%%%%%%%#%%# ", | |
" #&&.&&%%%%%%%%#%## ", | |
" #&&..&%%%%%%%%### ", | |
" #&&...%%%%%%%%## ", | |
" ###....######## ", | |
" .... .. ", | |
" .... .. ", | |
" .... .. ", | |
" . .. ", | |
" .. "] | |
AlignToView = [ | |
"24 24 9 1", | |
" c None", | |
". c #FF0000", | |
"+ c #000000", | |
"@ c #819803", | |
"# c #789A70", | |
"$ c #AC9134", | |
"% c #13DB00", | |
"& c #BFB1A2", | |
"* c #E2CA0B", | |
" ", | |
" + ", | |
" ++%++ ", | |
" ++%%%%%++ ", | |
" ++%%%%%%%%%++ ", | |
" +%%%%%%%%%%%%%+ ", | |
" +++%%%%%%%%%+++ ", | |
" +%%++%%%%%++%%+ ", | |
" +%%%%++%++%%%%+ ", | |
" +%%%%%%+%%$$$$$$$$$$$$$", | |
" +%%%%%%+%%$***********$", | |
" +%%%%%%+%%$***********$", | |
" +%%%%%%+%%$***********$", | |
" +%%%.%%+%%$***********$", | |
" +%%%%.%+%%$***..*..***$", | |
" +%%%%%.+%%$****...****$", | |
" ++%%%%.%%$****...****$", | |
" ++%%+..$***..*..***$", | |
" ++++ ....********$", | |
" + $***********$", | |
" $***********$", | |
" $***********$", | |
" $$$$$$$$$$$$$", | |
" "] | |
PlaneAxis = [ | |
"24 24 9 1", | |
" c None", | |
". c #CF0106", | |
"+ c #DB4244", | |
"@ c #CF5A59", | |
"# c #C47983", | |
"$ c #AD8FA3", | |
"% c #B7B3CA", | |
"& c #B1C7E2", | |
"* c #D6D3D7", | |
" .. ", | |
" .. ", | |
" .. ", | |
" &&&..&&& ", | |
" &&&&..&&&& ", | |
" &&&&&..&&&&& ", | |
" &&&&&&..&&&&&& ", | |
" &&&&&&&++&&&&&&& ", | |
" &&&&&&&&++&&&&&&&& ", | |
" &&&&&&&&++&&&&&&&& ", | |
" &&&&&&&&..&&&&&&&& ", | |
".......+++....+++.......", | |
".......+++....+++.......", | |
" &&&&&&&&..&&&&&&&& ", | |
" &&&&&&&&++&&&&&&&& ", | |
" &&&&&&&&++&&&&&&&& ", | |
" &&&&&&&++&&&&&&& ", | |
" &&&&&&..&&&&&& ", | |
" &&&&&..&&&&& ", | |
" &&&&..&&&& ", | |
" &&&..&&& ", | |
" .. ", | |
" .. ", | |
" .. "] | |
CameraPhoto = [ | |
"24 24 9 1", | |
" c None", | |
". c #161817", | |
"+ c #313332", | |
"@ c #424544", | |
"# c #515452", | |
"$ c #686B68", | |
"% c #838582", | |
"& c #A8ABA8", | |
"* c #D9DBD8", | |
" ", | |
" ", | |
" &***& ", | |
" &****% ", | |
" %&&&&# ", | |
" + ++ ", | |
" .+#$$#. ", | |
" +$$$$$$$+ ", | |
" +#$%%%%%%%%%%%%%$$@ ", | |
" %&&$$%%%*$$$$%%%%$$%+ ", | |
" +&%%$#%+$%$$$$###%$$%+ ", | |
" +%%&%%@+@#$&%$###@$$%+ ", | |
" +$###@++@#%###@####$%+ ", | |
" +$###@++@$@@....++#$$+ ", | |
" +$###@++@#+.@#..+++$%+ ", | |
" +$###@++@++.%&&@+@+#%+ ", | |
" +$###@++@++.$*&%@@+#%+ ", | |
" +$###@+@#++.+$%%##+#$+ ", | |
" +$$####++@++.@###@+++ ", | |
" .+@@+. ++@@##@++ ", | |
" +++++++ ", | |
" @@@ ", | |
" ", | |
" "] | |
CameraPhotoOk = [ | |
"24 24 9 1", | |
" c None", | |
". c #000100", | |
"+ c #161815", | |
"@ c #323331", | |
"# c #4C4E4B", | |
"$ c #686A67", | |
"% c #4B9A00", | |
"& c #898B88", | |
"* c #D8DBD7", | |
" %", | |
" %%.", | |
" %%.. ", | |
" %%..% ", | |
"% %%...% ", | |
".%% %%..%.% ", | |
"%..%% %%..%%.% ", | |
"%.%..%% %%..%%%.% ", | |
" %.%%..%%..%%%%.% ", | |
" %.%%%%..%%%%%.%&**& ", | |
" %.%%%%%%%%%.% &**& ", | |
" %.%%%%%%%.% # # ", | |
" %.%%%%%%.% @#$$#$ ", | |
" %.%%%%.% @$&&&&$ ", | |
" %.%%.%$&&&&$$&&&$$$", | |
" %.%.%&$&@$$$$##$$$#", | |
" %+%&$$#@#$$$####$#", | |
" %$###@@#$#@@@@#$#", | |
" $###@@#@@##@@@$#", | |
" $###@@#@@*&$#@##", | |
" $###@@#@+$&&#@##", | |
" $###@##@@@###@##", | |
" $$$$$$$$@###@# ", | |
" ### "] | |
import PySide | |
from PySide import (QtWidgets, QtCore, QtGui) | |
from PySide.QtWidgets import * #(QWidget, QApplication, QSlider, QGraphicsView, QGraphicsScene, QVBoxLayout, QStyle) | |
from PySide.QtGui import * #(QPainter, QColor, QIcon) | |
from PySide.QtSvg import * | |
try: | |
import webbrowser | |
except Exception: | |
None | |
import Draft, Part, FreeCAD, math, PartGui, FreeCADGui, DraftVecUtils | |
#import os, WorkingPlane | |
App = FreeCAD | |
from math import radians, degrees, sqrt, pi, sin, cos, asin | |
from decimal import * | |
from FreeCAD import Base | |
from FreeCAD import Vector | |
import pivy | |
from pivy import coin | |
#### Detect version macro ########################################### | |
global switchVesionMacroSearch#; switchVesionMacroSearch = False | |
def vesionSearch(): | |
try: | |
import urllib | |
from urllib import request | |
contentPage = request.urlopen("https://wiki.freecadweb.org/Macro_FCCamera").readlines() | |
for i in contentPage: | |
if "ctEven macro-version" in str(i): | |
versionDetect = (str(i).split(">")[1].split("\\")[0]) | |
if "ctEven macro-date" in str(i): | |
dateDetect = (str(i).split(">")[1].split("\\")[0]) | |
try: | |
if (len(versionDetect) != 0) and (len(dateDetect) != 0): | |
break | |
except Exception: | |
None | |
try: | |
if (versionDetect == __version__) and (dateDetect == __date__): | |
None | |
else: | |
msg = ("New version availlable : " + "\n" + | |
str(versionDetect) + ":" + str(dateDetect) + "\n" + | |
"You can install with AddonManager") | |
FreeCAD.Console.PrintMessage("your actual version : " + str(__version__) + " : " + str(__date__) + "\n") | |
FreeCAD.Console.PrintMessage("new version availlable : " + str(versionDetect) + " : " + str(dateDetect) + "\n") | |
diag = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, 'New Version', msg) | |
diag.setWindowModality(QtCore.Qt.ApplicationModal) | |
diag.exec_() | |
except Exception: | |
None | |
return versionDetect, dateDetect | |
except Exception: | |
None | |
switchVesionMacroSearch = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetBool("switchVesionMacroSearch") | |
if switchVesionMacroSearch == True: | |
vesionSearch() | |
#### Detect version macro ########################################### | |
global path ; path = "" | |
global pathFile ; pathFile = "" | |
global valeur ; valeur = 0.0 | |
global valeurV ; valeurV = 0.0 | |
global Rname ; Rname = ["","",""] | |
global RnameCube; RnameCube = "" | |
global RnameCompound; RnameCompound = "" | |
global datExtract; datExtract = "" | |
global positionX ; positionX = 0.0 | |
global positionY ; positionY = 0.0 | |
global positionZ ; positionZ = 0.0 | |
global vertexeS ; vertexeS = Vector(0.0,0.0,0.0) | |
global bounBoxCenter; bounBoxCenter = Vector(0.0,0.0,0.0) | |
global dim_Horizont ; dim_Horizont = 0 | |
global dim_Vertical ; dim_Vertical = 0 | |
global ori_Vertical ; ori_Vertical = 0 | |
global ori_Horizont ; ori_Horizont = 0 | |
global numberPhoto ; numberPhoto = 0.0 | |
global valueTest ; valueTest = 0.0 | |
global formatFichier; formatFichier= ".png" | |
global s ; s = "" | |
global ui ; ui = "" | |
global Nameelement2 ; Nameelement2 = "" # new selection | |
global vueView ; vueView = 0 # passe vue | |
try: | |
activeView = Gui.ActiveDocument.ActiveView | |
except Exception: | |
### Begin command Std_New | |
App.newDocument("FCCamera") | |
App.setActiveDocument("FCCamera") | |
App.ActiveDocument=App.getDocument("FCCamera") | |
Gui.ActiveDocument=Gui.getDocument("FCCamera") | |
activeView = Gui.ActiveDocument.ActiveView | |
### End command Std_New | |
global doc | |
doc = FreeCAD.ActiveDocument | |
if doc == None: | |
doc = FreeCAD.newDocument("FCCamera") # create one document | |
#### | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
dim_Horizont = ori_Horizont = mwActive.width() | |
dim_Vertical = ori_Vertical = mwActive.height() | |
except Exception: | |
dim_Horizont = ori_Horizont = mdi.width() | |
dim_Vertical = ori_Vertical = mdi.height() | |
#### | |
try: | |
_fromUtf8 = QtCore.QString.fromUtf8 | |
except AttributeError: | |
def _fromUtf8(s): | |
return s | |
try: | |
_encoding = QtGui.QApplication.UnicodeUTF8 | |
def _translate(context, text, disambig): | |
return QtGui.QApplication.translate(context, text, disambig, _encoding) | |
except AttributeError: | |
def _translate(context, text, disambig): | |
return QtGui.QApplication.translate(context, text, disambig) | |
class SelObserver: # SelObserver | |
def addSelection(self,document, object, element, position): # Selection SelObserver | |
global positionX | |
global positionY | |
global positionZ | |
global vertexeS | |
global bounBoxCenter | |
positionX = position[0] | |
positionY = position[1] | |
positionZ = position[2] | |
bounBoxCenter = Vector(0.0,0.0,0.0) | |
if (element[:4] == "Edge"): | |
vertex = FreeCAD.ActiveDocument.getObject(object).Shape.Edges[int(element[4:])-1].Vertexes | |
bounBoxCenter = FreeCAD.ActiveDocument.getObject(object).Shape.Edges[int(element[4:])-1].BoundBox.Center | |
try: | |
vertexeS = vertex[1].Point.sub(vertex[0].Point) | |
except Exception: | |
vertexeS = Vector(0.0,0.0,0.0) | |
else: | |
vertexeS = Vector(0.0,0.0,0.0) | |
try: | |
bounBoxCenter = FreeCAD.ActiveDocument.getObject(object).Shape.Edges[int(element[4:])-1].BoundBox.Center | |
except Exception: | |
bounBoxCenter = FreeCAD.Vector(positionX, positionY, positionZ) | |
def datExtract(data): | |
# return a string | |
data = str(data) | |
a = "" | |
for i in data: | |
if i in ("0123456789e.- "): | |
a+=i | |
a = a.strip(" ") | |
a = a.split(" ") | |
return a | |
def centerBoundBoxGlobal(): | |
global doc | |
doc = App.activeDocument() | |
objs0 = doc.findObjects() | |
pointMilieu = [] | |
if len(objs0) != 0: | |
xMin = yMin = zMin = 0.0 | |
xMax = yMax = zMax = 0.0 | |
for objs in objs0: | |
try: | |
if objs.ViewObject.Visibility: | |
if hasattr(objs, "Shape"): | |
s = objs.Shape | |
elif hasattr(objs, "Mesh"): # upgrade with wmayer thanks #http://forum.freecadweb.org/viewtopic.php?f=13&t=22331 | |
s = objs.Mesh | |
elif hasattr(objs, "Points"): | |
s = objs.Points | |
boundBox_ = s.BoundBox | |
extractValue = datExtract(boundBox_) | |
if float(extractValue[0]) < xMin: | |
xMin = float(extractValue[0]) | |
if float(extractValue[1]) < yMin: | |
yMin = float(extractValue[1]) | |
if float(extractValue[2]) < zMin: | |
zMin = float(extractValue[2]) | |
if float(extractValue[3]) > xMax: | |
xMax = float(extractValue[3]) | |
if float(extractValue[4]) > yMax: | |
yMax = float(extractValue[4]) | |
if float(extractValue[5]) > zMax: | |
zMax = float(extractValue[5]) | |
except Exception: | |
None | |
#### diagonale et pointMilieu | |
points=[FreeCAD.Vector(xMin, yMin, zMin),FreeCAD.Vector(xMax, yMax, zMax)] #diagonal | |
diagonal = Draft.makeWire(points,closed=False,face=False,support=None) #create diagonal line | |
try: | |
pointMilieu = diagonal.Shape.copy().discretize(3) #cut line for search center | |
except Exception: | |
None | |
doc.removeObject(diagonal.Name) | |
#Draft.makePoint(pointMilieu[1]) | |
try: | |
return pointMilieu[1] | |
except Exception: | |
return FreeCAD.Vector(0.0,0.0,0.0) | |
else: | |
return FreeCAD.Vector(0.0,0.0,0.0) | |
def To_Face_Or_To_Axis(ToFace): # 1=NormalAt 0=Axis #Align Face selected to Face or to Axis | |
global vueView | |
global Nameelement2 | |
global vertexeS | |
try: | |
FreeCAD.ActiveDocument.openTransaction("To_Face_Or_To_Axis")# memorise les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.commitTransaction() # restore les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.abortTransaction() # abandonne les actions(avec annuler restore) | |
sel = FreeCADGui.Selection.getSelection() | |
SubElement = FreeCADGui.Selection.getSelectionEx() | |
try: | |
Nameelement = SubElement[0].SubElementNames[0] | |
if Nameelement != Nameelement2: | |
vueView = 0 | |
Nameelement2 = Nameelement | |
except Exception: | |
Nameelement = "" | |
##https://forum.freecadweb.org/viewtopic.php?t=37580 | |
if ToFace == 1: # To_Face | |
if SubElement[0].TypeName == "PartDesign::Plane": | |
v = sel[0].Shape.normalAt(0,0) # NormalAt Object | |
else: | |
v = SubElement[0].SubObjects[0].normalAt(0,0) # NormalAt SubObject | |
App.Console.PrintMessage("NormalAt : ") | |
else: # To_Axis | |
try: | |
v=SubElement[0].SubObjects[0].Surface.Axis # Axis Surface | |
App.Console.PrintMessage("Surface Axis : ") | |
except Exception: | |
v=vertexeS # Axis Edges | |
App.Console.PrintMessage("Axis Edges : ") | |
if vueView == 0: | |
r=App.Rotation(App.Vector(0,0,1),v) | |
App.Console.PrintMessage("0,0,1"+"\n") | |
elif vueView == 1: | |
r=App.Rotation(App.Vector(0,0,-1),v) | |
App.Console.PrintMessage("0,0,-1"+"\n") | |
elif vueView == 2: | |
r=App.Rotation(App.Vector(0,1,0),v) | |
App.Console.PrintMessage("0,1,0"+"\n") | |
elif vueView == 3: | |
r=App.Rotation(App.Vector(0,-1,0),v) | |
App.Console.PrintMessage("0,-1,0"+"\n") | |
elif vueView == 4: | |
r=App.Rotation(App.Vector(1,0,0),v) | |
App.Console.PrintMessage("1,0,0"+"\n") | |
elif vueView == 5: | |
r=App.Rotation(App.Vector(-1,0,0),v) | |
App.Console.PrintMessage("-1,0,0"+"\n") | |
vueView = -1 | |
Gui.ActiveDocument.ActiveView.setCameraOrientation(r.Q)# | |
vueView += 1 | |
except: | |
App.Console.PrintError("Select a face"+"\n") | |
class Ui_MainWindow(object): | |
def setupUi(self, MainWindow): | |
global path | |
global pathFile | |
global valeur | |
global ori_Horizont | |
global ori_Vertical | |
global numberPhoto | |
self.window = MainWindow | |
################################################################################# | |
#path = FreeCAD.ConfigGet("AppHomePath") | |
#path = FreeCAD.ConfigGet("UserAppData") | |
#path = "your path" | |
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path | |
path = param.GetString("MacroPath","") + "/" # macro path | |
path = path.replace("\\","/") #pathFile = | |
# App.Console.PrintMessage("Path locality to FCCamera.....images.png [ " + path + " ]"+"\n") | |
################################################################################# | |
MainWindow.setObjectName(_fromUtf8("MainWindow")) | |
# MainWindow.resize(200, 625) | |
# MainWindow.move(900, 200) # deplace la fenetre | |
self.centralWidget = QtWidgets.QWidget(MainWindow) | |
self.centralWidget.setObjectName(_fromUtf8("centralWidget")) | |
self.FontImpost = "Arial" | |
# #self.xxxx.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.groupBox_00 = QtWidgets.QGroupBox() | |
#### | |
self.groupBox_001 = QtWidgets.QGroupBox() | |
self.label_02 = QtWidgets.QLabel() | |
### ---graphicsView--- | |
self.graphicsView = QtWidgets.QGraphicsView() | |
self.graphicsView.setFrameShape(QtWidgets.QFrame.StyledPanel) | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_X_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
### ---graphicsView--- | |
#### | |
self.groupBox_002 = QtWidgets.QGroupBox() | |
self.DS_Angle = QtWidgets.QDoubleSpinBox() | |
self.DS_Angle.setAlignment(QtCore.Qt.AlignCenter) | |
self.DS_Angle.setDecimals(4) | |
self.DS_Angle.setMinimum(-359.0) | |
self.DS_Angle.setMaximum(359.0) | |
self.DS_Angle.setSuffix(" degrees") | |
self.DS_Angle.setSingleStep(1.0) | |
self.DS_Angle.valueChanged.connect(self.on_DS_Angle_valueChanged) #connection DS_Angle | |
self.CB_Multiply_10 = QtWidgets.QCheckBox() | |
self.CB_Multiply_10.clicked.connect(self.on_CB_Multiply_10) #connection checkBox | |
self.label_03 = QtWidgets.QLabel() | |
self.RB_Angle_X = QtWidgets.QRadioButton() | |
self.RB_Angle_X.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.RB_Angle_X.setStyleSheet("color : #ff0000") # Color text | |
self.RB_Angle_X.setMouseTracking(True) | |
self.RB_Angle_X.setChecked(True) | |
self.RB_Angle_X.clicked.connect(self.on_RB_Angle_X_clicked) | |
self.RB_Angle_Y = QtWidgets.QRadioButton() | |
self.RB_Angle_Y.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.RB_Angle_Y.setStyleSheet("color : #008700") # Color text | |
self.RB_Angle_Y.clicked.connect(self.on_RB_Angle_Y_clicked) | |
self.RB_Angle_Z = QtWidgets.QRadioButton() | |
self.RB_Angle_Z.setStyleSheet("color : #0000ff") # Color text | |
self.RB_Angle_Z.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.RB_Angle_Z.clicked.connect(self.on_RB_Angle_Z_clicked) | |
self.RB_Direction = QtWidgets.QRadioButton() | |
self.RB_Direction.setStyleSheet("color : #000066") # Color text | |
self.RB_Direction.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.RB_Direction.clicked.connect(self.on_RB_Direction_clicked) | |
self.PB_Accept_View = QtWidgets.QPushButton() | |
self.PB_Accept_View.setIcon(QtGui.QIcon(QtGui.QPixmap(executeIcon)))# execute icone dans une variable | |
self.PB_Accept_View.clicked.connect(self.on_PB_Accept_View_clicked) | |
#### | |
self.groupBox_003 = QtWidgets.QGroupBox() | |
#self.groupBox_003.setVisible(False) | |
self.PB_Detect_Camera = QtWidgets.QPushButton() | |
self.PB_Detect_Camera.setIcon(QtGui.QIcon(QtGui.QPixmap(DetectCamera))) # DetectCamera icone dans une variable | |
self.PB_Detect_Camera.clicked.connect(self.on_PB_Detect_Camera_clicked) | |
self.label_04 = QtWidgets.QLabel() | |
self.PB_To_Face = QtWidgets.QPushButton() | |
self.PB_To_Face.setIcon(QtGui.QIcon(QtGui.QPixmap(CameraToFace))) # CameraToFace icone dans une variable | |
self.PB_To_Face.clicked.connect(self.on_PB_To_Face_clicked) # align view to face Face | |
self.PB_To_Axis = QtWidgets.QPushButton() | |
self.PB_To_Axis.setIcon(QtGui.QIcon(QtGui.QPixmap(CameraToAxis))) # CameraToAxis icone dans une variable | |
self.PB_To_Axis.clicked.connect(self.on_PB_To_Axis_clicked) # Align view to face Axis | |
self.PB_Align_O_To_View = QtWidgets.QPushButton() | |
self.PB_Align_O_To_View.setIcon(QtGui.QIcon(QtGui.QPixmap(AlignToView))) # AlignToView icone dans une variable | |
self.PB_Align_O_To_View.clicked.connect(self.on_PB_Align_O_To_View_clicked) # Align object to view | |
#### | |
self.groupBox_004 = QtWidgets.QGroupBox() | |
self.PB_Create_Plane = QtWidgets.QPushButton() | |
self.PB_Create_Plane.setIcon(QtGui.QIcon(QtGui.QPixmap(PlaneAxis))) # PlaneAxis icone dans une variable | |
self.PB_Create_Plane.clicked.connect(self.on_PB_Create_Plane_clicked) # create plane | |
self.RB_01_Plane_Point = QtWidgets.QRadioButton() | |
self.RB_01_Plane_Point.setChecked(True) | |
self.RB_02_Plane_Face = QtWidgets.QRadioButton() | |
self.RB_03_Plane_CMass = QtWidgets.QRadioButton() | |
self.RB_04_Center_BBox = QtWidgets.QRadioButton() | |
#### | |
self.groupBox_005 = QtWidgets.QGroupBox() | |
self.PB_Reset = QtWidgets.QPushButton(self.centralWidget) | |
self.PB_Reset.setIcon(QtGui.QIcon(QtGui.QPixmap(resetIcon))) # reset icone dans une variable | |
self.PB_Reset.clicked.connect(self.on_PB_Reset_clicked) # refresh | |
self.PB_Photo = QtWidgets.QPushButton() | |
self.PB_Photo.setIcon(QtGui.QIcon(QtGui.QPixmap(CameraPhoto))) # Camera icone dans une variable | |
self.PB_Photo.clicked.connect(self.on_PB_Photo_clicked) | |
self.PB_Quit = QtWidgets.QPushButton() | |
self.PB_Quit.setIcon(QtGui.QIcon(QtGui.QPixmap(quitIcon))) # quit icone dans une variable | |
self.PB_Quit.clicked.connect(self.on_PB_Quit_clicked) # quit | |
self.PB_Help = QtWidgets.QPushButton() | |
self.PB_Help.setIcon(QtGui.QIcon(QtGui.QPixmap(helpIcon))) # icone dans une variable help | |
self.PB_Help.clicked.connect(self.on_PB_Help) ### | |
#### | |
self.groupBox_00PH = QtWidgets.QGroupBox() | |
self.groupBox_00PH.setVisible(False) | |
#### | |
self.groupBox_00PH01 = QtWidgets.QGroupBox() | |
self.CBox_01_Ecran = QtWidgets.QComboBox() | |
# self.CBox_01_Ecran.setCurrentIndex(0) | |
# CBox_01_Ecran = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_01_Ecran")# | |
# print(CBox_01_Ecran) | |
# self.CBox_01_Ecran.setCurrentIndex(int(CBox_01_Ecran)) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Actual")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Icon 16 x 16")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Icon 32 x 32")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Icon 64 x 64")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Icon 128 x 128")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("CGA 320 x 200")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("QVGA 320 x 240")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("VGA 640 x 480")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("SVGA 800 x 600")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("XGA 1024 x 768")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("XGA+ 1152 x 864")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("SXGA 1280 x 1024")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("SXGA+ 1400 x 1050")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("UXGA 1600 x 1200")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("QXGA 2048 x 1536")) | |
self.CBox_01_Ecran.addItem(_fromUtf8("Free")) | |
QtCore.QObject.connect(self.CBox_01_Ecran, QtCore.SIGNAL("currentIndexChanged(QString)"), self.SIGNAL_CBox_01_Ecran_Changed) | |
self.DS_01_X = QtWidgets.QSpinBox() | |
self.DS_01_X.setMinimum(1) | |
self.DS_01_X.setMaximum(ori_Horizont) | |
self.DS_01_X.setSingleStep(1) | |
self.DS_01_X.setValue(ori_Horizont) | |
self.DS_01_X.valueChanged.connect(self.on_DS_01_X_valueChanged) #connection doubleSpinBox | |
self.label_05 = QtWidgets.QLabel() | |
self.label_05.setStyleSheet("color : #ff0000") # Color text | |
self.label_05.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.DS_02_Y = QtWidgets.QSpinBox() | |
self.DS_02_Y.setMinimum(1) | |
self.DS_02_Y.setMaximum(ori_Vertical) | |
self.DS_02_Y.setSingleStep(1) | |
self.DS_02_Y.setValue(ori_Vertical) | |
self.DS_02_Y.valueChanged.connect(self.on_DS_02_Y_valueChanged) #connection doubleSpinBox | |
self.label_06 = QtWidgets.QLabel() | |
self.label_06.setStyleSheet("color : #008700") # Color text | |
self.label_06.setFont(QtGui.QFont(self.FontImpost,weight=QtGui.QFont.Bold)) # Bold | |
self.label_07 = QtWidgets.QLabel() | |
self.PB_Photo_Adjust = QtWidgets.QPushButton() | |
self.PB_Photo_Adjust.setVisible(False) | |
# self.PB_Photo_Adjust.setIcon(QtGui.QIcon(path + "FCCamera_07.png")) | |
self.PB_Photo_Adjust.clicked.connect(self.on_PB_Photo_Adjust_clicked) | |
self.label_08 = QtWidgets.QLabel() | |
self.CBox_02_FileFormat = QtWidgets.QComboBox() | |
# CBox_02_FileFormat = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_02_FileFormat")# | |
# print(CBox_02_FileFormat) | |
# self.CBox_02_FileFormat.setCurrentIndex(int(CBox_02_FileFormat)) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("BMP *.bmp")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("ICO *.ico")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("JPEG *.jpeg")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("JPG *.jpg")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("PNG *.png")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("PPM *.ppm")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("TIF *.tif")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("TIFF *.tiff")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("XBM *.xbm")) | |
self.CBox_02_FileFormat.addItem(_fromUtf8("XPM *.xpm")) | |
#self.CBox_02_FileFormat.addItem(_fromUtf8("GIF *.gif")) | |
QtCore.QObject.connect(self.CBox_02_FileFormat, QtCore.SIGNAL("currentIndexChanged(QString)"), self.SIGNAL_CBox_02_FileFormat_Changed) | |
#### | |
self.groupBox_00PH02 = QtWidgets.QGroupBox() | |
self.RB_01_Actual = QtWidgets.QRadioButton() | |
self.RB_01_Actual.setChecked(True) | |
# self.RB_01_Actual.clicked.connect(self.on_RB_01_Actual_clicked) | |
self.RB_02_White = QtWidgets.QRadioButton() | |
# self.RB_02_White.clicked.connect(self.on_RB_02_White_clicked) | |
self.RB_03_Black = QtWidgets.QRadioButton() | |
# self.RB_03_Black.clicked.connect(self.on_RB_03_Black_clicked) | |
self.RB_04_Transparent = QtWidgets.QRadioButton() | |
# self.RB_04_Transparent.clicked.connect(self.on_RB_04_Transparent_clicked) | |
#### | |
self.groupBox_00PH03 = QtWidgets.QGroupBox() | |
self.PB_Photo_Launch = QtWidgets.QPushButton() | |
self.PB_Photo_Launch.setIcon(QtGui.QIcon(QtGui.QPixmap(CameraPhotoOk)))# execute icone dans une variable | |
self.PB_Photo_Launch.clicked.connect(self.on_PB_Photo_Launch_clicked) | |
self.PB_Photo_Reset = QtWidgets.QPushButton() | |
self.PB_Photo_Reset.setIcon(QtGui.QIcon(QtGui.QPixmap(resetIcon))) # reset icone dans une variable | |
self.PB_Photo_Reset.clicked.connect(self.on_PB_Photo_Reset_clicked) | |
self.PB_Photo_Quit = QtWidgets.QPushButton() | |
# self.PB_Photo_Quit.setIcon(QtGui.QIcon(QtGui.QPixmap(quitIcon))) # quit icone dans une variable | |
iconRotate = QtGui.QPixmap(quitIcon).transformed(QtGui.QTransform().rotate(-90), QtCore.Qt.SmoothTransformation)#Rotation | |
self.PB_Photo_Quit.setIcon(iconRotate) | |
self.PB_Photo_Quit.clicked.connect(self.on_PB_Photo_Quit_clicked) | |
##### | |
#### GridLayout begin ###### | |
self.grid0 = QtWidgets.QGridLayout(self.centralWidget) | |
self.grid0.setContentsMargins(10, 10, 10, 10) | |
self.grid0.addWidget(self.groupBox_00, 0, 0, 1, 1) | |
self.grid_00 = QtWidgets.QGridLayout(self.groupBox_00) | |
#### | |
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_001) | |
self.gridLayout_3.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 1) | |
self.grid_00.addWidget(self.groupBox_001, 0, 0, 1, 1) | |
#### | |
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_002) | |
self.gridLayout_4.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_4.addWidget(self.label_02, 0, 0, 1, 4) | |
self.gridLayout_4.addWidget(self.DS_Angle, 1, 0, 1, 3) | |
self.gridLayout_4.addWidget(self.CB_Multiply_10, 1, 3, 1, 1) | |
self.gridLayout_4.addWidget(self.label_03, 2, 0, 1, 1) | |
self.gridLayout_4.addWidget(self.RB_Angle_X, 3, 0, 1, 1) | |
self.gridLayout_4.addWidget(self.RB_Angle_Y, 3, 1, 1, 1) | |
self.gridLayout_4.addWidget(self.RB_Angle_Z, 3, 2, 1, 1) | |
self.gridLayout_4.addWidget(self.RB_Direction, 3, 3, 1, 1) | |
self.gridLayout_4.addWidget(self.PB_Accept_View, 4, 0, 1, 4) | |
self.grid_00.addWidget(self.groupBox_002, 1, 0, 1, 1) | |
#### | |
self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_003) | |
self.gridLayout_5.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_5.addWidget(self.PB_Detect_Camera, 0, 0, 1, 2) | |
self.gridLayout_5.addWidget(self.label_04, 1, 0, 1, 2) | |
self.gridLayout_5.addWidget(self.PB_To_Face, 2, 0, 1, 1) | |
self.gridLayout_5.addWidget(self.PB_To_Axis, 2, 1, 1, 1) | |
self.gridLayout_5.addWidget(self.PB_Align_O_To_View, 3, 0, 1, 2) | |
self.grid_00.addWidget(self.groupBox_003, 2, 0, 1, 1) | |
#### | |
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_004) | |
self.gridLayout_6.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_6.addWidget(self.PB_Create_Plane, 0, 0, 1, 4) | |
self.gridLayout_6.addWidget(self.RB_01_Plane_Point, 1, 0, 1, 1) | |
self.gridLayout_6.addWidget(self.RB_02_Plane_Face, 1, 1, 1, 1) | |
self.gridLayout_6.addWidget(self.RB_03_Plane_CMass, 1, 2, 1, 1) | |
self.gridLayout_6.addWidget(self.RB_04_Center_BBox, 1, 3, 1, 1) | |
self.grid_00.addWidget(self.groupBox_004, 3, 0, 1, 1) | |
#### | |
self.gridLayout_7 = QtWidgets.QGridLayout(self.groupBox_005) | |
self.gridLayout_7.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_7.addWidget(self.PB_Reset, 0, 0, 1, 1) | |
self.gridLayout_7.addWidget(self.PB_Photo, 0, 1, 1, 1) | |
self.gridLayout_7.addWidget(self.PB_Quit, 0, 2, 1, 1) | |
self.gridLayout_7.addWidget(self.PB_Help, 0, 3, 1, 1) | |
self.grid_00.addWidget(self.groupBox_005, 4, 0, 1, 1) | |
#### | |
#####photo | |
self.gridLayout_9 = QtWidgets.QGridLayout(self.groupBox_00PH) | |
self.gridLayout_11 = QtWidgets.QGridLayout(self.groupBox_00PH01) | |
self.gridLayout_11.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_11.addWidget(self.CBox_01_Ecran, 0, 0, 1, 4) | |
self.gridLayout_11.addWidget(self.DS_01_X, 1, 0, 1, 1) | |
self.gridLayout_11.addWidget(self.label_05, 1, 1, 1, 1) | |
self.gridLayout_11.addWidget(self.DS_02_Y, 1, 2, 1, 1) | |
self.gridLayout_11.addWidget(self.label_06, 1, 3, 1, 1) | |
self.gridLayout_11.addWidget(self.CBox_02_FileFormat, 2, 0, 1, 4) | |
self.gridLayout_11.addWidget(self.label_07, 3, 0, 1, 2) | |
self.gridLayout_11.addWidget(self.PB_Photo_Adjust, 3, 2, 1, 2) | |
self.gridLayout_11.addWidget(self.label_08, 4, 0, 1, 4) | |
self.gridLayout_9.addWidget(self.groupBox_00PH01, 0, 0, 1, 1) | |
#### | |
self.gridLayout_8 = QtWidgets.QGridLayout(self.groupBox_00PH02) | |
self.gridLayout_8.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_8.addWidget(self.RB_01_Actual, 0, 0, 1, 1) | |
self.gridLayout_8.addWidget(self.RB_02_White, 0, 1, 1, 1) | |
self.gridLayout_8.addWidget(self.RB_03_Black, 0, 2, 1, 1) | |
self.gridLayout_8.addWidget(self.RB_04_Transparent, 0, 3, 1, 1) | |
self.gridLayout_9.addWidget(self.groupBox_00PH02, 1, 0, 1, 1) | |
#### | |
self.gridLayout_10 = QtWidgets.QGridLayout(self.groupBox_00PH03) | |
self.gridLayout_10.setContentsMargins(10, 10, 10, 10) | |
self.gridLayout_10.addWidget(self.PB_Photo_Reset, 0, 1, 1, 1) | |
self.gridLayout_10.addWidget(self.PB_Photo_Quit, 0, 2, 1, 1) | |
self.gridLayout_10.addWidget(self.PB_Photo_Launch, 0, 3, 1, 1) | |
self.gridLayout_9.addWidget(self.groupBox_00PH03, 2, 0, 1, 1) | |
self.grid_00.addWidget(self.groupBox_00PH, 2, 0, 1, 1) | |
#### GridLayout end ###### | |
MainWindow.setCentralWidget(self.centralWidget) | |
self.retranslateUi(MainWindow) | |
QtCore.QMetaObject.connectSlotsByName(MainWindow) | |
def retranslateUi(self, MainWindow): | |
MainWindow.setWindowTitle("FCCamera") | |
MainWindow.setWindowIcon(QtGui.QIcon(path+'FCCamera_00.png')) # change l'icone de la fenetre principale | |
MainWindow.setWindowFlags(PySide.QtCore.Qt.WindowStaysOnTopHint) # PySide cette fonction met la fenetre en avant | |
_translate = QtCore.QCoreApplication.translate | |
global numberPhoto | |
global ori_Horizont | |
global ori_Vertical | |
self.groupBox_00.setTitle(_translate("MainWindow", "Version : " + __version__ + " : " + __date__) + " (rmu)") | |
self.groupBox_001.setTitle(_translate("MainWindow", "View")) | |
self.groupBox_002.setTitle(_translate("MainWindow", "Camera of Axis")) | |
#### | |
self.CB_Multiply_10.setText(_translate("MainWindow", "Step by 10")) | |
self.CB_Multiply_10.setToolTip(_translate("MainWindow", "If checked the value is Multiply by 10")) | |
self.label_02.setText(_translate("MainWindow", "Angle rotation Axis in degrees")) | |
self.DS_Angle.setToolTip(_translate("MainWindow", "Enter the angle of rotation in degrees.\n" | |
"The given angle is added to the angle of the current view")) | |
self.label_03.setText(_translate("MainWindow", "Axe of rotation")) | |
self.RB_Angle_X.setText(_translate("MainWindow", "X")) | |
self.RB_Angle_X.setToolTip(_translate("MainWindow", "Rotation of the camera on the X axis")) | |
self.RB_Angle_Y.setText(_translate("MainWindow", "Y")) | |
self.RB_Angle_Y.setToolTip(_translate("MainWindow", "Rotation of the camera on the Y axis")) | |
self.RB_Angle_Z.setText(_translate("MainWindow", "Z")) | |
self.RB_Angle_Z.setToolTip(_translate("MainWindow", "Rotation of the camera on the Z axis")) | |
self.RB_Direction.setText(_translate("MainWindow", "D")) | |
self.RB_Direction.setToolTip(_translate("MainWindow", "Rotation of the camera on the Direction axis" + "\n" | |
"to edge selected or point selected" + "\n" | |
"If the point are selected the mouse coordinates are used")) | |
self.PB_Accept_View.setText(_translate("MainWindow", "Accept the rotation")) | |
self.PB_Accept_View.setToolTip(_translate("MainWindow", "Accept the view given")) | |
#### | |
self.groupBox_003.setTitle(_translate("MainWindow", "Virtual")) | |
self.PB_Detect_Camera.setText(_translate("MainWindow", "Detect camera orientation")) | |
self.PB_Detect_Camera.setToolTip(_translate("MainWindow", "Detect the position of the camera\n" | |
" The returned value is the value provided by the function getCameraOrientation()")) | |
self.label_04.setText(_translate("MainWindow", "Align view :")) | |
self.PB_To_Face.setText(_translate("MainWindow", "To Face.")) | |
self.PB_To_Face.setToolTip(_translate("MainWindow", "Align the view to the selected face \n" | |
"Click and repeat the click for NormalAt : \n" | |
"(0,0,1) (0,0,-1) (0,1,0) (0,-1,0) (1,0,0) (-1,0,0)")) | |
self.PB_To_Axis.setText(_translate("MainWindow", "To Axis.")) | |
self.PB_To_Axis.setToolTip(_translate("MainWindow", "Align the view to Axis face selected \n" | |
"Click and repeat the click for Surface Axis : \n" | |
"(0,0,1) (0,0,-1) (0,1,0) (0,-1,0) (1,0,0) (-1,0,0)")) | |
self.PB_Align_O_To_View.setText(_translate("MainWindow", "Align Object to View")) | |
self.PB_Align_O_To_View.setToolTip(_translate("MainWindow", "Align the object selected to the actual view \n" | |
"The changed values are : Rotation Axis((X, Y, Z), Angle) \n" | |
"Same Euler angles : Yaw, Pitch, Roll \n The Translation is not modify")) | |
#### | |
self.groupBox_004.setTitle(_translate("MainWindow", "Plane")) | |
self.PB_Create_Plane.setText(_translate("MainWindow", "Create plane of view.")) | |
self.PB_Create_Plane.setToolTip(_translate("MainWindow", "A circular plane is created facing the screen to mouse click coordinates on an object \n" | |
"The radius of the plane is equal to the maximum dimension of BoundBox \n" | |
"If no object is selected, the plane is created to 0, 0, 0 coordinates with a radius of 20 mm")) | |
self.RB_01_Plane_Point.setText(_translate("MainWindow", "To Point")) | |
self.RB_01_Plane_Point.setToolTip(_translate("MainWindow", "Crate plane to Point mouse click")) | |
self.RB_02_Plane_Face.setText(_translate("MainWindow", "Center Face")) | |
self.RB_02_Plane_Face.setToolTip(_translate("MainWindow", "Crate plane to Center face")) | |
self.RB_03_Plane_CMass.setText(_translate("MainWindow", "Center Mass")) | |
self.RB_03_Plane_CMass.setToolTip(_translate("MainWindow", "Crate plane to Center mass")) | |
self.RB_04_Center_BBox.setText(_translate("MainWindow", "Center BBox")) | |
self.RB_04_Center_BBox.setToolTip(_translate("MainWindow", "Crate plane to Center bounding Box")) | |
#### | |
self.groupBox_005.setTitle(_translate("MainWindow", "Command")) | |
self.PB_Reset.setText(_translate("MainWindow", "Reset")) | |
self.PB_Reset.setToolTip(_translate("MainWindow", "Refresh alls")) | |
self.PB_Photo.setText(_translate("MainWindow", "Photo")) | |
self.PB_Photo.setToolTip(_translate("MainWindow", "Create serial photo for create animation" + "\n" | |
"Give the angle rotation desired" + "\n" | |
"Number image = 360 / Angle degrees rotation" + "\n" + "\n" | |
"Modify your window 3DView to the desirate dimension" + "\n" | |
"Click the Accept the rotation for verify if the object rotation is good")) | |
self.PB_Quit.setText(_translate("MainWindow", "Quit")) | |
self.PB_Quit.setToolTip(_translate("MainWindow", "Quit FCCamera")) | |
self.PB_Help.setText(_translate("MainWindow", "Help")) | |
self.PB_Help.setToolTip(_translate("MainWindow", "Help on line " + __version__ + " " + __date__ + " rmu")) | |
##### | |
##### Photo | |
self.groupBox_00PH.setTitle(_translate("MainWindow", "Photo")) | |
self.groupBox_00PH01.setTitle(_translate("MainWindow", "Definition")) | |
self.groupBox_00PH01.setToolTip(_translate("MainWindow", "Definition image")) | |
#### | |
self.CBox_01_Ecran.setCurrentIndex(0) | |
#CBox_01_Ecran = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_01_Ecran")# | |
#print(CBox_01_Ecran) | |
#self.CBox_01_Ecran.setCurrentIndex(int(CBox_01_Ecran)) | |
self.CBox_01_Ecran.setItemText(0 ,"Actual") | |
self.CBox_01_Ecran.setItemText(1 ,"Icon 16 x 16") | |
self.CBox_01_Ecran.setItemText(2 ,"Icon 32 x 32") | |
self.CBox_01_Ecran.setItemText(3 ,"Icon 64 x 64") | |
self.CBox_01_Ecran.setItemText(4 ,"Icon 128 x 128") | |
self.CBox_01_Ecran.setItemText(5 ,"CGA 320 x 200") | |
self.CBox_01_Ecran.setItemText(6 ,"QVGA 320 x 240") | |
self.CBox_01_Ecran.setItemText(7 ,"VGA 640 x 480") | |
self.CBox_01_Ecran.setItemText(8 ,"SVGA 800 x 600") | |
self.CBox_01_Ecran.setItemText(9 ,"XGA 1024 x 768") | |
self.CBox_01_Ecran.setItemText(10,"XGA+ 1152 x 864") | |
self.CBox_01_Ecran.setItemText(11,"SXGA 1280 x 1024") | |
self.CBox_01_Ecran.setItemText(12,"SXGA+ 1400 x 1050") | |
self.CBox_01_Ecran.setItemText(13,"UXGA 1600 x 1200") | |
self.CBox_01_Ecran.setItemText(14,"QXGA 2048 x 1536") | |
self.CBox_01_Ecran.setItemText(15,"Free") | |
#### | |
self.DS_01_X.setToolTip(_translate("MainWindow", "Value X")) | |
self.label_05.setText(_translate("MainWindow", "X")) | |
self.label_05.setToolTip(_translate("MainWindow", "Definition X image")) | |
self.DS_02_Y.setToolTip(_translate("MainWindow", "Value Y")) | |
self.label_06.setText(_translate("MainWindow", "Y")) | |
self.label_06.setToolTip(_translate("MainWindow", "Definition Y image")) | |
self.label_07.setText(_translate("MainWindow", "Number images : " + str(numberPhoto))) | |
self.label_07.setToolTip(_translate("MainWindow", "Number image theoretic")) | |
self.PB_Photo_Adjust.setText(_translate("MainWindow", "Adj.")) | |
self.PB_Photo_Adjust.setToolTip(_translate("MainWindow", "Adjust the definition on int number")) | |
self.PB_Photo_Adjust.setToolTip(_translate("MainWindow", "Adjust the number image to 360 degrees")) | |
self.label_08.setText(_translate("MainWindow", "")) | |
#### | |
self.CBox_02_FileFormat.setCurrentIndex(4) | |
#CBox_02_FileFormat = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_02_FileFormat")# | |
#self.CBox_02_FileFormat.setCurrentIndex(int(CBox_02_FileFormat)) | |
self.CBox_02_FileFormat.setItemText(0,"BMP *.bmp") | |
self.CBox_02_FileFormat.setItemText(1,"ICO *.ico") | |
self.CBox_02_FileFormat.setItemText(2,"JPEG *.jpeg") | |
self.CBox_02_FileFormat.setItemText(3,"JPG *.jpg") | |
self.CBox_02_FileFormat.setItemText(4,"PNG *.png") | |
self.CBox_02_FileFormat.setItemText(5,"PPM *.ppm") | |
self.CBox_02_FileFormat.setItemText(6,"TIF *.tif") | |
self.CBox_02_FileFormat.setItemText(7,"TIFF *.tiff") | |
self.CBox_02_FileFormat.setItemText(8,"XBM *.xbm") | |
self.CBox_02_FileFormat.setItemText(9,"XPM *.xpm") | |
#self.CBox_02_FileFormat.setItemText(10,"GIF *.gif") | |
#### | |
self.groupBox_00PH02.setTitle("BackGround image") | |
self.groupBox_00PH02.setToolTip(_translate("MainWindow", "Choice of property backGround image" + "\n" | |
"It is possible that the backGround does not appear in the desired color" + "\n" | |
"in this case do a test in FreeCAD :" + "\n" | |
"Menu > Tools > Save picture > Extended > Image properties")) | |
self.RB_01_Actual.setText(_translate("MainWindow", "Current")) | |
self.RB_01_Actual.setToolTip(_translate("MainWindow", "BackGround image in Actual color")) | |
self.RB_02_White.setText(_translate("MainWindow", "White")) | |
self.RB_02_White.setToolTip(_translate("MainWindow", "BackGround image in White")) | |
self.RB_03_Black.setText(_translate("MainWindow", "Black")) | |
self.RB_03_Black.setToolTip(_translate("MainWindow", "BackGround image in Black")) | |
self.RB_04_Transparent.setText(_translate("MainWindow", "Transparent")) | |
self.RB_04_Transparent.setToolTip(_translate("MainWindow", "BackGround image in Transparent")) | |
#### | |
self.groupBox_00PH03.setTitle(_translate("MainWindow", "Command photo")) | |
self.PB_Photo_Launch.setText(_translate("MainWindow", "Launch")) | |
self.PB_Photo_Launch.setToolTip(_translate("MainWindow", "Launch the creation files")) | |
self.PB_Photo_Reset.setText(_translate("MainWindow", "Reset")) | |
self.PB_Photo_Reset.setToolTip(_translate("MainWindow", "Refresh alls")) | |
self.PB_Photo_Quit.setText(_translate("MainWindow", "Return")) | |
self.PB_Photo_Quit.setToolTip(_translate("MainWindow", "Quit the photo panel")) | |
def on_RB_Angle_X_clicked(self): # X | |
# App.Console.PrintMessage("X"+"\n") | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_X_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
def on_RB_Angle_Y_clicked(self): # Y | |
# App.Console.PrintMessage("Y"+"\n") | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_Y_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
def on_RB_Angle_Z_clicked(self): # Z | |
# App.Console.PrintMessage("Z"+"\n") | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_Z_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
def on_RB_Direction_clicked(self): # D | |
# App.Console.PrintMessage("D"+"\n") | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_D_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
def on_DS_Angle_valueChanged(self,value): # connection DS_Angle value donnee en degres | |
global valeur | |
global numberPhoto | |
global valueTest | |
valeur = 0.0 | |
valeur = math.radians(value) # valeur en degres convertie en radian | |
self.DS_Angle.setStyleSheet("color : Base") | |
self.label_07.setStyleSheet("color : Base") | |
try: # section value for angle photo | |
numberPhoto = 360.0 / value | |
if abs(float(360.0 / value)) - int(abs(numberPhoto)) != 0.0: | |
self.PB_Photo_Adjust.setVisible(True) | |
self.label_08.setVisible(True) | |
numberPhoto = (abs(360.0 /value)) | |
self.label_07.setStyleSheet("color : Red") | |
self.PB_Photo_Adjust.setStyleSheet("background-color : #ff0000") | |
valueTest = abs(int(value)) | |
while ((value + valueTest) < (361 + value)) and ((value - valueTest) < (361 + value)): | |
if abs(float(360.0 / valueTest)) - int(abs(float(360.0 / valueTest))) == 0.0: | |
if self.DS_Angle.value() < 0: | |
self.label_08.setText("Ideal angle : " + str(-valueTest) + " = " + str(abs(int(360.0 / valueTest))) + " images") | |
else: | |
self.label_08.setText("Ideal angle : " + str(valueTest) + " = " + str(abs(int(360.0 / valueTest))) + " images") | |
self.label_08.setStyleSheet("color : #008700") | |
break | |
if self.DS_Angle.value() < 0: | |
valueTest -= 1 | |
else: | |
valueTest += 1 | |
FreeCADGui.updateGui() | |
self.PB_Photo_Adjust.setToolTip(u"Click to adjust the number images to 360 degrees" + "\n" | |
u"detected " + str(numberPhoto) + " = " + str(int(numberPhoto)) + " images" + "\n" | |
u"ideal choice angle : " + str(valueTest) + " degrees = " + str(abs(int(360.0 / valueTest))) + " images" + "\n" ) | |
else: | |
numberPhoto = int(abs(360.0 / value)) | |
self.label_07.setStyleSheet("color : Base") | |
self.label_08.setVisible(False) | |
self.label_08.setText("") | |
self.PB_Photo_Adjust.setVisible(False) | |
self.PB_Photo_Adjust.setStyleSheet("color : Base") | |
self.PB_Photo_Adjust.setToolTip(u"Adjust the number image to 360 degrees") | |
except Exception: | |
numberPhoto = 0 | |
self.PB_Photo.setToolTip(u"Create serial photo for create animation" + "\n" | |
u"Give the angle rotation desired" + "\n" | |
u"Number image = 360 / " + str(math.degrees(valeur)) + " = " + str(numberPhoto)) | |
self.label_07.setText("Number image : " + str(numberPhoto)) | |
def on_CB_Multiply_10(self): | |
if self.CB_Multiply_10.isChecked(): | |
self.DS_Angle.setSingleStep(10.0) | |
else: | |
self.DS_Angle.setSingleStep(1.0) | |
def on_PB_Detect_Camera_clicked(self): # detection Orientation camera | |
global vertexeS | |
try: | |
plan = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation() | |
cam=Gui.ActiveDocument.ActiveView.getCameraNode() | |
App.Console.PrintMessage("___Camera_Detection_____________________"+"\n") | |
App.Console.PrintMessage("position : " + str(cam.position.getValue().getValue()) + "\n") | |
first = FreeCAD.Vector(cam.position.getValue().getValue()) | |
distance_3DView_to_Axis = math.sqrt(first.x*first.x + first.y*first.y + first.z*first.z) | |
App.Console.PrintMessage(" : (position = Distance Center 3DView to Axis base = " + str(distance_3DView_to_Axis) + ")" + "\n") | |
App.Console.PrintMessage("orientation : " + str(FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().Axis)+" , "+str(FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().Angle) + "\n") | |
App.Console.PrintMessage("nearDistance : " + str(cam.nearDistance.getValue()) + "\n") | |
App.Console.PrintMessage("farDistance : " + str(cam.farDistance.getValue()) + "\n") | |
App.Console.PrintMessage("aspectRatio : " + str(cam.aspectRatio.getValue()) + "\n") | |
App.Console.PrintMessage("focalDistance : " + str(cam.focalDistance.getValue()) + "\n") | |
App.Console.PrintMessage("height : " + str(cam.height.getValue()) + "\n" + "\n") | |
App.Console.PrintMessage("___Camera_Orientation____________________"+"\n") | |
App.Console.PrintMessage("Radians XYZ Q : " + str(plan)+"\n") | |
extractValue = datExtract(plan) | |
xP = float(extractValue[0]) | |
yP = float(extractValue[1]) | |
zP = float(extractValue[2]) | |
qP = float(extractValue[3]) | |
App.Console.PrintMessage("Degrees XYZ : " + str(degrees(xP)) + " , " +str(degrees(yP)) + " , " + str(degrees(zP)) +"\n") | |
App.Console.PrintMessage("Degrees Q : " + str(degrees(qP)) +"\n"+"\n") | |
App.Console.PrintMessage("Radians Axis.xyz A : " + str(plan.Axis) + " , " + str(plan.Angle) +"\n") | |
App.Console.PrintMessage("Degrees Axis.x : " + str(degrees(plan.Axis.x)) +"\n") | |
App.Console.PrintMessage("Degrees Axis.y : " + str(degrees(plan.Axis.y)) +"\n") | |
App.Console.PrintMessage("Degrees Axis.z : " + str(degrees(plan.Axis.z)) +"\n") | |
App.Console.PrintMessage("Degrees Angle : " + str(degrees(plan.Angle)) +"\n") | |
#http://forum.freecadweb.org/viewtopic.php?f=13&t=14213 | |
App.Console.PrintMessage("Direction : " + str(cam.orientation.getValue().multVec(coin.SbVec3f(0,0,-1)).getValue()) + "\n") | |
if (vertexeS[0] + vertexeS[1] + vertexeS[2]) != 0.0: | |
App.Console.PrintMessage("Direction edge : " + str(vertexeS) + "\n") | |
App.Console.PrintMessage("___FCCamera______________________________"+"\n\n") | |
App.ActiveDocument.recompute() | |
except Exception: | |
App.Console.PrintError("Not Document open" + "\n") | |
def on_PB_Accept_View_clicked(self): # Accept Rotation Camera to Axis | |
global valeur | |
global vertexeS | |
global ori_Horizont | |
global ori_Vertical | |
global bounBoxCenter | |
if (valeur != 0): | |
Xv = 0.0; Yv = 0.0; Zv = 0.0 | |
try: | |
FreeCAD.ActiveDocument.openTransaction("Accept_View") #str(valeur)) # memorise les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.commitTransaction() # restore les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.abortTransaction() # abandonne les actions(avec annuler restore) | |
activeView = Gui.ActiveDocument.ActiveView | |
cam = Gui.ActiveDocument.ActiveView.getCameraNode() | |
rot = coin.SbRotation() | |
if self.RB_Direction.isChecked(): | |
cam.position.setValue(FreeCAD.Vector(bounBoxCenter)) # boundBox edge selected | |
else: | |
# activeView.fitAll() # boundBox all center | |
cam.position.setValue(centerBoundBoxGlobal()) # boundBox all center calculated | |
##### | |
if self.RB_Angle_X.isChecked(): | |
Xv = 1.0 | |
App.Console.PrintMessage("(X ") | |
else: | |
App.Console.PrintMessage("(- ") | |
if self.RB_Angle_Y.isChecked(): | |
Yv = 1.0 | |
App.Console.PrintMessage("Y ") | |
else: | |
App.Console.PrintMessage("- ") | |
if self.RB_Angle_Z.isChecked(): | |
Zv = 1.0 | |
App.Console.PrintMessage("Z ") | |
else: | |
App.Console.PrintMessage("- ") | |
if self.RB_Direction.isChecked(): | |
if (vertexeS[0] + vertexeS[1] + vertexeS[2]) != 0.0: | |
Xv = vertexeS[0] | |
Yv = vertexeS[1] | |
Zv = vertexeS[2] | |
App.Console.PrintMessage("D)" + "\n") | |
else: | |
Xv = bounBoxCenter[0] | |
Yv = bounBoxCenter[1] | |
Zv = bounBoxCenter[2] | |
if (Xv + Yv + Zv) == 0.0: | |
App.Console.PrintMessage("!)" + "\n") | |
App.Console.PrintError("Not axis selected (edge) for rotation" + "\n" | |
"or Direction is nul" + "\n") | |
Gui.updateGui() | |
else: | |
App.Console.PrintMessage("-) " + "\n") | |
##### | |
rot.setValue(coin.SbVec3f(Xv,Yv,Zv),valeur) | |
nrot = cam.orientation.getValue() * rot | |
cam.orientation = nrot | |
App.Console.PrintMessage(str(valeur)+" rad. , "+str(math.degrees(valeur))+" deg."+"\n") | |
App.Console.PrintMessage("FCCamera_________________________________"+"\n\n") | |
except Exception: | |
App.Console.PrintError("Not Document open"+"\n") | |
else: | |
App.Console.PrintError("Value angle egal zero select one Value"+"\n") | |
self.DS_Angle.setStyleSheet("color : #ff0000") | |
#### photo ################################################ | |
def SIGNAL_CBox_01_Ecran_Changed(self,text): | |
global dim_Horizont | |
global dim_Vertical | |
global ori_Horizont | |
global ori_Vertical | |
if text == "Actual": | |
dim_Horizont = ori_Horizont | |
dim_Vertical = ori_Vertical | |
if text == "Icon 16 x 16": | |
dim_Horizont = 16 | |
dim_Vertical = 16 | |
elif text == "Icon 32 x 32": | |
dim_Horizont = 32 | |
dim_Vertical = 32 | |
elif text == "Icon 64 x 64": | |
dim_Horizont = 64 | |
dim_Vertical = 64 | |
elif text == "Icon 128 x 128": | |
dim_Horizont = 128 | |
dim_Vertical = 128 | |
elif text == "CGA 320 x 200": | |
dim_Horizont = 320 | |
dim_Vertical = 200 | |
elif text == "QVGA 320 x 240": | |
dim_Horizont = 320 | |
dim_Vertical = 240 | |
elif text == "VGA 640 x 480": | |
dim_Horizont = 640 | |
dim_Vertical = 480 | |
elif text == "SVGA 800 x 600": | |
dim_Horizont = 800 | |
dim_Vertical = 600 | |
elif text == "XGA 1024 x 768": | |
dim_Horizont = 1024 | |
dim_Vertical = 768 | |
elif text == "XGA+ 1152 x 864": | |
dim_Horizont = 1152 | |
dim_Vertical = 864 | |
elif text == "SXGA 1280 x 1024": | |
dim_Horizont = 1280 | |
dim_Vertical = 1024 | |
elif text == "SXGA+ 1400 x 1050": | |
dim_Horizont = 1400 | |
dim_Vertical = 1050 | |
elif text == "UXGA 1600 x 1200": | |
dim_Horizont = 1600 | |
dim_Vertical = 1200 | |
elif text == "QXGA 2048 x 1536": | |
dim_Horizont = 2048 | |
dim_Vertical = 1536 | |
elif text == "Free": | |
None | |
self.DS_01_X.setValue(dim_Horizont) | |
self.DS_02_Y.setValue(dim_Vertical) | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: # FC: 1.1.0Dev | |
mwActive.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mwActive.tileSubWindows() | |
mwActive.showFullScreen() | |
#print("mwActive") | |
except Exception: # FC: 1.0.0 | |
mdi.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mdi.tileSubWindows() | |
mdi.showFullScreen() | |
#print("mdi") | |
def SIGNAL_CBox_02_FileFormat_Changed(self,text): | |
global formatFichier | |
if text == "BMP *.bmp": | |
formatFichier = ".bmp" | |
elif text == "ICO *.ico": | |
formatFichier = ".ico" | |
elif text == "JPEG *.jpeg": | |
formatFichier = ".jpeg" | |
elif text == "JPG *.jpg": | |
formatFichier = ".jpg" | |
elif text == "PNG *.png": | |
formatFichier = ".png" | |
elif text == "PPM *.ppm": | |
formatFichier = ".ppm" | |
elif text == "TIF *.tif": | |
formatFichier = ".tif" | |
elif text == "TIFF *.tiff": | |
formatFichier = ".tiff" | |
elif text == "XBM *.xbm": | |
formatFichier = ".xbm" | |
elif text == "XPM *.xpm": | |
formatFichier = ".xpm" | |
# elif text == "GIF .gif": | |
# formatFichier = "*.gif" | |
def on_DS_01_X_valueChanged(self, value): | |
global dim_Horizont | |
global dim_Vertical | |
dim_Horizont = value | |
self.DS_01_X.setValue(dim_Horizont) | |
#self.CBox_01_Ecran.setCurrentIndex(15) | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
mwActive.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mwActive.tileSubWindows() | |
except Exception: | |
mdi.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mdi.tileSubWindows() | |
def on_DS_02_Y_valueChanged(self, value): | |
global dim_Horizont | |
global dim_Vertical | |
dim_Vertical = value | |
self.DS_02_Y.setValue(dim_Vertical) | |
#self.CBox_01_Ecran.setCurrentIndex(15) | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
mwActive.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mwActive.tileSubWindows() | |
except Exception: | |
mdi.setGeometry(0, 0, dim_Horizont, dim_Vertical) | |
#mdi.tileSubWindows() | |
def on_PB_Photo_Launch_clicked(self): | |
global pathFile | |
global dim_Horizont | |
global dim_Vertical | |
global formatFichier | |
global valeur | |
if (valeur != 0): | |
SaveName, Filter = PySide.QtWidgets.QFileDialog.getSaveFileName(None, "Save a files ", pathFile, "*" + formatFichier) # PySide | |
if SaveName == "": | |
App.Console.PrintMessage("Process aborted" + "\n") | |
else: | |
pathFile = SaveName[:SaveName.rfind("/") + 1] | |
App.Console.PrintMessage("Registration of " + SaveName[:-4] + "_Animate_..." + "\n") | |
SaveName = SaveName[:-4] | |
try: | |
Xv = 0.0;Yv = 0.0;Zv = 0.0 | |
##### | |
if self.RB_Angle_X.isChecked(): | |
Xv = 1.0 | |
elif self.RB_Angle_Y.isChecked(): | |
Yv = 1.0 | |
elif self.RB_Angle_Z.isChecked(): | |
Zv = 1.0 | |
elif self.RB_Direction.isChecked(): | |
if (vertexeS[0] + vertexeS[1] + vertexeS[2]) != 0.0: | |
Xv = vertexeS[0] | |
Yv = vertexeS[1] | |
Zv = vertexeS[2] | |
else: | |
App.Console.PrintError("Not axis selected (edge) for rotation" + "\n" | |
"or Direction is nul" + "\n") | |
##### | |
if (Xv + Yv + Zv) != 0.0: | |
try: | |
fileCount = 0 | |
activeView = Gui.ActiveDocument.ActiveView | |
cam = Gui.ActiveDocument.ActiveView.getCameraNode() | |
for i in range(int(360.0 / abs(math.degrees(valeur)))): | |
Gui.updateGui() | |
if self.RB_Direction.isChecked(): | |
cam.position.setValue(FreeCAD.Vector(bounBoxCenter)) # boundBox edge selected | |
else: | |
#activeView.fitAll() # boundBox all center | |
cam.position.setValue(centerBoundBoxGlobal()) # boundBox all center calculated | |
cam = Gui.ActiveDocument.ActiveView.getCameraNode() | |
rot = coin.SbRotation() | |
rot.setValue(coin.SbVec3f(Xv,Yv,Zv),valeur) | |
nrot = cam.orientation.getValue() * rot | |
cam.orientation = nrot | |
fileCount += 1 | |
if self.RB_01_Actual.isChecked(): | |
fileName = SaveName + "_Animate_" + '%03d_%03d' % (fileCount, math.degrees(valeur)*fileCount) + "_Cu" + formatFichier | |
activeView.saveImage(fileName, dim_Horizont, dim_Vertical, "Current") | |
elif self.RB_02_White.isChecked(): | |
fileName = SaveName + "_Animate_" + '%03d_%03d' % (fileCount, math.degrees(valeur)*fileCount) + "_Wh" + formatFichier | |
activeView.saveImage(fileName, dim_Horizont, dim_Vertical, "White") | |
elif self.RB_03_Black.isChecked(): | |
fileName = SaveName + "_Animate_" + '%03d_%03d' % (fileCount, math.degrees(valeur)*fileCount) + "_Bl" + formatFichier | |
activeView.saveImage(fileName, dim_Horizont, dim_Vertical, "Black") | |
elif self.RB_04_Transparent.isChecked(): | |
fileName = SaveName + "_Animate_" + '%03d_%03d' % (fileCount, math.degrees(valeur)*fileCount) + "_Tr" + formatFichier | |
activeView.saveImage(fileName, dim_Horizont, dim_Vertical, "Transparent") | |
#App.Console.PrintMessage(fileName + "\n") | |
except Exception: | |
App.Console.PrintError("Error Creation File"+"\n") | |
App.Console.PrintMessage("End photos"+"\n") | |
except Exception: # if error detected to write | |
App.Console.PrintError("Error write file "+SaveName+"\n") # detect error ... display the text in red (PrintError) | |
else: | |
App.Console.PrintError("Give angle value for rotation"+"\n") | |
App.Console.PrintMessage("(Actual 3Dview = X " + str(dim_Horizont) + ", Y " + str(dim_Vertical) + ") " + "\n") | |
self.DS_Angle.setStyleSheet("color : #ff0000") | |
def on_PB_Photo_Adjust_clicked(self): | |
global valueTest | |
if self.DS_Angle.value() < 0: | |
self.DS_Angle.setValue(-valueTest) | |
else: | |
self.DS_Angle.setValue(valueTest) | |
self.PB_Photo_Adjust.setVisible(False) | |
self.label_08.setVisible(False) | |
self.label_08.setText("") | |
# self.label_08.setStyleSheet("color : Base") | |
def on_PB_Photo_Quit_clicked(self): | |
global ori_Horizont | |
global ori_Vertical | |
self.PB_Photo.setText("Photo") | |
self.groupBox_00PH.setVisible(False) | |
self.groupBox_003.setVisible(True) | |
self.groupBox_004.setVisible(True) | |
self.groupBox_005.setVisible(True) | |
# self.CBox_02_FileFormat.setCurrentIndex(4) | |
# self.CBox_01_Ecran.setCurrentIndex(0) | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
mwActive.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mwActive.tileSubWindows() | |
except Exception: | |
mdi.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mdi.tileSubWindows() | |
Gui.SendMsgToActiveView("ViewFit") | |
def on_PB_Photo_Reset_clicked(self): # Reset photo | |
global ui | |
ui.on_PB_Reset_clicked() | |
def on_PB_Photo_clicked(self): # Create photo | |
global ui | |
global valeur | |
global ori_Horizont | |
global ori_Vertical | |
global dim_Horizont | |
global dim_Vertical | |
global numberPhoto | |
try: | |
self.groupBox_003.setVisible(False) | |
self.groupBox_004.setVisible(False) | |
self.groupBox_005.setVisible(False) | |
self.groupBox_00PH.setVisible(True) | |
self.PB_Photo.setText("Reset") | |
except Exception: | |
App.Console.PrintError("Not Document open" + "\n") | |
#### photo ############################################################# | |
def on_PB_Align_O_To_View_clicked(self): #Align and Fix Object to View | |
FreeCAD.ActiveDocument.openTransaction("Align_O_To_View")# memorise les actions (avec annuler restore) | |
sel = FreeCADGui.Selection.getSelection() | |
if (len(sel)==0): | |
App.Console.PrintError("Select one object"+"\n") | |
else: | |
Nameelement = sel[0].Name | |
App.Console.PrintMessage(str(Nameelement)+"\n") | |
pl = FreeCAD.Placement() | |
pl.Rotation = Gui.ActiveDocument.ActiveView.getCameraOrientation() | |
pl.Base = sel[0].Placement.Base | |
App.ActiveDocument.getObject(Nameelement).Placement=pl | |
def on_PB_Create_Plane_clicked(self): # Create plane | |
global doc | |
global positionX # create plans coordinate mouse | |
global positionY | |
global positionZ | |
FreeCAD.ActiveDocument.openTransaction("FCC_FCPlane") # memorise les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.commitTransaction() # restore les actions (avec annuler restore) | |
#FreeCAD.ActiveDocument.abortTransaction() # abandonne les actions(avec annuler restore) | |
rayon = 20 # Radius of plane | |
sel = FreeCADGui.Selection.getSelection() | |
selEx = FreeCADGui.Selection.getSelectionEx() | |
objs = [selobj.Object for selobj in selEx] | |
if len(objs) != 0.0: # radius plane = > BounBox length | |
s = objs[0].Shape | |
boundBox_ = s.BoundBox | |
boundBoxLX = boundBox_.XLength | |
boundBoxLY = boundBox_.YLength | |
boundBoxLZ = boundBox_.ZLength | |
rayon = boundBoxLX | |
if rayon < boundBoxLY: | |
rayon = boundBoxLY | |
elif rayon < boundBoxLZ: | |
rayon = boundBoxLZ | |
if self.RB_01_Plane_Point.isChecked(): # Point mouse | |
None | |
elif self.RB_02_Plane_Face.isChecked(): # Face, Wire BoundBox Center | |
positionX = selEx[0].SubObjects[0].BoundBox.Center.x | |
positionY = selEx[0].SubObjects[0].BoundBox.Center.y | |
positionZ = selEx[0].SubObjects[0].BoundBox.Center.z | |
elif self.RB_03_Plane_CMass.isChecked(): # Center O fMass | |
positionX = sel[0].Shape.CenterOfMass.x | |
positionY = sel[0].Shape.CenterOfMass.y | |
positionZ = sel[0].Shape.CenterOfMass.z | |
elif self.RB_04_Center_BBox.isChecked(): # BoundBox Center | |
positionX = sel[0].Shape.BoundBox.Center.x | |
positionY = sel[0].Shape.BoundBox.Center.y | |
positionZ = sel[0].Shape.BoundBox.Center.z | |
if len(sel) == 0: | |
boundBoxLX = rayon | |
try: | |
doc = FreeCAD.ActiveDocument | |
radiusP = rayon # Radius of plane | |
FcPlane = doc.addObject("App::DocumentObjectGroup","FcPlane") | |
plan = Gui.ActiveDocument.ActiveView.getCameraOrientation() | |
App.Console.PrintMessage("\n"+"Create plane radius : " + str(radiusP) + " mm)"+"\n") | |
App.Console.PrintMessage("Camera Orientation : " + str(plan)+"\n") | |
App.Console.PrintMessage("Point position : " + str(positionX)+" "+str(positionY)+" "+str(positionZ)+"\n") | |
App.Console.PrintMessage("____________________"+"\n") | |
extractValue = datExtract(plan) | |
xP = float(extractValue[0]) | |
yP = float(extractValue[1]) | |
zP = float(extractValue[2]) | |
qP = float(extractValue[3]) | |
pl = FreeCAD.Placement() | |
pl.Rotation.Q = (xP,yP,zP,qP) # rotation of object | |
pl.Base = FreeCAD.Vector(positionX,positionY,positionZ) # here coordinates XYZ of plan | |
#create axis | |
points=[FreeCAD.Vector(0.0,0.0,0.0),FreeCAD.Vector(0.0,0.0,boundBoxLX * 3.0)] | |
centerX = Draft.makeWire(points,closed=False,face=False,support=None) | |
centerX.Placement = pl | |
centerX.Placement.Rotation = centerX.Placement.Rotation.multiply(App.Rotation(0,90,0)) | |
centerX.Placement = centerX.Placement.multiply(App.Placement(App.Vector(0.0,0.0,-float(boundBoxLX * 3.0)/2.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0))) | |
centerX.ViewObject.LineColor = (1.0,1.0,1.0) | |
centerX.ViewObject.LineWidth = 1.0 | |
centerX.ViewObject.DrawStyle = str("Dashdot") | |
centerX.Label = str("Axis White PlaneX") | |
FcPlane.addObject(centerX) | |
points=[FreeCAD.Vector(0.0,0.0,0.0),FreeCAD.Vector(0.0,0.0,boundBoxLX * 3.0)] | |
centerY = Draft.makeWire(points,closed=False,face=False,support=None) | |
centerY.Placement = pl | |
centerY.Placement.Rotation = centerY.Placement.Rotation.multiply(App.Rotation(0,90,90)) | |
centerY.Placement = centerY.Placement.multiply(App.Placement(App.Vector(0.0,0.0,-float(boundBoxLX * 3.0)/2.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0))) | |
centerY.ViewObject.LineColor = (1.0,1.0,1.0) | |
centerY.ViewObject.LineWidth = 1.0 | |
centerY.ViewObject.DrawStyle = str("Dashdot") | |
centerY.Label = str("Axis White PlaneY") | |
FcPlane.addObject(centerY) | |
cercle = Draft.makeCircle(radius=radiusP, placement=pl, face=True, support=None) | |
Rnameplane = App.ActiveDocument.ActiveObject.Name | |
App.ActiveDocument.ActiveObject.Label = "PlaneC" | |
FreeCAD.ActiveDocument.getObject(Rnameplane).MakeFace = True | |
FreeCADGui.ActiveDocument.getObject(Rnameplane).LineColor = (1.0,0.0,0.0) | |
FreeCADGui.ActiveDocument.getObject(Rnameplane).ShapeColor = (0.0,0.66666669,1.0) | |
FreeCADGui.ActiveDocument.getObject(Rnameplane).Transparency = 80 | |
FcPlane.addObject(cercle) # contener character | |
FreeCAD.ActiveDocument.recompute() | |
positionX = 0.0 | |
positionY = 0.0 | |
positionZ = 0.0 | |
except Exception: | |
App.Console.PrintError("Not Document open" + "\n") | |
def on_PB_To_Face_clicked(self): # view to face selected Face | |
To_Face_Or_To_Axis(1) | |
def on_PB_To_Axis_clicked(self): # view to face selected Axis | |
To_Face_Or_To_Axis(0) | |
def on_PB_Reset_clicked(self): # Refresh | |
global valeur | |
global positionX | |
global positionY | |
global positionZ | |
global vueView | |
global path | |
global fileCount | |
global numberPhoto | |
global ori_Horizont | |
global ori_Vertical | |
try: | |
Gui.ActiveDocument.ActiveView.viewTop() | |
Gui.SendMsgToActiveView("ViewFit") | |
valeur = 0.0 | |
fileCount = 0 | |
self.DS_Angle.setProperty("value", 0.0) | |
positionX = 0.0 | |
positionY = 0.0 | |
positionZ = 0.0 | |
vueView = 0 | |
self.CB_Multiply_10.setChecked(False) | |
self.DS_Angle.setSingleStep(1.0) | |
self.RB_Angle_X.setChecked(True) | |
pic = QtGui.QPixmap() | |
pic.loadFromData(base64.b64decode(FCCamera_Axis_rotation_X_BMP)) | |
self.scene = QtWidgets.QGraphicsScene() | |
self.scene.addPixmap(QtGui.QPixmap(pic)) | |
self.graphicsView.setScene(ui.scene) | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
mwActive.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mwActive.tileSubWindows() | |
except Exception: | |
mdi.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mdi.tileSubWindows() | |
self.CBox_01_Ecran.setCurrentIndex(0) | |
self.DS_01_X.setValue(ori_Horizont) | |
self.DS_02_Y.setValue(ori_Vertical) | |
centerBoundBoxGlobal() | |
self.RB_01_Plane_Point.setChecked(True) | |
self.RB_01_Actual.setChecked(True) | |
App.Console.PrintMessage("Refresh (3Dview = X " + str(ori_Horizont) + ", Y " + str(ori_Vertical) + ") " + "\n") | |
numberPhoto = 0 | |
self.label_07.setText("Number image : " + str(numberPhoto)) | |
except Exception: | |
App.Console.PrintError("Not Document open" + "\n") | |
def on_PB_Quit_clicked(self): # quit | |
global s | |
global ori_Horizont | |
global ori_Vertical | |
global pathFile | |
global switchVesionMacroSearch | |
activeView = Gui.ActiveDocument.ActiveView | |
mainWindow = FreeCADGui.getMainWindow() | |
mdi = mainWindow.findChild(QtWidgets.QMdiArea) | |
mwActive = mdi.activeSubWindow() | |
try: | |
#mwActive.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mwActive.resize(ori_Horizont, ori_Vertical) | |
mwActive.showFullScreen() | |
except Exception: | |
#mdi.setGeometry(0, 0, ori_Horizont, ori_Vertical) | |
#mdi.resize(ori_Horizont, ori_Vertical) | |
mdi.showFullScreen() | |
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetBool("switchVesionMacroSearch", switchVesionMacroSearch) | |
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetString("setPathFile", pathFile)# | |
#FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetInt("CBox_01_Ecran", self.CBox_01_Ecran.currentIndex())# | |
#FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetInt("CBox_02_FileFormat", self.CBox_02_FileFormat.currentIndex())# | |
Gui.SendMsgToActiveView("ViewFit") | |
App.Console.PrintMessage("Fin FCCamera" + "\n") | |
FreeCADGui.Selection.removeObserver(s) # desinstalle la fonction residente | |
self.window.close() | |
def on_PB_Help(self): # | |
webbrowser.open("http://www.freecadweb.org/wiki/index.php?title=Macro_FCCamera") | |
App.Console.PrintMessage("http://www.freecadweb.org/wiki/index.php?title=Macro_FCCamera" + "\n") | |
################################################################################################## | |
#read parameter | |
pathFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetString("setPathFile") | |
if pathFile == "": | |
pathFile = path | |
# CBox_01_Ecran = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_01_Ecran")# | |
# print(CBox_01_Ecran) | |
# CBox_02_FileFormat = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetInt("CBox_02_FileFormat")# | |
# print(CBox_02_FileFormat) | |
################################################################################################## | |
##Start##### | |
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetString("Version",__version__ + " (" + __date__ + ")")# | |
#Gui.ActiveDocument.ActiveView.setAxisCross(True) # GuiAxis true | |
s=SelObserver() # installe the function in resident mode SelObserver | |
FreeCADGui.Selection.addObserver(s) # installe the function in resident mode SelObserver | |
MainWindow = QtWidgets.QMainWindow() | |
ui = Ui_MainWindow() | |
ui.setupUi(MainWindow) | |
MainWindow.show() | |
Hi, this is a nice macro. I use it for making presentations of assembled constructions. I also add an easy feature that enables animated rotations like this: https://www.youtube.com/watch?v=bybqvos4xYk
...basically, I added:
- another button for rotation in opposite angle,
- in function on_PB_Accept_View_clicked added an if with:
if self.CB_Multiply_10.isChecked():
for n in range(90):
rot.setValue(coin.SbVec3f(Xv,Yv,Zv),valeur*fw_dir)
nrot = cam.orientation.getValue() * rot
cam.orientation = nrot
FreeCADGui.updateGui()
time.sleep(0.01)
else:
rot.setValue(coin.SbVec3f(Xv,Yv,Zv),valeur)
nrot = cam.orientation.getValue() * rot
cam.orientation = nrot
Currently, I still have messy code, but if you would be interested in this particular feature I would be happy to contribute and clean the code and make a patch.
Regards,
David
Hi
thank for appreciate my macro and many thanks for this beautiful video, I do not understand well your demand for rotate reverse you must enter one negative angle (10=normal and -10=reverse) or one loop in the principal loop ? why ?
For the animation i just finished (not yet finished example animation in the wiki) my other macro https://wiki.freecadweb.org/Macro_Rotate_To_Point, i adding command for save all coordinates of the object worked (selected rotation translation) you have two possibility:
- save the coordinates in a file form [0.0,0.0,0.0],[0.0,0.0,0.0] (i thoughtful for user create his mode and save it in preference)
- save in complete macro (saved directly in the macro directory (just accept)) with options include:
-
Type Key Q to Quit
-
Type Key D to Decrease speed
-
Type Key I to Increase speed
-
Type Key P to Pause/Continue or key RETURN or ESCAPE
-
Type Key S to Step by Step (key RETURN or ESCAPE to continue)
-
Type Key M for this message
maybe adding the possibility save also image ... work many objects then work with object name ...
tell me (vous pouvez aussi ma parler en Français)
mario
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 (in the same location of the macro)
toolbar
rename in FCCamera_00.png
rename in FCCamera_01.png
rename in FCCamera_02.png
rename in FCCamera_03.png
rename in FCCamera_04.png
rename in FCCamera_05.png
rename in FCCamera_06.png
rename in FCCamera_07.png
rename in FCCamera_08.png