Cercle Circonscrit 3D

Forum destiné aux questions et discussions en français
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
gdo35
Posts: 189
Joined: Wed Jan 25, 2012 7:25 pm

Re: Cercle Circonscrit 3D

Post by gdo35 »

Super boulot les amis !

En plus ca fait un excellent exemple de développement de plugin via python/qt. ;)
User avatar
NormandC
Veteran
Posts: 18589
Joined: Sat Feb 06, 2010 9:52 pm
Location: Québec, Canada

Re: Cercle Circonscrit 3D

Post by NormandC »

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.
denisfr
Posts: 5
Joined: Tue Jan 08, 2013 5:08 pm

Re: Cercle Circonscrit 3D

Post by denisfr »

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.
denisfr
Posts: 5
Joined: Tue Jan 08, 2013 5:08 pm

Re: Cercle Circonscrit 3D

Post by denisfr »

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
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
Pour moi au contraire, trois points peuvent définir un et unique plan, non?

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 :oops:
User avatar
NormandC
Veteran
Posts: 18589
Joined: Sat Feb 06, 2010 9:52 pm
Location: Québec, Canada

Re: Cercle Circonscrit 3D

Post by NormandC »

denisfr wrote:Pour moi au contraire, trois points peuvent définir un et unique plan, non?
Arf tu as tout à fait raison... Je ne sais pas ce que j'ai pensé quand j'ai écrit ça ! :oops:
mario52
Veteran
Posts: 4692
Joined: Wed May 16, 2012 2:13 pm

Re: Cercle Circonscrit 3D

Post by mario52 »

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
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.
denisfr
Posts: 5
Joined: Tue Jan 08, 2013 5:08 pm

Re: Cercle Circonscrit 3D

Post by denisfr »

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:

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()
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.
mario52
Veteran
Posts: 4692
Joined: Wed May 16, 2012 2:13 pm

Re: Cercle Circonscrit 3D

Post by mario52 »

Bonjour
denisfr wrote: Le gros changement ce trouve dans la partie du calcul 3D, qui a été mis dans une fonction à part: affichage3D.
ça va certainement intéresser galou_breizh qui l' a codé.
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.
denisfr
Posts: 5
Joined: Tue Jan 08, 2013 5:08 pm

Re: Cercle Circonscrit 3D

Post by denisfr »

Bonjour,

C'est bien vous qui avez créer le wiki?
mario52
Veteran
Posts: 4692
Joined: Wed May 16, 2012 2:13 pm

Re: Cercle Circonscrit 3D

Post by mario52 »

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
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.
Post Reply