Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYEtageEditor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
21 #include <qmessagebox.h>
22 #include <qdialog.h>
23 #include <qlayout.h>
24 #include <qlabel.h>
25 #include <qpushbutton.h>
26 #include <qbuttongroup.h>
27 // Added by qt3to4:
28 #include <QHBoxLayout>
29 #include <QGridLayout>
30 #include <QGroupBox>
31 
49 #include "TYEtageEditor.h"
50 
51 #define TR(id) OLocalizator::getString("TYEtageEditor", (id))
52 
54 {
55  _dispDist = true;
56 
57  QObject::connect(this, &TYEtageEditor::endedSavingPoints, this, &TYEtageEditor::endEtage);
58 }
59 
61 
63 {
64  bool invalid = false;
65  bool onlyEcran = false;
66  TYTabPoint tabPts = this->getSavedPoints();
67 
68  if (!(getSavedPoints().size() > 1) || (!_pModeler->askForResetResultat()))
69  {
70  return;
71  }
72 
73  // Test validity of polyline
74  if (tabPts.size() >= 3)
75  {
76  // On teste si la polyligne ne se coupe pas elle-meme...
77  invalid = testCrossSegment(tabPts, onlyEcran);
78  }
79  else
80  {
81  // Pas assez de points pour faire un etage
82  onlyEcran = true;
83  }
84 
85  if (invalid)
86  {
87  writeDebugMsg("Etage invalide !!!");
88  QMessageBox::warning(_pModeler, TR("id_caption"), TR("id_msg_etage_invalid"));
89  return;
90  }
91  else
92  {
93  forceNormals(tabPts);
94  writeDebugMsg("Etage valide !!!");
95  }
96 
97  TYEtageEditorPropertiesDlg* pDlg = new TYEtageEditorPropertiesDlg(_pModeler, tabPts, onlyEcran);
98 
99  // Affiche la boite de dialogue
100  int ret = pDlg->exec();
101 
102  if (ret == QDialog::Accepted)
103  {
104  double hauteur = pDlg->getHauteur();
105  double epaisseur = pDlg->getEpaisseur();
106  bool closed = pDlg->etageSelected();
107 
108  if (hauteur <= 0)
109  {
110  return;
111  }
112 
113  // Compute volume's center position
114  TYRepere rep;
115  computeCenter(pDlg->getHauteurSol(), tabPts, rep);
116 
117  if (closed) // Build an etage...
118  {
119  buildFloor(tabPts, rep, hauteur, closed);
120  }
121  else // Build an "Ecran"
122  {
123  buildScreen(tabPts, rep, hauteur, epaisseur);
124  }
125 
126  // repasse en mode camera selection
127  // XXX The bug goes here
129  }
130 }
131 
132 bool TYEtageEditor::testCrossSegment(TYTabPoint& tabPts, bool& onlyEcran)
133 {
134  TYPoint pt;
135  bool invalid(false);
136  size_t nbPts = tabPts.size();
137 
138  for (size_t i = 0; (i < nbPts) && !invalid; i++)
139  {
140  TYSegment seg1(tabPts[i], tabPts[(i + 1) % nbPts]);
141 
142  for (size_t j = 0; (j < nbPts) && !invalid; j++)
143  {
144  TYSegment seg2(tabPts[j], tabPts[(j + 1) % nbPts]);
145  // Test if at least one vertex is in common
146  if ((seg1._ptA != seg2._ptA) && (seg1._ptB != seg2._ptB) && (seg1._ptA != seg2._ptB) &&
147  (seg1._ptB != seg2._ptA))
148  {
149  // Test si il y a intersection
150  if (seg1.intersects(seg2, pt, TYSEUILCONFONDUS) != INTERS_NULLE)
151  {
152  // Si l'intersection intervient entre les points extremes du tab
153  if ((i == nbPts - 1) || (j == nbPts - 1))
154  {
155  onlyEcran = true;
156  }
157  else
158  {
159  invalid = true;
160  }
161  }
162  }
163  }
164  }
165 
166  return invalid;
167 }
168 
170 {
171  if (tabPts.size() > 2)
172  {
173  // Si l'etage est valide, on teste le sens de construction (pour les etages uniquement):
174  // ==> si la somme des produits croises des segments est negative, le sens de construction est correct
175  // Sinon, on inverse le sens des points du dernier au premier
176  double somme = 0;
177  for (unsigned int i = 1; i < tabPts.size() - 1; i++)
178  {
179  OVector3D v1(tabPts[i - 1], tabPts[i]);
180  OVector3D v2(tabPts[i], tabPts[i + 1]);
181  v1.normalize();
182  v2.normalize();
183 
184  somme = somme + v1.cross(v2)._z;
185  }
186 
187  if (somme > 0) // Inversion du sens de construction
188  {
189  TYTabPoint tabPtsTemp = tabPts;
190  tabPts.clear();
191  vector<TYPoint>::reverse_iterator it;
192  for (it = tabPtsTemp.rbegin(); it != tabPtsTemp.rend(); it++)
193  {
194  tabPts.push_back((*it));
195  }
196  }
197  }
198 }
199 
201 {
202  // L'etage, dans son repere, est en z=0
203  for (size_t i = 0; i < tabPts.size(); i++)
204  {
205  tabPts[i]._z = 0.0;
206  }
207 }
208 
209 void TYEtageEditor::computeCenter(const double initialOffset, TYTabPoint& tabPts, TYRepere& rep)
210 {
211  size_t nbPts = tabPts.size();
212 
213  // On calcul le centre de gravite de l'etage pour l'utiliser comme repere dans le bâtiment
214  OVector3D centre(0.0, 0.0, 0.0);
215 
216  // On effectue la moyenne en (X,Y) des points au sol
217  for (size_t i = 0; i < nbPts; i++)
218  {
219  centre._x += tabPts[i]._x;
220  centre._y += tabPts[i]._y;
221  }
222 
223  // Moyenne
224  centre._x /= nbPts;
225  centre._y /= nbPts;
226 
227  // On translate les points saisies en tenant compte du centre
228  for (size_t i = 0; i < nbPts; i++)
229  {
230  tabPts[i] = OVector3D(tabPts[i]) - centre;
231  }
232 
233  // Hauteur au sol saisie
234  centre._z = initialOffset;
235 
236  // Repere de l'etage dans le bâtiment
237  rep._origin = centre;
238 }
239 
240 void TYEtageEditor::buildFloor(TYTabPoint& tabPts, TYRepere& rep, double hauteur, bool closed)
241 {
242  LPTYEtage pEtage = new TYEtage();
243 
244  // Construction des murs
245  pEtage->setMurs(tabPts, hauteur, closed);
246 
247  // Recuperation ou construction du bâtiment
248  TYBatiment* pBat = NULL;
249  bool added = false;
250 
251  if (QString(_pModeler->metaObject()->className()).compare("TYBatimentModelerFrame") == 0)
252  {
253  pBat = ((TYBatimentModelerFrame*)_pModeler)->getBatiment();
254 
255  // Ajout de l'etage au bâtiment
256  if (pBat && (added = pBat->addAcousticVol((LPTYAcousticVolume&)pEtage, rep)))
257  {
258  // Action
259  TYAction* pAction = new TYAddAccVolToAccVolNodeAction((LPTYAcousticVolume&)pEtage, pBat,
260  _pModeler, TR("id_action_addetage"));
261  _pModeler->getActionManager()->addAction(pAction);
262  }
263  }
264  else if (QString(_pModeler->metaObject()->className()).compare("TYSiteModelerFrame") == 0)
265  {
266  pBat = new TYBatiment();
267  LPTYInfrastructure pInfra = ((TYSiteModelerFrame*)_pModeler)->getSite()->getInfrastructure();
268  pInfra->addBatiment(pBat, rep);
269 
270  // Ajout de l'etage au bâtiment
271  if (pBat && (added = pBat->addAcousticVol((LPTYAcousticVolume&)pEtage, TYRepere())))
272  {
273  // Action
274  TYAction* pAction =
275  new TYAddElementToInfraAction(pBat, pInfra, _pModeler, TR("id_action_addetage"));
276  _pModeler->getActionManager()->addAction(pAction);
277  }
278  else
279  {
280  pInfra->remBatiment(pBat);
281  }
282  }
283 
284  if (added && pBat)
285  {
286  // On ajoute ce bat a la selection du calcul courant
287  if (getTYApp()->getCurProjet() && _pModeler->isElementInCurrentProjet())
288  {
290 
291  if (pCalcul)
292  {
293  pCalcul->addToSelection(pBat);
294  }
295  }
297 
298  pBat->updateGraphicTree();
300 
301  // Update
303  }
304 }
305 
306 void TYEtageEditor::buildScreen(TYTabPoint& tabPts, TYRepere& rep, double height, double thickness)
307 {
308  LPTYEcran pEcran = new TYEcran();
309 
310  // Construction des murs
311  pEcran->setElements(tabPts, height, thickness);
312 
313  // Recuperation ou construction du bâtiment
314  TYBatiment* pBat = NULL;
315  bool added = false;
316 
317  if (QString(_pModeler->metaObject()->className()).compare("TYBatimentModelerFrame") == 0)
318  {
319  pBat = ((TYBatimentModelerFrame*)_pModeler)->getBatiment();
320 
321  // Ajout de l'ecran au bâtiment
322  if (pBat && (added = pBat->addAcousticVol((LPTYAcousticVolume&)pEcran, rep)))
323  {
324  // Action
325  TYAction* pAction = new TYAddAccVolToAccVolNodeAction((LPTYAcousticVolume&)pEcran, pBat,
326  _pModeler, TR("id_action_addecran"));
327  _pModeler->getActionManager()->addAction(pAction);
328  }
329  }
330  else if (QString(_pModeler->metaObject()->className()).compare("TYSiteModelerFrame") == 0)
331  {
332  pBat = new TYBatiment();
333  LPTYInfrastructure pInfra = ((TYSiteModelerFrame*)_pModeler)->getSite()->getInfrastructure();
334  pInfra->addBatiment(pBat, rep);
335 
336  // Ajout de l'ecran a l'infrastructure...
337  if (pBat && (added = pBat->addAcousticVol((LPTYAcousticVolume&)pEcran, TYRepere())))
338  {
339  // Action
340  TYAction* pAction =
341  new TYAddElementToInfraAction(pBat, pInfra, _pModeler, TR("id_action_addecran"));
342  _pModeler->getActionManager()->addAction(pAction);
343  }
344  else
345  {
346  pInfra->remBatiment(pBat);
347  }
348  }
349 
350  if (added && pBat)
351  {
352  // On ajoute ce bat a la selection du calcul courant
353  if (getTYApp()->getCurProjet() && _pModeler->isElementInCurrentProjet())
354  {
356 
357  if (pCalcul)
358  {
359  pCalcul->addToSelection(pBat);
360  }
361  }
363 
365 
366  // Update
367  pBat->updateGraphicTree();
369  }
370 }
371 
372 // ********* PROPERTY DIALOG DEFINITION *********************
373 
375  : TYFormDialog(parent)
376 {
377  _pBatBtn = NULL;
378  _pEcranBtn = NULL;
379  _pEpaisseurLabelName = NULL;
380  _pEpaisseurLineEdit = NULL;
381  _pHauteurLineEdit = NULL;
382  _pHauteurSolLineEdit = NULL;
383 
384  this->setWindowTitle(TR("id_caption"));
385 
386  QGridLayout* pLayout = new QGridLayout();
387  setLayout(pLayout);
388 
389  // Hauteur
390  _pHauteurLayout = new QHBoxLayout();
391  _pHauteurLayout->setContentsMargins(10, 10, 10, 10);
392  pLayout->addLayout(_pHauteurLayout, 0, 0);
393  QLabel* pHauteurLabelName = new QLabel(this);
394  pHauteurLabelName->setText(TR("id_hauteur_label"));
395  _pHauteurLayout->addWidget(pHauteurLabelName);
396  _pHauteurLineEdit = new TYLineEdit(QString(), false, false, this);
397 
398  double hauteur = 5.0;
399  if (TYPreferenceManager::exists(TYDIRPREFERENCEMANAGER, "DefaultHMur"))
400  {
401  hauteur = TYPreferenceManager::getDouble(TYDIRPREFERENCEMANAGER, "DefaultHMur");
402  }
403  else
404  {
405  TYPreferenceManager::setDouble(TYDIRPREFERENCEMANAGER, "DefaultHMur", hauteur);
406  }
407 
408  _pHauteurLineEdit->setText(QString().setNum(hauteur, 'f', 2));
410 
411  // Epaisseur pour les ecrans
412  _pEpaisseurLayout = new QHBoxLayout();
413  _pEpaisseurLayout->setContentsMargins(10, 10, 10, 10);
414  pLayout->addLayout(_pEpaisseurLayout, 1, 0);
415  _pEpaisseurLabelName = new QLabel(this);
416  _pEpaisseurLabelName->setText(TR("id_epaisseur_ecran_label"));
418  _pEpaisseurLineEdit = new TYLineEdit(QString(), false, false, this);
419  _pEpaisseurLineEdit->setText(QString().setNum(0.0, 'f', 2));
420 
421  double epaisseur = 0.3;
422  if (TYPreferenceManager::exists(TYDIRPREFERENCEMANAGER, "DefaultWidthEcran"))
423  {
424  epaisseur = TYPreferenceManager::getDouble(TYDIRPREFERENCEMANAGER, "DefaultWidthEcran");
425  }
426  else
427  {
428  TYPreferenceManager::setDouble(TYDIRPREFERENCEMANAGER, "DefaultWidthEcran", epaisseur);
429  }
430 
431  _pEpaisseurLineEdit->setText(QString().setNum(epaisseur, 'f', 2));
432 
434  _pEpaisseurLabelName->setEnabled(false);
435  _pEpaisseurLineEdit->setEnabled(false);
436 
437  // Hauteur par rapport au sol
438  _pHauteurSolLayout = new QHBoxLayout();
439  _pHauteurSolLayout->setContentsMargins(10, 10, 10, 10);
440  pLayout->addLayout(_pHauteurSolLayout, 2, 0);
441  QLabel* pHauteurSolLabelName = new QLabel(this);
442  pHauteurSolLabelName->setText(TR("id_hauteur_sol_label"));
443  _pHauteurSolLayout->addWidget(pHauteurSolLabelName);
444  _pHauteurSolLineEdit = new TYLineEdit(QString(), true, false, this);
445  _pHauteurSolLineEdit->setText(QString().setNum(0.0, 'f', 2));
446 
448 
449  // Ecran ou bâtiment
450  _pEcranOuBatLayout = new QHBoxLayout();
451  _pEcranOuBatLayout->setContentsMargins(10, 10, 10, 10);
452  pLayout->addLayout(_pEcranOuBatLayout, 3, 0);
453 
454  QButtonGroup* pEcranOuBatBtnGroup = new QButtonGroup();
455  pEcranOuBatBtnGroup->setExclusive(true);
456  _pBatBtn = new QRadioButton(TR("id_bat_label"));
457  pEcranOuBatBtnGroup->addButton(_pBatBtn, 0);
458  _pEcranBtn = new QRadioButton(TR("id_ecran_label"));
459  pEcranOuBatBtnGroup->addButton(_pEcranBtn, 1);
460  _pBatBtn->setChecked(true);
461 
462  QGridLayout* groupBoxEcranOuBatLayout = new QGridLayout();
463  groupBoxEcranOuBatLayout->addWidget(_pBatBtn, 0, 0);
464  groupBoxEcranOuBatLayout->addWidget(_pEcranBtn, 0, 1);
465 
466  QGroupBox* groupBoxEcranOuBat = new QGroupBox();
467  groupBoxEcranOuBat->setTitle(TR(""));
468  groupBoxEcranOuBat->setLayout(groupBoxEcranOuBatLayout);
469 
470  _pEcranOuBatLayout->addWidget(groupBoxEcranOuBat);
471 
472  if (onlyEcran)
473  {
474  _pEcranBtn->setChecked(true);
475  _pEcranBtn->setEnabled(false);
476  _pBatBtn->setEnabled(false);
477  _pEpaisseurLabelName->setEnabled(true);
478  _pEpaisseurLineEdit->setEnabled(true);
479  }
480 
481  // Disambiguate the overloaded signals
482  void (QButtonGroup::*_qButtonGroup_clicked)(int) = &QButtonGroup::idClicked;
483 
484  QObject::connect(pEcranOuBatBtnGroup, _qButtonGroup_clicked, this,
486 
487  // Geometrie
488  _tabPtsW = new TabPointsWidget(tabPts, this);
489  _tabPtsW->update();
490  QHBoxLayout* tabPointsLayout = new QHBoxLayout();
491  tabPointsLayout->setContentsMargins(10, 10, 10, 10);
492  pLayout->addLayout(tabPointsLayout, 4, 0);
493  tabPointsLayout->addWidget(_tabPtsW);
494 
495  // Btns Ok et Cancel
496  _pBtnLayout = new QHBoxLayout();
497  pLayout->addLayout(_pBtnLayout, 5, 0);
498 
499  _pBtnLayout->addStretch(1);
500 
501  // Ok
502  QPushButton* pButtonOK = new QPushButton(TR("id_ok_btn"), this);
503  pButtonOK->setDefault(true);
504  QObject::connect(pButtonOK, &QPushButton::clicked, this, &TYEtageEditorPropertiesDlg::accept);
505  _pBtnLayout->addWidget(pButtonOK);
506 
507  // Cancel
508  QPushButton* pButtonCancel = new QPushButton(TR("id_cancel_btn"), this);
509  pButtonCancel->setShortcut(Qt::Key_Escape);
510  QObject::connect(pButtonCancel, &QPushButton::clicked, this, &TYEtageEditorPropertiesDlg::reject);
511  _pBtnLayout->addWidget(pButtonCancel);
512 }
513 
515 {
516  // QObject::disconnect(_pBatBtn, &QPushButton::clicked, this, &TYEtageEditor::toggleEtage);
517 
518  delete _pHauteurLayout;
519  delete _pHauteurSolLayout;
520  delete _pEpaisseurLayout;
521  delete _pEcranOuBatLayout;
522  delete _pBtnLayout;
523  _pBatBtn = NULL;
524  _pEcranBtn = NULL;
525  _pEpaisseurLabelName = NULL;
526  _pEpaisseurLineEdit = NULL;
527  _pHauteurLineEdit = NULL;
528  _pHauteurSolLineEdit = NULL;
529 }
530 
532 {
533  if (_pEcranBtn->isChecked())
534  {
535  _pEpaisseurLabelName->setEnabled(true);
536  _pEpaisseurLineEdit->setEnabled(true);
537  }
538  else
539  {
540  _pEpaisseurLabelName->setEnabled(false);
541  _pEpaisseurLineEdit->setEnabled(false);
542  }
543 }
544 
546 {
547  _tabPtsW->apply();
548  QDialog::accept();
549 }
All base classes related to 3D manipulation.
#define TYSEUILCONFONDUS
Definition: 3d.h:47
#define INTERS_NULLE
No intersection.
Definition: 3d.h:35
fichier contenant differents types d'actions (fichier header)
TYApplication * getTYApp()
Retourne le pointeur sur l'application.
void writeDebugMsg(QString msg)
Affiche un message de debug dans la fenetre de sortie.
TYMainWindow * getTYMainWnd()
Retourne le pointeur sur la fenetre principale.
pour l'application Tympan (fichier header)
Modeler specialisee pour l'edition des batiments (fichier header)
std::vector< TYPoint > TYTabPoint
Collection de TYPoint.
Definition: TYDefines.h:340
#define TYDIRPREFERENCEMANAGER
Definition: TYElement.h:52
#define TR(id)
Construit un etage a partir des points saisis (fichier header)
Fenetre principale de l'application Tympan (fichier header)
Classe Modeler specialisee pour l'edition des sites (fichier header)
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
double _z
z coordinate of OCoord3D
Definition: 3d.h:284
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
OPoint3D _origin
The origin point.
Definition: 3d.h:1279
OPoint3D _ptA
Point A of the segment.
Definition: 3d.h:1201
virtual int intersects(const OSegment3D &seg, OPoint3D &pt, double seuilConfondus) const
Return the intersection point with another segment.
Definition: 3d.cpp:1267
OPoint3D _ptB
Point B of the segment.
Definition: 3d.h:1203
The 3D vector class.
Definition: 3d.h:298
void normalize()
Normalizes this vector.
Definition: 3d.cpp:225
OVector3D cross(const OVector3D &vector) const
Cross product.
Definition: 3d.cpp:196
void refreshSiteFrame()
Rafraichit l'arborescence du TYSiteFrame.
TYModelerFrame * _pModeler
Le modeler associe a cet editor.
bool addAcousticVol(LPTYAcousticVolumeGeoNode pAccVolGeoNode, bool recursif=true)
void addAction(TYAction *pAction)
Ajoute une nouvelle action a l'historique.
Definit une action, necessaire pour la gestion de l'undo.
Definition: TYAction.h:37
ajout d'un volume acoustique a un ensemble de volumes acoustiques
Definition: TYActions.h:146
Ajout d'un element a une infrastructure.
Definition: TYActions.h:398
LPTYProjet getCurProjet()
Set/Get du projet courant.
Classe Modeler specialisee pour l'edition des batiments.
bool addToSelection(TYUUID id)
Adds the item to the selection of this Calculation.
Definition: TYCalcul.cpp:872
TYLineEdit * _pEpaisseurLineEdit
double getEpaisseur()
Retourne l'epaisseur saisie.
void toggleButton(int i)
Callback qd l'utilisateur selectionne la creation d'un ecran.
TYEtageEditorPropertiesDlg(QWidget *parent, TYTabPoint &tabPts, bool onlyEcran=false)
double getHauteurSol()
Retourne la hauteur au sol saisie.
Definition: TYEtageEditor.h:94
bool etageSelected()
Retourne si l'utilisateur a selectionne la construction d'un etage.
TabPointsWidget * _tabPtsW
TYLineEdit * _pHauteurSolLineEdit
double getHauteur()
Retourne la hauteur saisie.
Definition: TYEtageEditor.h:86
void initZ(TYTabPoint &tabPts)
TYEtageEditor(TYModelerFrame *pModeler)
bool testCrossSegment(TYTabPoint &tabPts, bool &onlyEcran)
void computeCenter(const double initialOffset, TYTabPoint &tabPts, TYRepere &rep)
void buildScreen(TYTabPoint &tabPts, TYRepere &rep, double height, double thickness)
void buildFloor(TYTabPoint &tabPts, TYRepere &rep, double hauteur, bool closed)
void endEtage()
Construit un etage a partir des points saisis.
void forceNormals(TYTabPoint &tabPts)
bool setMurs(const TYTabPoint &tabPts, double hauteur=2.0, bool close=true)
Definition: TYEtage.cpp:875
bool addBatiment(LPTYBatimentGeoNode pBatimentGeoNode)
bool remBatiment(const LPTYBatimentGeoNode pBatimentGeoNode)
void setDefaultCameraMode()
Classe generique pour une fenetre de modeleur.
TYRenderWindowInteractor * getView()
TYActionManager * getActionManager()
bool isElementInCurrentProjet()
bool askForResetResultat()
virtual void updateView(bool clipping=true, bool axesAndGrid=true)
void updateDisplayList(void)
gestion de l'edition d'une polyligne
void endedSavingPoints()
TYTabPoint & getSavedPoints()
bool _dispDist
Indique si l'information de distance doit etre affichee ou non.
LPTYCalcul getCurrentCalcul()
Set/Get du pointeur du Calcul courant.
Definition: TYProjet.h:426
TYOpenGLRenderer * getRenderer()
Classe Modeler specialisee pour l'edition des sites.
virtual void apply()
virtual void update()