Cercle Circonscrit 3D
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
Be nice to others! Read the FreeCAD code of conduct!
Re: Cercle Circonscrit 3D
Super boulot les amis !
En plus ca fait un excellent exemple de développement de plugin via python/qt.
En plus ca fait un excellent exemple de développement de plugin via python/qt.
Re: Cercle Circonscrit 3D
Dommage que denisfr ne soit plus revenu sur le forum depuis le 10 janvier, il n'est donc pas au courant de ces développements.
Re: Cercle Circonscrit 3D
Bonjour,
Désolé de ne pas être repassé depuis si longtemps. J'étais très occupé.
Je vais regarder le code de Mario de plus près. Merci à Lui et aux autres.
Désolé de ne pas être repassé depuis si longtemps. J'étais très occupé.
Je vais regarder le code de Mario de plus près. Merci à Lui et aux autres.
Re: Cercle Circonscrit 3D
Bonjour,
Après avoir lu le code et les posts de Mario, je me suis posé une question:
Apparemment, il faut mettre le cercle dans un plan (vues dans le script).
Hors contrairement à ce qu'a dit normandc
Un point peut contenir une infinité de plan, deux un ensemble ayant la droite passant entre ces deux points, et trois un seul.
Donc ma question, peut-on créer un plan temporaire avec ces trois points, les y déplacer afin d'avoir des points en deux dimensions? On peut ainsi trouver le cercle dans ce plan, qu'il suffira de recaler dans l’espace. Par contre, je ne connais pas les méthodes pour faire ça
Après avoir lu le code et les posts de Mario, je me suis posé une question:
Apparemment, il faut mettre le cercle dans un plan (vues dans le script).
Hors contrairement à ce qu'a dit normandc
Pour moi au contraire, trois points peuvent définir un et unique plan, non?normandc wrote:mais il me semble qu'il est impossible de circonscrire un cercle à trois points si ceux-ci ne sont pas sur un même plan
Un point peut contenir une infinité de plan, deux un ensemble ayant la droite passant entre ces deux points, et trois un seul.
Donc ma question, peut-on créer un plan temporaire avec ces trois points, les y déplacer afin d'avoir des points en deux dimensions? On peut ainsi trouver le cercle dans ce plan, qu'il suffira de recaler dans l’espace. Par contre, je ne connais pas les méthodes pour faire ça
Re: Cercle Circonscrit 3D
Arf tu as tout à fait raison... Je ne sais pas ce que j'ai pensé quand j'ai écrit ça !denisfr wrote:Pour moi au contraire, trois points peuvent définir un et unique plan, non?
Re: Cercle Circonscrit 3D
Bonjour denisfr
Ce petit programme permet de circonscrire un cercle sur trois points, sur un même plan ou non c'est à dire chacun n'importe où dans l'espace (mode par défaut)
Si vous voulez que les points soient sur le même plan X Y ou Z à vous de les créer sur le plan que vous aurez choisi de les sélectionner et activer la fonction (une des trois autres fonctions , ces trois autres fonctions créent un cercle circonscrit dans chaque plan XYZ sur le point choisi.
Je crois que ce petit programme est complet , à vous de l'utiliser.
ici quelques exemples
mario
Ce petit programme permet de circonscrire un cercle sur trois points, sur un même plan ou non c'est à dire chacun n'importe où dans l'espace (mode par défaut)
Si vous voulez que les points soient sur le même plan X Y ou Z à vous de les créer sur le plan que vous aurez choisi de les sélectionner et activer la fonction (une des trois autres fonctions , ces trois autres fonctions créent un cercle circonscrit dans chaque plan XYZ sur le point choisi.
Je crois que ce petit programme est complet , à vous de l'utiliser.
ici quelques exemples
mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
My macros on Gist.github here complete macros Wiki and forum.
Re: Cercle Circonscrit 3D
Bonjour,
Merci beaucoup Mario52.
Voici quelques petites remarques (toutes gentilles ):
1) La macro donnait quelques faux suivant l'ordre de sélection.
2) Le code n'était pas trop lisible (les variables n'avaient pas de nom explicite)
Voici donc ma petite modification de code qui pourrait être incorporée:
Le gros changement ce trouve dans la partie du calcul 3D, qui a été mis dans une fonction à part: affichage3D.
J'ai ajouté deux variables globales:
1) gnumDebug # Défini le niveau de débogage Définir une valeur (0>x>5) pour afficher plus d'informations
2) gblTest # Pour créer des points aléatoires à des fins de test (en cliquant sur Appliquer, la macro crée trois points aléatoirement (-10>x>10) pour définir le cercle circonscrit en 3D
Voilou.
Merci beaucoup Mario52.
Voici quelques petites remarques (toutes gentilles ):
1) La macro donnait quelques faux suivant l'ordre de sélection.
2) Le code n'était pas trop lisible (les variables n'avaient pas de nom explicite)
Voici donc ma petite modification de code qui pourrait être incorporée:
Code: Select all
# -*- coding: utf-8 -*-
# Cercle sur 3 points.py
# créer un cercle à partir de 3 points sélectionnés
# combinaison des deux programmes "créer un cercle à partir de 3 points sélectionnés"
# avec comme options le cercle (orthogonal) peut être construit sur un plans au choix
# à la coordonnée d'une des trois formes sélectionnées au choix
# le mode par défaut, crée le cercle dans l'espace 3D
# les options créent le cercle de manière orthogonale sur le plan et vue au choix
# avec la création du point central O/N, de la couleur se rapportant aux axes O/N
# 04/03/2013 # 24/03/2013 # by mario52
# la formule adaptée (avec l'autorisation de son auteur) par " mario52 " pour les cercles orthogonaux provient de
# http://www-obs.univ-lyon1.fr/labo/fc/Ateliers_archives/ateliers_2005-06/cercle_3pts.pdf
# lire la note dans le pdf, sur l'ordre de sélection des points,
# si la formule renvoie une erreur (exemple les 3 points dans le même alignement)
# la formule adaptée par " galou_breizh " pour le cercle dans l'espace 3D provient de
# http://en.wikipedia.org/wiki/Circumscribed_circle
# la fenêtre reste toujours visible et permet de travailler sur les autres programmes
# comme par exemple sélectionner d'autres points dans FreeCAD
import Draft, Part, FreeCAD, math, PartGui, FreeCADGui, PyQt4, random
from math import sqrt, pi, sin, asin, cos, acos
from FreeCAD import Base
from PyQt4 import QtCore, QtGui
# gnumVueChoix = 0 et gnumAlignerSur = 0 , mode par défaut
global gnumVueChoix # choix de la vue Dessus=1 XY, vue Face=2 ZX, vue Droite=3 ZY (Orthogonal)
global gnumAlignerSur # aligne le cercle sur une forme au choix (1,2 ou 3) ou sur Z=0 (Orthogonal)
global gblAfficherPoint # affiche le point central du cercle
global gblColorer # gblColorer suivant l'axe 1=Ok 0=Couleur courante uniquement Orthogonal !
global gblAfficherConst # affiche la construction du cercle
global gnumDebug # Défini le niveau de débogage
global gblTest # Pour créer des points aléatoires à des fins de test
gnumVueChoix = 0
gnumAlignerSur = 0
gblAfficherPoint = True
gblColorer = True
gblAfficherConst = False
gnumDebug = 0
gblTest = False
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def __init__(self, MainWindow):
self.window = MainWindow
path = FreeCAD.ConfigGet("AppHomePath") # chemin
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(490, 302)
MainWindow.setWindowIcon(QtGui.QIcon(path+'View-C3P.png'))
self.widCentralWidget = QtGui.QWidget(MainWindow)
self.widCentralWidget.setObjectName(_fromUtf8("widCentralWidget"))
self.grpbMode = QtGui.QGroupBox(self.widCentralWidget)
self.grpbMode.setGeometry(QtCore.QRect(20, 10, 130, 161))
self.grpbMode.setObjectName(_fromUtf8("grpbMode"))
self.rbtModeDefault = QtGui.QRadioButton(self.grpbMode)
self.rbtModeDefault.setGeometry(QtCore.QRect(10, 30, 130, 20))
self.rbtModeDefault.setChecked(True)
self.rbtModeDefault.setObjectName(_fromUtf8("rbtModeDefault"))
self.rbtModeDefault.clicked.connect(self.on_rbtModeDefault_clicked) #connection rbtModeDefault
self.rbtModeDefault.setToolTip(_translate("MainWindow", "Cercle sur 3 points dans l'espace", None))
self.rbtModeFrontView = QtGui.QRadioButton(self.grpbMode)
self.rbtModeFrontView.setGeometry(QtCore.QRect(10, 60, 130, 20))
self.rbtModeFrontView.setObjectName(_fromUtf8("rbtModeFrontView"))
self.rbtModeFrontView.clicked.connect(self.on_rbtModeFrontView_clicked) #connection rbtModeFrontView
self.rbtModeFrontView.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la vue de face", None))
#self.strImgModeFrontView = "C:\Program Files\FreeCAD0.13\View-Front.png"
self.strImgModeFrontView = path+"View-Front.png"
icoModeFrontView = QtGui.QIcon()
icoModeFrontView.addPixmap(QtGui.QPixmap(self.strImgModeFrontView),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.rbtModeFrontView.setIcon(icoModeFrontView)
self.rbtModeUpView = QtGui.QRadioButton(self.grpbMode)
self.rbtModeUpView.setGeometry(QtCore.QRect(10, 90, 130, 20))
self.rbtModeUpView.setObjectName(_fromUtf8("rbtModeUpView"))
self.rbtModeUpView.clicked.connect(self.on_rbtModeUpView_clicked) #connection rbtModeUpView
self.rbtModeUpView.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la vue de dessus", None))
#self.strImgModeTopView = "C:\Program Files\FreeCAD0.13\View-Top.png"
self.strImgModeTopView = path+"View-Top.png"
icoModeTopView = QtGui.QIcon()
icoModeTopView.addPixmap(QtGui.QPixmap(self.strImgModeTopView),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.rbtModeUpView.setIcon(icoModeTopView)
self.rbtModeRightView = QtGui.QRadioButton(self.grpbMode)
self.rbtModeRightView.setGeometry(QtCore.QRect(10, 120, 130, 20))
self.rbtModeRightView.setObjectName(_fromUtf8("rbtModeRightView"))
self.rbtModeRightView.clicked.connect(self.on_rbtModeRightView_clicked) #connection rbtModeRightView
self.rbtModeRightView.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la vue de droite", None))
#self.strImgModeRightView = "C:\Program Files\FreeCAD0.13\View-Left.png"
self.strImgModeRightView = path+"View-Left.png"
icoModeRightView = QtGui.QIcon()
icoModeRightView.addPixmap(QtGui.QPixmap(self.strImgModeRightView),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.rbtModeRightView.setIcon(icoModeRightView)
self.grpbAlign = QtGui.QGroupBox(self.widCentralWidget)
self.grpbAlign.setGeometry(QtCore.QRect(170, 10, 120, 161))
self.grpbAlign.setObjectName(_fromUtf8("grpbAlign"))
self.rbtAlignDefault = QtGui.QRadioButton(self.grpbAlign)
self.rbtAlignDefault.setGeometry(QtCore.QRect(10, 30, 95, 20))
self.rbtAlignDefault.setChecked(True)
self.rbtAlignDefault.setObjectName(_fromUtf8("rbtAlignDefault"))
self.rbtAlignDefault.clicked.connect(self.on_rbtAlignDefault_clicked) #connection rbtAlignDefault
self.rbtAlignDefault.setToolTip(_translate("MainWindow", "Cercle sur 3 points dans l'espace", None))
self.rbtAlignFrm1 = QtGui.QRadioButton(self.grpbAlign)
self.rbtAlignFrm1.setGeometry(QtCore.QRect(10, 60, 95, 20))
self.rbtAlignFrm1.setObjectName(_fromUtf8("rbtAlignFrm1"))
self.rbtAlignFrm1.clicked.connect(self.on_rbtAlignFrm1_clicked) #connection rbtAlignFrm1
self.rbtAlignFrm1.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la forme 1", None))
self.rbtAlignFrm2 = QtGui.QRadioButton(self.grpbAlign)
self.rbtAlignFrm2.setGeometry(QtCore.QRect(10, 90, 95, 20))
self.rbtAlignFrm2.setObjectName(_fromUtf8("rbtAlignFrm2"))
self.rbtAlignFrm2.clicked.connect(self.on_rbtAlignFrm2_clicked) #connection rbtAlignFrm2
self.rbtAlignFrm2.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la forme 2", None))
self.rbtAlignFrm3 = QtGui.QRadioButton(self.grpbAlign)
self.rbtAlignFrm3.setGeometry(QtCore.QRect(10, 120, 95, 20))
self.rbtAlignFrm3.setObjectName(_fromUtf8("rbtAlignFrm3"))
self.rbtAlignFrm3.clicked.connect(self.on_rbtAlignFrm3_clicked) #connection rbtAlignFrm3
self.rbtAlignFrm3.setToolTip(_translate("MainWindow", "Cercle orthogonal sur la forme 3", None))
self.chkbShowCenter = QtGui.QCheckBox(self.widCentralWidget)
self.chkbShowCenter.setGeometry(QtCore.QRect(20, 180, 140, 20))
self.chkbShowCenter.setChecked(True)
self.chkbShowCenter.setObjectName(_fromUtf8("chkbShowCenter"))
self.chkbShowCenter.setToolTip(_translate("MainWindow", "Affiche un point sur le centre du cercle", None))
# self.chkbShowCenter.clicked.connect(self.on_chkbShowCenter_clicked) #connection chkbShowCenter
self.chkbAssoColor = QtGui.QCheckBox(self.widCentralWidget)
self.chkbAssoColor.setGeometry(QtCore.QRect(170, 180, 150, 20))
self.chkbAssoColor.setChecked(True)
self.chkbAssoColor.setObjectName(_fromUtf8("chkbAssoColor"))
self.chkbAssoColor.setToolTip(_translate("MainWindow", "Associe la couleur du cercle à la couleur des axes X,Y,Z (Orthogonal)", None))
# self.chkbAssoColor.clicked.connect(self.on_chkbAssoColor_clicked) #connection chkbAssoColor
self.chkbShowConst = QtGui.QCheckBox(self.widCentralWidget)
self.chkbShowConst.setGeometry(QtCore.QRect(20, 210, 140, 20))
self.chkbShowConst.setChecked(False)
self.chkbShowConst.setObjectName(_fromUtf8("chkbShowConst"))
self.chkbShowConst.setToolTip(_translate("MainWindow", "Affiche la construction du cercle", None))
# self.chkbShowConst.clicked.connect(self.on_chkbShowCenter_clicked) #connection chkbShowConst
if gnumDebug>0:
self.lbDebug = QtGui.QLabel(self.widCentralWidget)
self.lbDebug.setGeometry(QtCore.QRect(170, 210, 81, 10))
self.lbDebug.setObjectName(_fromUtf8("lbDebug"))
self.lbDebug.setText(_translate("MainWindow", "Debug=", None)+str(gnumDebug))
if gblTest:
self.lbTest = QtGui.QLabel(self.widCentralWidget)
self.lbTest.setGeometry(QtCore.QRect(170, 225, 81, 10))
self.lbTest.setObjectName(_fromUtf8("lbTest"))
self.lbTest.setText(_translate("MainWindow", "Test Mode", None))
self.lneCoordX = QtGui.QLineEdit(self.widCentralWidget)
self.lneCoordX.setGeometry(QtCore.QRect(320, 30, 151, 22))
self.lneCoordX.setObjectName(_fromUtf8("lneCoordX"))
self.lneCoordX.setReadOnly(True)
self.lneCoordY = QtGui.QLineEdit(self.widCentralWidget)
self.lneCoordY.setGeometry(QtCore.QRect(320, 80, 151, 22))
self.lneCoordY.setObjectName(_fromUtf8("lneCoordY"))
self.lneCoordY.setReadOnly(True)
self.lneCoordZ = QtGui.QLineEdit(self.widCentralWidget)
self.lneCoordZ.setGeometry(QtCore.QRect(320, 130, 151, 22))
self.lneCoordZ.setObjectName(_fromUtf8("lneCoordZ"))
self.lneCoordZ.setReadOnly(True)
self.lneRadius = QtGui.QLineEdit(self.widCentralWidget)
self.lneRadius.setGeometry(QtCore.QRect(320, 180, 151, 22))
self.lneRadius.setObjectName(_fromUtf8("lneRadius"))
self.lneRadius.setReadOnly(True)
self.lneAngle = QtGui.QLineEdit(self.widCentralWidget)
self.lneAngle.setGeometry(QtCore.QRect(320, 230, 151, 22))
self.lneAngle.setObjectName(_fromUtf8("lneAngle"))
self.lneAngle.setReadOnly(True)
self.lbCoordX = QtGui.QLabel(self.widCentralWidget)
self.lbCoordX.setGeometry(QtCore.QRect(320, 10, 91, 16))
self.lbCoordX.setObjectName(_fromUtf8("lbCoordX"))
self.lbCoordY = QtGui.QLabel(self.widCentralWidget)
self.lbCoordY.setGeometry(QtCore.QRect(320, 60, 91, 16))
self.lbCoordY.setObjectName(_fromUtf8("lbCoordY"))
self.lbCoordZ = QtGui.QLabel(self.widCentralWidget)
self.lbCoordZ.setGeometry(QtCore.QRect(320, 110, 91, 16))
self.lbCoordZ.setObjectName(_fromUtf8("lbCoordZ"))
self.lbRadius = QtGui.QLabel(self.widCentralWidget)
self.lbRadius.setGeometry(QtCore.QRect(320, 160, 53, 16))
self.lbRadius.setObjectName(_fromUtf8("lbRadius"))
self.lbAngle = QtGui.QLabel(self.widCentralWidget)
self.lbAngle.setGeometry(QtCore.QRect(320, 210, 81, 16))
self.lbAngle.setObjectName(_fromUtf8("lbAngle"))
self.pbtExit = QtGui.QPushButton(self.widCentralWidget)
self.pbtExit.setGeometry(QtCore.QRect(20, 240, 90, 28))
self.pbtExit.setObjectName(_fromUtf8("pbtExit"))
self.pbtExit.clicked.connect(self.on_pbtExit_clicked) #connection pbtExit
self.pbtExit.setToolTip(_translate("MainWindow", "Quitte la fonction", None))
self.pbtAppli = QtGui.QPushButton(self.widCentralWidget)
self.pbtAppli.setGeometry(QtCore.QRect(110, 240, 90, 28))
self.pbtAppli.setObjectName(_fromUtf8("pbtAppli"))
self.pbtAppli.clicked.connect(self.on_pbtAppli_clicked) #connection pbtAppli
self.pbtAppli.setToolTip(_translate("MainWindow", "Applique la fonction sans quitter", None))
#self.pbtAppli.setStyleSheet("background-color: red") #cette fonction donne une couleur au bouton
#self.pbtAppli.setStyleSheet("color : #ff0000") #cette fonction donne une couleur au texte du bouton
#self.pbtAppli.setStyleSheet("color : #ff0000; background-color : #0000ff;" ) #combinaison des deux
self.pbtSetDefault = QtGui.QPushButton(self.widCentralWidget)
self.pbtSetDefault.setGeometry(QtCore.QRect(200, 240, 90, 28))
self.pbtSetDefault.setObjectName(_fromUtf8("pbtSetDefault"))
self.pbtSetDefault.clicked.connect(self.on_pbtSetDefault_clicked) #connection pbtSetDefault
self.pbtSetDefault.setToolTip(_translate("MainWindow", "Définit le mode par défaut (Cercle sur 3 points dans l'espace)", None))
MainWindow.setCentralWidget(self.widCentralWidget)
self.stbStatusBar = QtGui.QStatusBar(MainWindow)
self.stbStatusBar.setObjectName(_fromUtf8("stbStatusBar"))
MainWindow.setStatusBar(self.stbStatusBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowFlags(PyQt4.QtCore.Qt.WindowStaysOnTopHint) # cette fonction met la fenêtre en avant
#MainWindow.setStyleSheet("background-color: red") #cette fonction donne une couleur à la fenêtre
#MainWindow.setWindowOpacity(0.5) #cette fonction donne une transparence à la fenêtre
MainWindow.setWindowTitle(_translate("MainWindow", "Cercle sur 3 points", None))
self.grpbMode.setTitle(_translate("MainWindow", "Mode", None))
self.rbtModeDefault.setText(_translate("MainWindow", "Défaut", None))
self.rbtModeFrontView.setText(_translate("MainWindow", "Vue Face", None))
self.rbtModeUpView.setText(_translate("MainWindow", "Vue Dessus", None))
self.rbtModeRightView.setText(_translate("MainWindow", "Vue Droite", None))
self.grpbAlign.setTitle(_translate("MainWindow", "Alignement sur", None))
self.rbtAlignDefault.setText(_translate("MainWindow", "Défaut", None))
self.rbtAlignFrm1.setText(_translate("MainWindow", "Forme 1", None))
self.rbtAlignFrm2.setText(_translate("MainWindow", "Forme 2", None))
self.rbtAlignFrm3.setText(_translate("MainWindow", "Forme 3", None))
self.chkbShowCenter.setText(_translate("MainWindow", "Afficher le centre", None))
self.chkbAssoColor.setText(_translate("MainWindow", "Associer les couleurs", None))
self.chkbShowConst.setText(_translate("MainWindow", "Afficher la construction", None))
self.lbCoordX.setText(_translate("MainWindow", "Coordonnée X", None))
self.lbCoordY.setText(_translate("MainWindow", "Coordonnée Y", None))
self.lbCoordZ.setText(_translate("MainWindow", "Coordonnée Z", None))
self.lbRadius.setText(_translate("MainWindow", "Rayon", None))
self.lbAngle.setText(_translate("MainWindow", "Angle", None))
self.pbtExit.setText(_translate("MainWindow", "Quitter", None))
self.pbtAppli.setText(_translate("MainWindow", "Appliquer", None))
self.pbtSetDefault.setText(_translate("MainWindow", "Défaut", None))
# radioboutons du groupe Mode
def on_rbtModeDefault_clicked(self):
if self.rbtModeDefault.isChecked():
self.rbtAlignDefault.setChecked(True)
def on_rbtModeFrontView_clicked(self):
if self.rbtAlignDefault.isChecked():
self.rbtAlignFrm1.setChecked(True)
def on_rbtModeUpView_clicked(self):
if self.rbtAlignDefault.isChecked():
self.rbtAlignFrm1.setChecked(True)
def on_rbtModeRightView_clicked(self):
if self.rbtAlignDefault.isChecked():
self.rbtAlignFrm1.setChecked(True)
# radioboutons du groupe Alignement
def on_rbtAlignDefault_clicked(self):
if self.rbtAlignDefault.isChecked():
self.rbtModeDefault.setChecked(True)
def on_rbtAlignFrm1_clicked(self):
if self.rbtModeDefault.isChecked():
self.rbtModeFrontView.setChecked(True)
def on_rbtAlignFrm2_clicked(self):
if self.rbtModeDefault.isChecked():
self.rbtModeFrontView.setChecked(True)
def on_rbtAlignFrm3_clicked(self):
if self.rbtModeDefault.isChecked():
self.rbtModeFrontView.setChecked(True)
# Boutons
def on_pbtExit_clicked(self): # Bouton Quitte la fonction
App.Console.PrintMessage("Terminé\r\n")
self.window.hide()
def on_pbtAppli_clicked(self): # Bouton Appliquer
if self.rbtModeDefault.isChecked():
gnumVueChoix=0
if self.rbtModeFrontView.isChecked():
gnumVueChoix=1
if self.rbtModeUpView.isChecked():
gnumVueChoix=2
if self.rbtModeRightView.isChecked():
gnumVueChoix=3
if self.rbtAlignDefault.isChecked():
gnumAlignerSur=0
if self.rbtAlignFrm1.isChecked():
gnumAlignerSur=1
if self.rbtAlignFrm2.isChecked():
gnumAlignerSur=2
if self.rbtAlignFrm3.isChecked():
gnumAlignerSur=3
gblAfficherPoint = (self.chkbShowCenter.checkState()<>0)
gblColorer = (self.chkbAssoColor.checkState()<>0)
gblAfficherConst = (self.chkbShowConst.checkState()<>0)
if gnumDebug>4:
App.Console.PrintMessage("Appliquer\r\n")
App.Console.PrintMessage("gnumVueChoix:"+str(gnumVueChoix)+" \t")
App.Console.PrintMessage("gnumAlignerSur:"+str(gnumAlignerSur)+" \t")
App.Console.PrintMessage("gblAfficherPoint:"+str(gblAfficherPoint)+" \t")
App.Console.PrintMessage("gblColorer:"+str(gblColorer)+" \r\n")
def errorDialog(msg):
# Create a simple dialog QMessageBox
# The first argument indicates the icon used: one of QtGui.QMessageBox.{NoIcon, Information, Warning, Critical, Question}
diag = QtGui.QMessageBox(QtGui.QMessageBox.Critical,u"Error Message",msg)
diag.setWindowFlags(PyQt4.QtCore.Qt.WindowStaysOnTopHint) # cette fonction met la fenêtre en avant
#diag.setWindowModality(QtCore.Qt.ApplicationModal) # la fonction a été désactivée pour favoriser "WindowStaysOnTopHint"
diag.exec_()
def affiche(pplPlacement, pCentreX=None, pCentreY=None, pCentreZ=None, pRayon=0.0, pAngle=0.0, pAfficherPoint=False, pColorer=False, pCoulRouge=0.0, pCoulVert=0.0, pCoulBleu=0.0):
if gnumDebug>3:
App.Console.PrintMessage("pplPlacement:"+str(pplPlacement)+"\r\n")
App.Console.PrintMessage("pCentreX:"+str(pCentreX)+"\r\n")
App.Console.PrintMessage("pCentreY:"+str(pCentreY)+"\r\n")
App.Console.PrintMessage("pCentreZ:"+str(pCentreZ)+"\r\n")
App.Console.PrintMessage("pRayon:"+str(pRayon)+"\r\n")
App.Console.PrintMessage("pAngle:"+str(pAngle)+"\r\n")
App.Console.PrintMessage("pAfficherPoint:"+str(pAfficherPoint)+"\r\n")
App.Console.PrintMessage("pColorer:"+str(pColorer)+"\r\n")
App.Console.PrintMessage("pCoulRouge:"+str(pCoulRouge)+"\r\n")
App.Console.PrintMessage("pCoulVert:"+str(pCoulVert)+"\r\n")
App.Console.PrintMessage("pCoulBleu:"+str(pCoulBleu)+"\r\n")
if (pCentreX<>None) and (pCentreY<>None) and (pCentreZ<>None):
pplPlacement.Base=FreeCAD.Vector(pCentreX,pCentreY,pCentreZ)
if (pCentreX==None): pCentreX=pplPlacement.Base.x
if (pCentreY==None): pCentreY=pplPlacement.Base.y
if (pCentreZ==None): pCentreZ=pplPlacement.Base.z
crlTemp=Draft.makeCircle((pRayon),placement=pplPlacement,face=False,support=None)
if gnumDebug>3: App.Console.PrintMessage("crlTemp:"+str(crlTemp)+"\r\n")
if pColorer==1:
crlTemp.ViewObject.LineColor = (pCoulRouge,pCoulVert,pCoulBleu)
if pAfficherPoint==1:
pntTemp=Draft.makePoint(pCentreX,pCentreY,pCentreZ)
pntTemp.Label="Center"
if gnumDebug>3: App.Console.PrintMessage("pntTemp:"+str(pntTemp)+"\r\n")
if pColorer==1:
pntTemp.ViewObject.PointColor = (pCoulRouge,pCoulVert,pCoulBleu)
self.lneCoordX.setText(str(pCentreX))
self.lneCoordY.setText(str(pCentreY))
self.lneCoordZ.setText(str(pCentreZ))
self.lneRadius.setText(str(pRayon))
self.lneAngle.setText(str(pAngle))
if gnumDebug>0: App.Console.PrintMessage("Done\r\n")
def affiche3D(pvecP1, pvecP2, pvecP3):
if gnumDebug>0: App.Console.PrintMessage("Cercle 3D\r\n")
if gnumDebug>2: App.Console.PrintMessage("pvecP1:"+str(pvecP1)+"\r\n")
if gnumDebug>2: App.Console.PrintMessage("pvecP2:"+str(pvecP2)+"\r\n")
if gnumDebug>2: App.Console.PrintMessage("pvecP3:"+str(pvecP3)+"\r\n")
#Code modifié de http://pygeo.sourceforge.net/docs/base/analytics/_position3.py.html?f=379&l=397#378
#Calcul des vecteurs entre les trois points
vecP1P2 = pvecP2 - pvecP1
vecP1P3 = pvecP3 - pvecP1
if gnumDebug>2: App.Console.PrintMessage("vecP1P2:"+str(vecP1P2)+"\r\n")
if gnumDebug>2: App.Console.PrintMessage("vecP1P3:"+str(vecP1P3)+"\r\n")
if gblAfficherConst: Draft.makeWire([pvecP2, pvecP1],closed=False,face=False,support=None).Label="vecP1P2"
if gblAfficherConst: Draft.makeWire([pvecP3, pvecP1],closed=False,face=False,support=None).Label="vecP1P3"
#Calcul du vecteur normal au plan P1P2P3
vecNormal=vecP1P2.cross(vecP1P3)
if gnumDebug>2: App.Console.PrintMessage("vecNormal:"+str(vecNormal)+"\r\n")
if gblAfficherConst and (gnumDebug>0): Draft.makeWire([pvecP1, vecNormal+pvecP1],closed=False,face=False,support=None).Label="vecNormal"
if vecNormal.Length==0:
errorDialog(u"Points alignés")
return
#Calcul de la surface de ces deux vecteur
numSurf = vecP1P2.dot(vecP1P3)
if gnumDebug>2: App.Console.PrintMessage("numSurf:"+str(numSurf)+"\r\n")
#Calcul des longueurs au carré des deux vecteurs
numDistP1P2 = vecP1P2.Length * vecP1P2.Length
numDistP1P3 = vecP1P3.Length * vecP1P3.Length
if gnumDebug>2: App.Console.PrintMessage("numDistP1P2:"+str(numDistP1P2)+"\r\n")
if gnumDebug>2: App.Console.PrintMessage("numDistP1P3:"+str(numDistP1P3)+"\r\n")
#Récupération de l'angle car:
#vecP1P2.dot(vecP1P3)=vecP1P2.Length²*vecP1P3.Length²*cos(angleP2P1P3)
#http://fr.wikipedia.org/wiki/Produit_scalaire
numDen=2.0*(numDistP1P2 * numDistP1P3 - numSurf*numSurf)
if gnumDebug>2: App.Console.PrintMessage("numDen:"+str(numDen)+"\r\n")
try:
numFactorP1P2=(numDistP1P2 - numSurf) / numDen*numDistP1P3
if abs(numFactorP1P2)<1e-10:
numFactorP1P2=0
if gnumDebug>2: App.Console.PrintMessage("numFactorP1P2:"+str(numFactorP1P2)+"\r\n")
numFactorP1P3=(numDistP1P3 - numSurf) / numDen*numDistP1P2
if abs(numFactorP1P3)<1e-10:
numFactorP1P3=0
if gnumDebug>2: App.Console.PrintMessage("numFactorP1P3:"+str(numFactorP1P3)+"\r\n")
except ZeroDivisionError:
errorDialog(u"Points non distincs")
return
vecP1P2.multiply(numFactorP1P2)
if gnumDebug>2: App.Console.PrintMessage("vecP1P2:"+str(vecP1P2)+"\r\n")
vecP1P3.multiply(numFactorP1P3)
if gnumDebug>2: App.Console.PrintMessage("vecP1P3:"+str(vecP1P3)+"\r\n")
vecCenter= vecP1P2 + vecP1P3 + pvecP1
if gnumDebug>2: App.Console.PrintMessage("vecCenter:"+str(vecCenter)+"\r\n")
# Creation of a circle
numRayon = (vecCenter - pvecP1).Length
if gnumDebug>2: App.Console.PrintMessage("numRayon:"+str(numRayon)+"\r\n")
vecNormalRot=vecNormal
vecNormalRot.normalize()
vecAxeRot = App.Vector(0, 0, 1).cross(vecNormalRot)
if gnumDebug>2: App.Console.PrintMessage("vecAxeRot:"+str(vecAxeRot)+"\r\n")
if gblAfficherConst and (gnumDebug>1): Draft.makeWire([App.Vector(0,0,0), vecNormalRot],closed=False,face=False,support=None).Label="vecAxeRot"
#Rotation en Z= angle entre l'axe X vers Y
numAngle = asin(vecAxeRot.Length) * 180 / pi
if gnumDebug>2: App.Console.PrintMessage("numAngle:"+str(numAngle)+"\r\n")
if vecNormal.z < 0 :#Angle entre 180 et 360°
numAngle = 360 - numAngle
if gnumDebug>2: App.Console.PrintMessage("numAngle après correction:"+str(numAngle)+"\r\n")
if vecAxeRot.Length > 0:
vecAxeRot.normalize()
plCercle = Base.Placement(vecCenter,vecAxeRot,numAngle)
if gnumDebug>2: App.Console.PrintMessage("plCercle:"+str(plCercle)+"\r\n")
affiche(plCercle,pRayon=numRayon,pAngle=numAngle,pAfficherPoint=gblAfficherPoint,pColorer=gblColorer)
# prendre les objets sélectionnés
objSelect = FreeCADGui.Selection.getSelection()
centreX=0;centreY=0;rayon=0
# S'il y a 3 points sélectionnés alors..
if (len(objSelect)==3) or gblTest :
if (gnumVueChoix>0) and (not gblTest):
i=0
tabCoord=[0,0,0,0,0,0,0,0,0]
for obj in objSelect:
pntCoord=(obj.Shape.BoundBox.Center)
tabCoord[i+0]=(pntCoord.x)
tabCoord[i+1]=(pntCoord.y)
tabCoord[i+2]=(pntCoord.z)
i=i+3
if gnumVueChoix==3: # Vue de droite ZY (Rouge)
z_point_1=tabCoord[0]
x_point_1=tabCoord[1]
y_point_1=tabCoord[2]
z_point_2=tabCoord[3]
x_point_2=tabCoord[4]
y_point_2=tabCoord[5]
z_point_3=tabCoord[6]
x_point_3=tabCoord[7]
y_point_3=tabCoord[8]
elif gnumVueChoix==2: # Vue de face ZX (Vert)
y_point_1=tabCoord[0]
z_point_1=tabCoord[1]
x_point_1=tabCoord[2]
y_point_2=tabCoord[3]
z_point_2=tabCoord[4]
x_point_2=tabCoord[5]
y_point_3=tabCoord[6]
z_point_3=tabCoord[7]
x_point_3=tabCoord[8]
else: # Vue de dessus XY (Bleu)
x_point_1=tabCoord[0]
y_point_1=tabCoord[1]
z_point_1=tabCoord[2]
x_point_2=tabCoord[3]
y_point_2=tabCoord[4]
z_point_2=tabCoord[5]
x_point_3=tabCoord[6]
y_point_3=tabCoord[7]
z_point_3=tabCoord[8]
# Calcul des coordonnées du centre du cercle
try:
centreX =((x_point_3**2-x_point_2**2+y_point_3**2-y_point_2**2)/(2*(y_point_3-y_point_2))-(x_point_2**2-x_point_1**2+y_point_2**2-y_point_1**2)/(2*(y_point_2-y_point_1)))/((x_point_3-x_point_2)/(y_point_3-y_point_2)-(x_point_2-x_point_1)/(y_point_2-y_point_1))
centreY =-(x_point_2-x_point_1)/(y_point_2-y_point_1)*centreX+(x_point_2**2-x_point_1**2+y_point_2**2-y_point_1**2)/(2*(y_point_2-y_point_1))
rayon =sqrt((x_point_1-centreX)**2+(y_point_1-centreY)**2)
except:
errorDialog(u"Calcul impossible trop d'élements alignés")
else:
#finally: # si finally est présent, il sera TOUJOURS exécuté
# Définition de la coordonnée Z
centreZ=0
# Création du cercle
pl=FreeCAD.Placement()
if gnumVueChoix==1: # Plan XY Dessus
pl.Rotation.Q=(0,0,0,1.0)
if gnumAlignerSur==1:
affiche(pl,centreX,centreY,z_point_1,rayon,0,gblAfficherPoint,gblColorer,0.0,0.0,1.0)
elif gnumAlignerSur==2:
affiche(pl,centreX,centreY,z_point_2,rayon,0,gblAfficherPoint,gblColorer,0.0,0.0,1.0)
elif gnumAlignerSur==3:
affiche(pl,centreX,centreY,z_point_3,rayon,0,gblAfficherPoint,gblColorer,0.0,0.0,1.0)
elif gnumVueChoix==2: # Plan XZ Face
pl.Rotation.Q=(1,0,0,1.0)
if gnumAlignerSur==1:
affiche(pl,centreY,z_point_1,centreX,rayon,0,gblAfficherPoint,gblColorer,0.0,1.0,0.0)
elif gnumAlignerSur==2:
affiche(pl,centreY,z_point_2,centreX,rayon,0,gblAfficherPoint,gblColorer,0.0,1.0,0.0)
elif gnumAlignerSur==3:
affiche(pl,centreY,z_point_3,centreX,rayon,0,gblAfficherPoint,gblColorer,0.0,1.0,0.0)
elif gnumVueChoix==3: # Plan YZ Droite
pl.Rotation.Q=(0,1,0,1.0)
if gnumAlignerSur==1:
affiche(pl,z_point_1,centreX,centreY,rayon,0,gblAfficherPoint,gblColorer,1.0,0.0,0.0)
elif gnumAlignerSur==2:
affiche(pl,z_point_2,centreX,centreY,rayon,0,gblAfficherPoint,gblColorer,1.0,0.0,0.0)
elif gnumAlignerSur==3:
affiche(pl,z_point_3,centreX,centreY,rayon,0,gblAfficherPoint,gblColorer,1.0,0.0,0.0)
else: # if gnumVueChoix>0: 3D XYZ
if gblTest:
vecRandP1=App.Vector(random.random()*20-10,random.random()*20-10,random.random()*20-10)
Draft.makePoint(vecRandP1.x,vecRandP1.y,vecRandP1.z).Label="vecRandP1"
vecRandP2=App.Vector(random.random()*20-10,random.random()*20-10,random.random()*20-10)
Draft.makePoint(vecRandP2.x,vecRandP2.y,vecRandP2.z).Label="vecRandP2"
vecRandP3=App.Vector(random.random()*20-10,random.random()*20-10,random.random()*20-10)
Draft.makePoint(vecRandP3.x,vecRandP3.y,vecRandP3.z).Label="vecRandP3"
affiche3D( vecRandP1, vecRandP2, vecRandP3)
else:
affiche3D( objSelect[0].Shape.BoundBox.Center,
objSelect[1].Shape.BoundBox.Center,
objSelect[2].Shape.BoundBox.Center)
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(objSelect[0])
FreeCADGui.Selection.addSelection(objSelect[1])
FreeCADGui.Selection.addSelection(objSelect[2])
else:# if len(objSelect)==3 :
# Si la condition n'est pas remplie, recommencer
errorDialog(u"Sélectionnez 3 points et recommencez")
#FreeCAD.Console.PrintError("Sélectionnez 3 points et recommencez\r\n")
#________________________________________________________________________________
def on_pbtSetDefault_clicked(self): # Valeurs d'origine
App.Console.PrintMessage("Défaut\r\n")
gnumVueChoix=0 # choix de la vue Dessus=1 XY, vue Face=2 ZX, vue Droite=3 ZY
self.rbtModeDefault.setChecked(True)
gnumAlignerSur=0 # aligne le cercle sur une forme au choix (1,2 ou 3) ou sur Z=0
self.rbtAlignDefault.setChecked(True)
gblAfficherPoint=1 # affiche le point central du cercle
self.chkbShowCenter.setChecked(True)
gblColorer=1 # gblColorer suivant l'axe 1=Ok 0=Couleur courante uniquement Orthogonal !
self.chkbAssoColor.setChecked(True)
#______________________________________________________________________________________
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow(MainWindow)
MainWindow.show()
J'ai ajouté deux variables globales:
1) gnumDebug # Défini le niveau de débogage Définir une valeur (0>x>5) pour afficher plus d'informations
2) gblTest # Pour créer des points aléatoires à des fins de test (en cliquant sur Appliquer, la macro crée trois points aléatoirement (-10>x>10) pour définir le cercle circonscrit en 3D
Voilou.
Re: Cercle Circonscrit 3D
Bonjour
mario
ça va certainement intéresser galou_breizh qui l' a codé.denisfr wrote: Le gros changement ce trouve dans la partie du calcul 3D, qui a été mis dans une fonction à part: affichage3D.
mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
My macros on Gist.github here complete macros Wiki and forum.
Re: Cercle Circonscrit 3D
Bonjour,
C'est bien vous qui avez créer le wiki?
C'est bien vous qui avez créer le wiki?
Re: Cercle Circonscrit 3D
Bonjour
non juste traduit le wiki original en français (une partie) et soigné la présentation à mon idée avec des ajouts de prises d'écrans avec l'interface fr
pour le moment nous ne sommes que trois avec normandc et yorik
mario
non juste traduit le wiki original en français (une partie) et soigné la présentation à mon idée avec des ajouts de prises d'écrans avec l'interface fr
pour le moment nous ne sommes que trois avec normandc et yorik
mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
My macros on Gist.github here complete macros Wiki and forum.