Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYSetGeometriqueParcours.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 
16 /*
17  *
18  */
19 
20 #include <math.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 
27 #include "TYPointParcours.h"
28 #include <assert.h>
29 #include <algorithm>
30 
35 
36 // Return Value Description for Qsort compare
37 //< 0 elem1 less than elem2
38 // 0 elem1 equivalent to elem2
39 //> 0 elem1 greater than elem2
40 int compareTYPolyligneParcours(const void* p1, const void* p2)
41 {
44  int indexPointPoly1 = P1->indexePoint1();
45  int indexPointPoly2 = P2->indexePoint1();
46  assert(indexPointPoly1 >= 0);
47  assert(indexPointPoly2 >= 0);
48  // Si les 2 premiers indexes sont egaux, on regarde les suivants:
49  if (indexPointPoly1 == indexPointPoly2)
50  {
51  indexPointPoly1 = P1->indexePoint2();
52  indexPointPoly2 = P2->indexePoint2();
53  }
54  return (indexPointPoly1 - indexPointPoly2);
55 }
56 
58 {
59  // Copie des points
62  int i = 0, j = 0;
63  for (i = 0; i < _nNbPointTotal; i++)
64  {
65  _ListePoint[i] = geoIn._ListePoint[i];
66  }
67  // Copie des polylignes
70  for (i = 0; i < _nNbPolylines; i++)
71  {
73  for (j = 0; j < geoIn._ListePolylines[i].nombreDePoint(); j++)
74  {
75  // Copie le pointeur du point de la polyligne copiée:
77  }
78  }
79 }
80 
82 {
84  tmp = _ListePolylines[i];
86  _ListePolylines[j] = tmp;
87 }
88 
90 {
91  int nNbDoublons = 0;
92  // Cette methode elimine 2 sortes de segments:
93  // 1. segments bouclant sur le meme point
94  // 2. segments doubles (Ex: [P1,P2] & [P2,P1])
95  // Pour ce traitement, on trie la liste de polyligne de 2 facons:
96  // 1. l'indice du premier point doit etre le plus faible (swap au besoin dans chaque polyligne)
97  // 2. suivant la valeur du premier indice
98 
99  // 1. Swap des indexes de points si necessaire
100  int indexPoint1 = 0, indexPoint2 = 0, i = 0, j = 0;
101  for (i = 0; i < _nNbPolylines; i++)
102  {
103  assert(_ListePolylines[i].nombreDePoint() == 2);
104  indexPoint1 = _ListePolylines[i].indexePoint1();
105  indexPoint2 = _ListePolylines[i].indexePoint2();
106  assert(indexPoint1 >= 0);
107  assert(indexPoint2 >= 0);
108  if (indexPoint1 > indexPoint2)
109  {
110  // Swap
111  _ListePolylines[i].setPoint(0, &(_ListePoint[indexPoint2]));
112  _ListePolylines[i].setPoint(1, &(_ListePoint[indexPoint1]));
113  }
114  }
115  // 2. QSort sur les polylignes (base sur le fait que toutes les polylignes contiennent 2 points
116  // exactement)
117  qsort((void*)_ListePolylines, (size_t)_nNbPolylines, sizeof(TYPolyligneParcours),
119 
120  // 3."Suppression" des segments ayant les memes indexes
121  i = 0;
122  j = 1;
123  int nOldNbPolylines = _nNbPolylines;
124  while (i < _nNbPolylines)
125  {
126  indexPoint1 = _ListePolylines[i].indexePoint1();
127  indexPoint2 = _ListePolylines[i].indexePoint2();
128  while (j < nOldNbPolylines && indexPoint1 == _ListePolylines[j].indexePoint1() &&
129  indexPoint2 == _ListePolylines[j].indexePoint2())
130  {
131  _nNbPolylines--;
132  nNbDoublons++;
133  j++;
134  }
135  i++;
136  if (i != j && j < nOldNbPolylines)
137  {
139  }
140  j++;
141  }
142 
143  // 4."Suppression" des segments bouclant sur le meme point
144  for (i = 0; i < _nNbPolylines; i++)
145  {
146  indexPoint1 = _ListePolylines[i].indexePoint1();
147  indexPoint2 = _ListePolylines[i].indexePoint2();
148  if (indexPoint1 == indexPoint2)
149  {
150  if (i != (_nNbPolylines - 1))
151  {
153  }
154  i--; // reverifier si la nouvelle n'est pas redondante
155  _nNbPolylines--;
156  nNbDoublons++;
157  }
158  }
159 
160  return nNbDoublons;
161 }
162 
164 {
165  int i = 0, j = 0, index = 0, doublons = 0;
166  // 1. On modifie les identifiants des points doubles (on suppose qu'ils sont dans l'ordre):
167  for (i = 0; i < _nNbPointTotal; i++)
168  {
169  for (j = i; j < _nNbPointTotal; j++)
170  {
171  // Ne pas merger les points appartenant a 2 types de courbes (infra & topo)
172  bool bPointAppartenantAuMemeType = ((_ListePoint[i].isEcran == _ListePoint[j].isEcran) &&
173  (_ListePoint[i].isInfra == _ListePoint[j].isInfra));
174  if ((bPointAppartenantAuMemeType) && (_ListePoint[j].Identifiant > i) &&
176  {
177  _ListePoint[j].Identifiant = -i; // les points inutilises ont des indexes negatifs
178  doublons++;
179  }
180  }
181  }
182  // 2. On modifie les ptr sur points des polylignes:
183  for (i = 0; i < _nNbPolylines; i++)
184  {
185  for (j = 0; j < _ListePolylines[i].nombreDePoint(); j++)
186  {
187  index = _ListePolylines[i].indexePoint(j);
188  do // attention, le point peut faire reference a un point lui-meme doublon (donc ayant un id
189  // negatif)
190  {
191  index = abs(index);
192  index = _ListePoint[index].Identifiant;
193  } while (index < 0);
194  _ListePolylines[i].setPoint(j, &(_ListePoint[index]));
195  }
196  }
197  return doublons;
198 }
199 
201  TYPointParcours& Srce, TYPointParcours& Dest, int* IndexePointsFrontiere, int& NbPointsFrontiere,
202  std::vector<bool>& pEstUnPointIntersectant, bool bCoteGauche, bool* PointsAGauche, bool* PointsADroite)
203 {
204  int i = 0, indexePoint = 0, indexePoint1 = 0, indexePoint2 = 0;
205  int nAncienNbPointTotal = _nNbPointTotal / 2; // cf SeparationDroiteGauche
206  // Initialisation
207  NbPointsFrontiere = 0;
208  pEstUnPointIntersectant.clear();
209  for (i = 0; i < _nNbPointTotal; i++)
210  {
211  pEstUnPointIntersectant.push_back(false);
212  }
213  for (i = 0; i < _nNbPolylines; i++)
214  {
215  // 1. Recherche des segments traversant [SR]
216  // Attention !! On considere que les polylignes ne sont que des segments (nb point = 2).
217  assert(2 == _ListePolylines[i].nombreDePoint());
218  // Indexe du point dans la liste de point:
219  indexePoint1 = _ListePolylines[i].indexePoint1();
220  indexePoint2 = _ListePolylines[i].indexePoint2();
221  // Est-ce qu'un des points est des deux cotes ?
222  if (PointsAGauche[indexePoint1] == PointsADroite[indexePoint1])
223  {
224  // Oui le marquer
225  pEstUnPointIntersectant[indexePoint1] = true;
226  IndexePointsFrontiere[NbPointsFrontiere] = indexePoint1;
227  NbPointsFrontiere++;
228  continue;
229  }
230  if (PointsAGauche[indexePoint2] == PointsADroite[indexePoint2])
231  {
232  // Oui le marquer
233  pEstUnPointIntersectant[indexePoint2] = true;
234  IndexePointsFrontiere[NbPointsFrontiere] = indexePoint2;
235  NbPointsFrontiere++;
236  continue;
237  }
238  // Y a-t-il passage de frontiere ?
239  bool b2PointsAGauche = PointsAGauche[indexePoint1] && PointsAGauche[indexePoint2];
240  bool b2PointsADroite = PointsADroite[indexePoint1] && PointsADroite[indexePoint2];
241  if (b2PointsAGauche || b2PointsADroite)
242  {
243  continue; // non
244  }
245  int nIndexePointFrontiereDansSegment = 0;
246  if (bCoteGauche)
247  {
248  nIndexePointFrontiereDansSegment = PointsADroite[indexePoint1] ? 0 : 1;
249  }
250  else
251  {
252  nIndexePointFrontiereDansSegment = PointsAGauche[indexePoint1] ? 0 : 1;
253  }
254  indexePoint = _ListePolylines[i].indexePoint(nIndexePointFrontiereDansSegment);
255  // Retenir l'autre point
256  // 2. Modification du point donnant lieu a un point frontiere
257  // Ce passage de frontiere peut donner lieu a 2 points d'intersections sur SR,
258  // si une autre polyligne rejoint ce point (indexePoint) de l'autre ci��te
259  //=> on cree un nouveau point ayant les memes coordonnees:
260  _ListePoint[nAncienNbPointTotal] = _ListePoint[indexePoint];
261  _ListePoint[nAncienNbPointTotal].Identifiant = nAncienNbPointTotal;
262  // Modifier la reference dans la polyligne
263  _ListePolylines[i].setPoint(nIndexePointFrontiereDansSegment, &(_ListePoint[nAncienNbPointTotal]));
264  indexePoint = nAncienNbPointTotal;
265  nAncienNbPointTotal++;
266 
267  // Marquer le point frontiere:
268  IndexePointsFrontiere[NbPointsFrontiere] = indexePoint;
269  pEstUnPointIntersectant[indexePoint] = true;
270  // Calculer l'intersection avec [SR]:
271  TYPointParcours::IntersectionDroites(Srce, Dest, _ListePoint[indexePoint1], _ListePoint[indexePoint2],
272  _ListePoint[indexePoint]);
273  NbPointsFrontiere++;
274  }
275 }
276 
278  bool*& PointsAGauche, bool*& PointsADroite)
279 {
280  // 1. Etablir une liste des points a droite, une autre de ceux a gauche
281  // Rq: on a 2 listes car on prend aussi les points sur la frontiere
282  // Inversion S-R si necessaire
283  // bool bSAGaucheDeR = ListePointSR[0].x < ListePointSR[1].x;
284  // Signe de l'angle
285  // sign = (vec1.cross(vec2)._z > 0) ? -1 : 1;
286  PointsAGauche = new bool[_nNbPointTotal];
287  PointsADroite = new bool[_nNbPointTotal];
288  TYPointParcours SR = Dest;
289  SR.x -= Srce.x;
290  SR.y -= Srce.y;
291  for (int i = 0; i < _nNbPointTotal; i++)
292  {
293  // Est-ce un point racine ?
294  if (_ListePoint[i].Identifiant == i)
295  {
297  SP.x -= Srce.x;
298  SP.y -= Srce.y;
299  PointsAGauche[i] = TYPointParcours::ZCross(SR, SP) > 0;
300  PointsADroite[i] = TYPointParcours::ZCross(SR, SP) < 0;
301  }
302  else
303  {
304  PointsAGauche[i] = false;
305  PointsADroite[i] = false;
306  }
307  }
308 }
309 
310 void TYSetGeometriqueParcours::SeparationDroiteGauche(bool* PointsAGauche, bool* PointsADroite,
311  TYSetGeometriqueParcours& geoGauche,
312  TYSetGeometriqueParcours& geoDroite, int compteurIter)
313 {
314  int i = 0, j = 0, indexePoint = 0;
315  // 2. Marquer les polylignes où au moins un point est a gauche (idem pour la droite)
316  bool* bAuMoinsUnPointAGauche = new bool[_nNbPolylines];
317  bool* bAuMoinsUnPointADroite = new bool[_nNbPolylines];
318  for (i = 0; i < _nNbPolylines; i++)
319  {
320  bAuMoinsUnPointAGauche[i] = false;
321  bAuMoinsUnPointADroite[i] = false;
322  // Cette polyligne a-t-elle au moins un point a gauche (/ droite)?
323  for (j = 0; j < _ListePolylines[i].nombreDePoint() &&
324  (!bAuMoinsUnPointADroite[i] || !bAuMoinsUnPointAGauche[i]);
325  j++)
326  {
327  indexePoint = _ListePolylines[i].indexePoint(j);
328  if (indexePoint < _nNbPointTotal)
329  {
330  bAuMoinsUnPointAGauche[i] = bAuMoinsUnPointAGauche[i] || PointsAGauche[indexePoint];
331  bAuMoinsUnPointADroite[i] = bAuMoinsUnPointADroite[i] || PointsADroite[indexePoint];
332  }
333  }
334  }
335  // 3. Les listes (geo) gauche, doite et principale doivent etre independantes
336  //=>on en cree de nouvelles
337  // Copie des points
338  // facteur 2 : precaution due au fait que les points a ramener a la frontiere peuvent donner 2 points
339  // d'intersection
340  geoGauche._ListePoint = new TYPointParcours[2 * _nNbPointTotal];
341  geoDroite._ListePoint = new TYPointParcours[2 * _nNbPointTotal];
342  for (i = 0; i < _nNbPointTotal; i++)
343  {
344  geoGauche._ListePoint[i] = _ListePoint[i];
345  geoDroite._ListePoint[i] = _ListePoint[i];
346  }
347  geoGauche._nNbPointTotal = 2 * _nNbPointTotal;
348  geoDroite._nNbPointTotal = 2 * _nNbPointTotal;
349  // Copie des polylignes
350  geoGauche.AllouerPolylignes(_nNbPolylines);
351  geoDroite.AllouerPolylignes(_nNbPolylines);
352  geoGauche._nNbPolylines = 0;
353  geoDroite._nNbPolylines = 0;
354 
355  for (i = 0; i < _nNbPolylines; i++)
356  {
357  // Fix issue #139
358  // Source and receptor have indexes of MAX_INT and MAX_INT-1
359  // They must not be processed here because it's useless and provokes outofbound access on static
360  // arrays
361  if (polyligneContientSouR(i))
362  {
363  continue;
364  }
365 
366  if (bAuMoinsUnPointAGauche[i])
367  {
368  // On ajoute cette polyligne
369  geoGauche._ListePolylines[geoGauche._nNbPolylines].allouer(_ListePolylines[i].nombreDePoint());
370  // Copie des references de point
371  for (j = 0; j < _ListePolylines[i].nombreDePoint(); j++)
372  {
373  // Indexe du point dans la liste de point:
374  indexePoint = _ListePolylines[i].indexePoint(j);
375  // Copie de la reference:
376  geoGauche._ListePolylines[geoGauche._nNbPolylines].ajoutePoint(
377  j, &(geoGauche._ListePoint[indexePoint]));
378  }
379  geoGauche._nNbPolylines++;
380  }
381  if (bAuMoinsUnPointADroite[i])
382  {
383  // On ajoute cette polyligne
384  geoDroite._ListePolylines[geoDroite._nNbPolylines].allouer(_ListePolylines[i].nombreDePoint());
385  // Copie des references de point
386  for (j = 0; j < _ListePolylines[i].nombreDePoint(); j++)
387  {
388  // Indexe du point dans la liste de point:
389  indexePoint = _ListePolylines[i].indexePoint(j);
390  // Copie de la reference:
391  geoDroite._ListePolylines[geoDroite._nNbPolylines].ajoutePoint(
392  j, &(geoDroite._ListePoint[indexePoint]));
393  }
394  geoDroite._nNbPolylines++;
395  }
396  }
397  // CherchePointsAGauche(PointsAGauche, geoGauche._ListePolylines, geoGauche._nNbPolylines,
398  // geoGauche._ListePoint, geoGauche._nNbPointTotal);
399  SAFE_DELETE_LIST(bAuMoinsUnPointAGauche);
400  SAFE_DELETE_LIST(bAuMoinsUnPointADroite);
401 }
402 
404 {
405  bool ret = false;
406  for (int j = 0; j < _ListePolylines[i].nombreDePoint(); j++)
407  {
408  if (_ListePolylines[i].indexePoint(j) >= _nNbPointTotal)
409  {
410  ret = true;
411  break;
412  }
413  }
414  return ret;
415 }
416 
417 // Return Value Description for Qsort compare
418 //< 0 elem1 less than elem2
419 // 0 elem1 equivalent to elem2
420 //> 0 elem1 greater than elem2
421 int compareAbscissesCurvilignes(const void* p1, const void* p2)
422 {
426  int e1 = *((int*)(p1));
427  int e2 = *((int*)(p2));
428  TYPointParcours& P1 = ListePoint[e1];
429  TYPointParcours& P2 = ListePoint[e2];
430 
431  double dAbscisseCurviligneCP1 = TYPointParcours::AbscisseCurviligneCarreSurSR(P1, *Srce, *Dest);
432  double dAbscisseCurviligneCP2 = TYPointParcours::AbscisseCurviligneCarreSurSR(P2, *Srce, *Dest);
433 
434  if (dAbscisseCurviligneCP1 < dAbscisseCurviligneCP2)
435  {
436  return -1;
437  }
438  if (dAbscisseCurviligneCP1 > dAbscisseCurviligneCP2)
439  {
440  return 1;
441  }
442  return 0;
443 }
444 
446  int* IndexePointsFrontiere,
447  int NbPointsFrontiere)
448 {
449  // int i;
450  // TYPointParcours* P;
451  // double PDist;
452 
453  if (NbPointsFrontiere == 0)
454  {
455  return;
456  }
457 
458  /*
459  for(i=0; i < NbPointsFrontiere;i++)
460  {
461  P = &(_ListePoint[IndexePointsFrontiere[i]]);
462  if (P != NULL)
463  PDist = fabs(P->x - Srce.x) + fabs(P->y-Srce.y);
464  }
465  */
466  // Quick Sort
471  qsort((void*)IndexePointsFrontiere, (size_t)NbPointsFrontiere, sizeof(int), compareAbscissesCurvilignes);
473  // qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void
474  // *elem2 ) );
475 
476  /*
477  for(i=0; i < NbPointsFrontiere;i++)
478  {
479  P = &(_ListePoint[IndexePointsFrontiere[i]]);
480  if (P != NULL)
481  PDist = fabs(P->x - Srce.x) + fabs(P->y-Srce.y);
482  }
483  */
484 }
485 
487 {
488  assert(_ListePolylines);
489  assert(_ListePoint);
490  // Enregistrement du point:
492  _ListePolylines[indexPolyligne].ajoutePoint(_ListePolylines[indexPolyligne].nombreDePoint(),
494  _nNbPointTotal++;
495  return true;
496 }
497 
499  TYPolyligneParcours*& PolyligneRacine,
500  std::vector<bool>& pEstUnPointIntersectant,
501  TYSetGeometriqueParcours& geoPremierePasse)
502 {
503  int IndexPoint = IndexPointRacine;
504  int IndexPointSuivant = 0;
505  // Cette methode ajoute les points rencontres sur la polyligne racine, dans le sens impose par le point
506  // racine Le point racine est-il le premier ou le second point de la polyligne racine ?
507  TYPolyligneParcours* PolyligneCourante = PolyligneRacine;
508  TYPolyligneParcours* PolyligneSuivante = PolyligneCourante;
509  do
510  {
511  // Memorisons la derniere polyligne non nulle:
512  PolyligneRacine = PolyligneCourante;
513  IndexPointSuivant = PolyligneCourante->indexePointSuivant(IndexPoint, PolyligneSuivante);
514  // Enregistrer l'autre point du segment
515  geoPremierePasse.AjoutePointALaPolyLigne(0, _ListePoint[IndexPointSuivant]);
516  IndexPoint = IndexPointSuivant;
517  } while (NULL != PolyligneSuivante && !pEstUnPointIntersectant[IndexPoint] &&
518  (PolyligneCourante = PolyligneSuivante));
519 
520  return IndexPoint;
521 }
522 
524 {
525  // Verifier que toutes les polylignes d'infra sont fermees, exceptees les ecrans
526  for (int i = 0; i < _nNbPolylines; i++)
527  {
528  if (_ListePolylines[i].isInfra() && !_ListePolylines[i].isEcran())
529  {
530  if (!_ListePolylines[i].estSurUnParcourFermee())
531  {
532  return false;
533  }
534  }
535  }
536  return true;
537 }
538 
540  std::vector<bool>& pEstUnPointIntersectant)
541 {
542  // Cette methode rempli la structure Connexes, attribut de chaque point:
543  int i = 0, j = 0;
544  // Initialiser la liste
545  for (i = 0; i < this->_nNbPointTotal; i++)
546  {
547  Connexes[i].IndexesSegment[0] = -1; // Premier segment incluant ce point
548  Connexes[i].IndexesSegment[1] = -1; // Second segment incluant ce point
549  Connexes[i].NbSegmentsConnexes = 0; // Nb de segment incluant ce point
550  }
551  // Pour chaque polyligne, construire une liste de points connexes :
552  // on renseigne les champs NbSegmentsConnexes & IndexesSegment
553  int indexePoint = 0;
554  for (i = 0; i < _nNbPolylines; i++)
555  {
556  assert(_ListePolylines[i].nombreDePoint() == 2);
557  for (j = 0; j < _ListePolylines[i].nombreDePoint(); j++)
558  {
559  indexePoint = _ListePolylines[i].indexePoint(j);
560  int NbSegmentsConnexes = Connexes[indexePoint].NbSegmentsConnexes;
561  // A-t-on deja 2 segments connexes pour ce point ?
562  if (NbSegmentsConnexes >= 2)
563  {
564  // Oui=>il faudrait dedoubler ce point
565  TYPointParcours* _newListePoint = new TYPointParcours[_nNbPointTotal + 1];
566  std::copy(_ListePoint, _ListePoint + _nNbPointTotal, _newListePoint);
567  for (int a = 0; a < _nNbPolylines; a++)
568  {
569  for (int b = 0; b < _ListePolylines[a].nombreDePoint(); b++)
570  {
571  int index = _ListePolylines[a].indexePoint(b);
572  _ListePolylines[a].setPoint(b, &(_newListePoint[index]));
573  }
574  }
575  delete[] _ListePoint;
576  _ListePoint = _newListePoint;
577  Connexite* newConnexes = new Connexite[_nNbPointTotal + 1];
578  std::copy(Connexes, Connexes + _nNbPointTotal, newConnexes);
579  delete[] Connexes;
580  Connexes = newConnexes;
581 
583  p->isInfra = _ListePoint[indexePoint].isInfra;
584  p->isEcran = _ListePoint[indexePoint].isEcran;
585  p->x = _ListePoint[indexePoint].x;
586  p->y = _ListePoint[indexePoint].y;
587  p->z = _ListePoint[indexePoint].z;
589  _ListePolylines[i].setPoint(j, p);
590 
591  newConnexes[_nNbPointTotal].IndexesSegment[0] = -1; // Premier segment incluant ce point
592  newConnexes[_nNbPointTotal].IndexesSegment[1] = -1; // Second segment incluant ce point
593  newConnexes[_nNbPointTotal].NbSegmentsConnexes = 0; // Nb de segment incluant ce point
594  NbSegmentsConnexes = 0;
595 
596  // Fix issue #91 : array _estUnPointIntersectant must be extended
597  pEstUnPointIntersectant.push_back(pEstUnPointIntersectant[indexePoint]);
598 
599  indexePoint = _nNbPointTotal;
600  _nNbPointTotal++;
602  assert(NbSegmentsConnexes < 2);
603  }
604  Connexes[indexePoint].IndexesSegment[NbSegmentsConnexes] = i;
605  Connexes[indexePoint].NbSegmentsConnexes++;
606  }
607  }
608  // Pour faciliter le parcours, on affecte le ptr sur les polylignes voisines de la courante
609  //=> on renseigne les champs _PolyligneP0 & _PolyligneP1
610  for (i = 0; i < _nNbPolylines; i++)
611  {
612  //_PolyligneP0 & _PolyligneP1 pointent imperativement:
613  //- sur une autre polyligne que la courante
614  //- sur 2 polylignes differentes (sauf si aucune polyligne voisine)
615  assert(_ListePolylines[i].nombreDePoint() == 2);
616  // Creons des alias de type tableau sur les voisines _PolyligneP0 & _PolyligneP1
617  TYPolyligneParcours** pPolylignesVoisines[2];
618  pPolylignesVoisines[0] = &(_ListePolylines[i]._PolyligneP0);
619  pPolylignesVoisines[1] = &(_ListePolylines[i]._PolyligneP1);
620  int NbSegmentsConnexes = Connexes[indexePoint].NbSegmentsConnexes; // verification supplementaire
621 
622  for (j = 0; j < 2; j++) // test enleve pour tester que pPolylignesVoisines[j] vaut bien NULL
623  {
624  assert((*pPolylignesVoisines[j]) == NULL); // l'initialisation devrait etre deja faite
625  // On s'occupe des segments connexes au point j du segment courant
626  int IndexePj = _ListePolylines[i].indexePoint(j);
627  // Premier segment connexe
628  int indexeSegmentj = Connexes[IndexePj].IndexesSegment[0];
629  if (indexeSegmentj != i && indexeSegmentj != -1) // la voisine n'est ni la courante, ni
630  // inexistante
631  {
632  // Le premier segment connexe est un voisin acceptable
633  *(pPolylignesVoisines[j]) = &(_ListePolylines[indexeSegmentj]);
634  }
635  else
636  {
637  // Testons le second segment:
638  indexeSegmentj = Connexes[IndexePj].IndexesSegment[1];
639  if (indexeSegmentj != i && indexeSegmentj != -1)
640  // Le second segment connexe est un voisin acceptable
641  {
642  *(pPolylignesVoisines[j]) = &(_ListePolylines[indexeSegmentj]);
643  }
644  else
645  {
646  *(pPolylignesVoisines[j]) = NULL; // par securite
647  }
648  }
649  NbSegmentsConnexes--;
650  }
651  // Verifions que les voisins des 2 points du segment ne sont pas les memes!
652  bool bP0P1PointentSurMemePolyligne =
654  bool bAssert = bP0P1PointentSurMemePolyligne ? (_ListePolylines[i]._PolyligneP0 == NULL) : true;
655 
656  assert(bAssert);
657  if (!bAssert)
658  {
659  bAssert = true;
660  }
661  }
662  return true;
663 }
664 
666  int* IndexePointsFrontiere, int NbPointsFrontiere,
667  std::vector<bool>& pEstUnPointIntersectant, Connexite* Connexes,
668  TYSetGeometriqueParcours& geoPremierePasse, int compteurIter)
669 {
670 
671  // Retourne false si on est enferme
672  // La premiere passe consiste en la creation d'un parcours longeant toutes les polylignes intersectantes
673  // 1. Ordonner les points d'intersection
674 
675  TriePointsIntersectionSuivantSR(Srce, Dest, IndexePointsFrontiere, NbPointsFrontiere);
676 
677  // 2.1 Trouver le premier point d'intersection apres S
678  int i = 0;
679  while (i < NbPointsFrontiere &&
680  TYPointParcours::Scalaire(Srce, _ListePoint[IndexePointsFrontiere[i]], Srce, Dest) < 0)
681  {
682  i++;
683  }
684  int PremierPointIntersection = i;
685  while (i < NbPointsFrontiere &&
686  TYPointParcours::Scalaire(Dest, _ListePoint[IndexePointsFrontiere[i]], Dest, Srce) > 0)
687  {
688  i++;
689  }
690  int DernierPointIntersection = i;
691 
692  int nbPt = _nNbPointTotal;
693  nbPt = 4 * _nNbPointTotal; // au pire, on parcours tout 2 fois
694 
695  // 3. Allouer de la memoire pour les points du trajet
696  geoPremierePasse._ListePolylines = new TYPolyligneParcours[1];
697  geoPremierePasse._ListePolylines[0].allouer(nbPt);
698  geoPremierePasse._ListePoint = new TYPointParcours[nbPt];
699  geoPremierePasse._nNbPointTotal = 0;
700  geoPremierePasse._nNbPolylines = 1;
701 
702  // 4. Parcourir les polylignes
703  geoPremierePasse.AjoutePointALaPolyLigne(0, Srce);
704  for (i = PremierPointIntersection; i < DernierPointIntersection; i++)
705  {
706  // Le point suivant du parcourt est la prochaine intersection:
707  int IndexPoint = IndexePointsFrontiere[i];
708  // A quelle polyligne appartient ce point ?
709  int indexPolyligne = Connexes[IndexPoint].IndexesSegment[0];
710  TYPolyligneParcours* PolyligneCourante = &(_ListePolylines[indexPolyligne]);
711  // Il faut parcourir cette polyligne et ses connexes pour en enregistrer les points
712  // Attention au sens, car le point d'intersection peut etre le second de la polyligne
713  // On enregistre pas le point racine:
714  geoPremierePasse.AjoutePointALaPolyLigne(0, _ListePoint[IndexPoint]);
715  IndexPoint = ParcourtPolyligneAPartirDe(IndexPoint, PolyligneCourante, pEstUnPointIntersectant,
716  geoPremierePasse);
717  // Le dernier point est-il un point d'intersection ?
718  if (pEstUnPointIntersectant[IndexPoint])
719  {
720  // On finit par un point d'intersection
721  // Est-il derriere S ?
722  if (TYPointParcours::Scalaire(Srce, _ListePoint[IndexPoint], Srce, Dest) < 0)
723  // Oui=>retourner faux car on est emprisonne
724  {
725  return false;
726  }
727  // Est-il devant R ?
728  if (TYPointParcours::Scalaire(Dest, _ListePoint[IndexPoint], Dest, Srce) < 0)
729  // Oui=>retourner faux car on est emprisonne
730  {
731  return false;
732  }
733  // On a peut etre passe d'autres points d'intersection: tant mieux !
734  // Mais il faut savoir où on en est dans les points d'intersection:
735  while (i < NbPointsFrontiere && IndexPoint != IndexePointsFrontiere[i])
736  {
737  i++;
738  }
739  }
740  else
741  {
742  // On ne finit pas par un point d'intersection
743  if (!PolyligneCourante->isEcran())
744  {
745  // TODO : return false implique qu'aucun chemin n'est valide, mais cette condition ne concerne
746  // pas tous les points !
747  return false; // on considere que le rayon est parti dans la nature
748  }
749  //=>il faut parcourir la polyligne courante dans l'autre sens
750  IndexPoint = ParcourtPolyligneAPartirDe(IndexPoint, PolyligneCourante, pEstUnPointIntersectant,
751  geoPremierePasse);
752  }
753  }
754  // Ajout du recepteur
755  geoPremierePasse.AjoutePointALaPolyLigne(0, Dest);
756  return true;
757 }
758 
760  TYSetGeometriqueParcours& geoSecondePasse,
761  bool bTrajetsAGaucheDeSR, TYPointParcours**& pTableauEC,
762  int& nbPtsEC, int compteurIter, bool bIsLastSecondePasse)
763 {
764  compteurIter++;
765  int i = 0;
766 
767  if (!bIsLastSecondePasse && compteurIter > 2)
768  {
769  return false;
770  }
771 
772  // 1. Calcul de l'EC de geoPremierePasse
773  // 1.1 Recuperer les points de la premiere passe
774  int nNbPointsPremierePasse = geoPremierePasse._nNbPointTotal;
775 
776  // XBH : 12/10/2004 - if nothing to compute, exit now!
777  if (nNbPointsPremierePasse == 0)
778  {
779  return false;
780  }
781 
782  TYPointParcours** TableauDePointsPremierePasse = new TYPointParcours*[nNbPointsPremierePasse];
783  for (i = 0; i < nNbPointsPremierePasse; i++)
784  {
785  TableauDePointsPremierePasse[i] = &(geoPremierePasse._ListePoint[i]);
786  }
787  // calcul de l'EC de cet ensemble
788  TYPointParcours** TableauDePointsEC = new TYPointParcours*[nNbPointsPremierePasse];
789  int nNbPointsEC = 0;
790 
791  // Mettons R en seconde position dans le tableau (exige pour le calcul d'EC)
792  TYPointParcours* pRecepteur = TableauDePointsPremierePasse[nNbPointsPremierePasse - 1];
793  TableauDePointsPremierePasse[nNbPointsPremierePasse - 1] = TableauDePointsPremierePasse[1];
794  TableauDePointsPremierePasse[1] = pRecepteur;
795 
796  // Sens de parcours S->R
797  int indexS = 0;
798  int indexR = 1;
799  bool bSaGaucheDeR = TableauDePointsPremierePasse[indexS]->x < TableauDePointsPremierePasse[indexR]->x;
800 
801  bool premierPtsLesPlusHauts = bTrajetsAGaucheDeSR != bSaGaucheDeR;
802 
804  TableauDePointsPremierePasse, nNbPointsPremierePasse, TableauDePointsEC, premierPtsLesPlusHauts);
805 
806  SAFE_DELETE_LIST(TableauDePointsPremierePasse);
807  // 2. Parcours de l'EC, et choix du trajet sans intersection
808  // 2.1. Allouer de la memoire pour les points du trajet
809  int nNbPointAlloue = nNbPointsEC * nNbPointsPremierePasse * 4;
810  geoSecondePasse.Clean();
811  geoSecondePasse._ListePolylines = new TYPolyligneParcours[1]; // 1 seule polyligne
812  geoSecondePasse._ListePolylines[0].allouer(nNbPointAlloue); // allouer assez de points!
813  geoSecondePasse._ListePoint = new TYPointParcours[nNbPointAlloue];
814  geoSecondePasse._nNbPointTotal = 0;
815  geoSecondePasse._nNbPolylines = 1;
816  // 2.2. Ajouter les points de S vers R
817  // Les points doivent etre ordonnes de S vers R
818  bool bOrdonneDeSversR =
819  (TableauDePointsEC[0]->Identifiant == geoPremierePasse._ListePolylines[0].indexePoint(0));
820  if (!bOrdonneDeSversR)
821  {
822  InverseOrdreDesPoints(TableauDePointsEC, nNbPointsEC);
823  }
824  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[0]);
825  int nVerifNbPointsAjoutes = 1;
826  int nbPts = nNbPointsEC;
827  for (i = 1; i < nbPts; i++)
828  {
829  if (!bIsLastSecondePasse && (compteurIter < 2) &&
830  this->intersects(*TableauDePointsEC[i - 1], *TableauDePointsEC[i]))
831  {
832  TYSetGeometriqueParcours nouvellePremierePasse;
833  TYSetGeometriqueParcours nouvelleSecondePasse;
834 
835  // Tentative différente, si il y a un obstacle, on refait une premiere passe
836  int* IndexePointsFrontiere = new int[_nNbPointTotal];
837  int NbPointsFrontiere = 0;
838  bool* PointsAGauche = nullptr;
839  bool* PointsADroite = nullptr;
840  TYPointParcours** pTableauECG = nullptr;
841  TYPointParcours** pTableauECD = nullptr;
842  int nbPtsECD = 0;
843  int nbPtsECG = 0;
844  TYSetGeometriqueParcours geoGauche;
845  TYSetGeometriqueParcours geoDroite;
846 
847  MarquePointsADroiteEtAGauche(*TableauDePointsEC[i - 1], *TableauDePointsEC[i], PointsAGauche,
848  PointsADroite);
849  SeparationDroiteGauche(PointsAGauche, PointsADroite, geoGauche, geoDroite, false);
850 
851  std::vector<bool> estUnPointIntersectant;
852 
853  if (bTrajetsAGaucheDeSR)
854  {
855  geoGauche.RamenerPointsTraversantLaFrontiere(*TableauDePointsEC[i - 1], *TableauDePointsEC[i],
856  IndexePointsFrontiere, NbPointsFrontiere,
857  estUnPointIntersectant, bTrajetsAGaucheDeSR,
858  PointsAGauche, PointsADroite);
859  Connexite* Connexes = new Connexite[geoGauche._nNbPointTotal];
860  bool bOk = geoGauche.ListerPointsConnexes(Connexes, estUnPointIntersectant);
861  if (!bOk)
862  {
863  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
864  nVerifNbPointsAjoutes++;
865  SAFE_DELETE_LIST(Connexes);
866  SAFE_DELETE_LIST(pTableauECG);
867  continue;
868  }
869  bool bPasEnferme = geoGauche.PremierePasse(
870  *TableauDePointsEC[i - 1], *TableauDePointsEC[i], IndexePointsFrontiere,
871  NbPointsFrontiere, estUnPointIntersectant, Connexes, nouvellePremierePasse, compteurIter);
872  if (!bPasEnferme)
873  {
874  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
875  nVerifNbPointsAjoutes++;
876  SAFE_DELETE_LIST(Connexes);
877  SAFE_DELETE_LIST(pTableauECG);
878  continue;
879  }
880  bool bSecondePasseOk =
881  geoGauche.SecondePasse(nouvellePremierePasse, nouvelleSecondePasse, bTrajetsAGaucheDeSR,
882  pTableauECG, nbPtsECG, compteurIter);
883  if (!bSecondePasseOk)
884  {
885  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
886  nVerifNbPointsAjoutes++;
887  SAFE_DELETE_LIST(Connexes);
888  SAFE_DELETE_LIST(pTableauECG);
889  continue;
890  }
891 
892  int nNbPointNouvelleSecondePasse = nouvelleSecondePasse._nNbPointTotal;
893  // Si on dépasse la taille allouée au tableau de points alors il faut l'étendre
894  if (nVerifNbPointsAjoutes + nNbPointNouvelleSecondePasse >
895  geoSecondePasse._ListePolylines[0].getnNbPointAlloue())
896  {
897  int nouvelleTaille = nVerifNbPointsAjoutes + (nbPts - i) * nNbPointNouvelleSecondePasse;
898  geoSecondePasse._ListePolylines[0].extendPtrPoints(nouvelleTaille);
899  geoSecondePasse.extendListePoint(nouvelleTaille);
900  }
901  for (int j = 1; j < nouvelleSecondePasse._nNbPointTotal; j++)
902  {
903  geoSecondePasse.AjoutePointALaPolyLigne(0, nouvelleSecondePasse._ListePoint[j]);
904  nVerifNbPointsAjoutes++;
905  }
906  SAFE_DELETE_LIST(Connexes);
907  SAFE_DELETE_LIST(pTableauECG);
908  }
909  else
910  {
911  geoDroite.RamenerPointsTraversantLaFrontiere(*TableauDePointsEC[i - 1], *TableauDePointsEC[i],
912  IndexePointsFrontiere, NbPointsFrontiere,
913  estUnPointIntersectant, bTrajetsAGaucheDeSR,
914  PointsAGauche, PointsADroite);
915  Connexite* Connexes = new Connexite[geoDroite._nNbPointTotal];
916  bool bOk = geoDroite.ListerPointsConnexes(Connexes, estUnPointIntersectant);
917  if (!bOk)
918  {
919  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
920  nVerifNbPointsAjoutes++;
921  SAFE_DELETE_LIST(Connexes);
922  SAFE_DELETE_LIST(pTableauECD);
923  continue;
924  }
925  bool bPasEnferme = geoDroite.PremierePasse(
926  *TableauDePointsEC[i - 1], *TableauDePointsEC[i], IndexePointsFrontiere,
927  NbPointsFrontiere, estUnPointIntersectant, Connexes, nouvellePremierePasse, compteurIter);
928  if (!bPasEnferme)
929  {
930  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
931  nVerifNbPointsAjoutes++;
932  SAFE_DELETE_LIST(Connexes);
933  SAFE_DELETE_LIST(pTableauECD);
934  continue;
935  }
936  bool bSecondePasseOk =
937  geoDroite.SecondePasse(nouvellePremierePasse, nouvelleSecondePasse, bTrajetsAGaucheDeSR,
938  pTableauECD, nbPtsECD, compteurIter);
939  if (!bSecondePasseOk)
940  {
941  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
942  nVerifNbPointsAjoutes++;
943  SAFE_DELETE_LIST(Connexes);
944  SAFE_DELETE_LIST(pTableauECD);
945  continue;
946  }
947 
948  int nNbPointNouvelleSecondePasse = nouvelleSecondePasse._nNbPointTotal;
949  // Si on dépasse la taille allouée au tableau de points alors il faut l'étendre
950  if (nVerifNbPointsAjoutes + nNbPointNouvelleSecondePasse >
951  geoSecondePasse._ListePolylines[0].getnNbPointAlloue())
952  {
953  int nouvelleTaille = nVerifNbPointsAjoutes + (nbPts - i) * nNbPointNouvelleSecondePasse;
954  geoSecondePasse._ListePolylines[0].extendPtrPoints(nouvelleTaille);
955  geoSecondePasse.extendListePoint(nouvelleTaille);
956  }
957  for (int j = 1; j < nouvelleSecondePasse._nNbPointTotal; j++)
958  {
959  geoSecondePasse.AjoutePointALaPolyLigne(0, nouvelleSecondePasse._ListePoint[j]);
960  nVerifNbPointsAjoutes++;
961  }
962 
963  SAFE_DELETE_LIST(Connexes);
964  SAFE_DELETE_LIST(pTableauECD);
965  }
966  }
967  else
968  {
969  geoSecondePasse.AjoutePointALaPolyLigne(0, *TableauDePointsEC[i]);
970  nVerifNbPointsAjoutes++;
971  }
972  }
973 
974  pTableauEC = TableauDePointsEC;
975  nbPtsEC = nNbPointsEC;
976  // xbh: do not delete here as long as we returned the pointer outside this function
977  // delete [] TableauDePointsEC;
978  return true;
979 }
980 
982  int nNbPointsDeLaListe)
983 {
984  for (int i = 0; i < nNbPointsDeLaListe / 2; i++)
985  {
986  TYPointParcours* pTmp = ListeDePointsAInverser[nNbPointsDeLaListe - 1 - i];
987  ListeDePointsAInverser[nNbPointsDeLaListe - 1 - i] = ListeDePointsAInverser[i];
988  ListeDePointsAInverser[i] = pTmp;
989  }
990 }
991 
993  int nIndexePoly, int nIndexeNbPremierPointAAjouter,
994  int nIndexeDernierPointAAjouter)
995 {
996  int nNbPointsAjoutes = 0;
997  // 1 Parcourir la polyligne source jusqu'a se positionner sur le premier point
998  TYPolyligneParcours* PolyligneSource = &(geoPolySource._ListePolylines[nIndexePoly]);
999 
1000  int i = 0;
1001  for (i = 0; i < PolyligneSource->nombreDePoint() &&
1002  PolyligneSource->indexePoint(i) != nIndexeNbPremierPointAAjouter;
1003  i++)
1004  {
1005  ;
1006  }
1007  for (i = i + 1; i < PolyligneSource->nombreDePoint(); i++)
1008  {
1009  TYPointParcours aTYPointParcours = PolyligneSource->point(i);
1010  AjoutePointALaPolyLigne(0, aTYPointParcours);
1011  nNbPointsAjoutes++;
1012  if (PolyligneSource->indexePoint(i) == nIndexeDernierPointAAjouter)
1013  {
1014  break;
1015  }
1016  }
1017  return nNbPointsAjoutes;
1018 }
1019 
1021 {
1022  // On regarde les intersections avec tous les segments du set
1023  TYPointParcours P;
1024  int indexPoint1In = P1.Identifiant;
1025  int indexPoint2In = P2.Identifiant;
1026  for (int i = 0; i < _nNbPolylines; i++)
1027  {
1028  assert(_ListePolylines[i].nombreDePoint() == 2);
1029  int indexPoint1 = _ListePolylines[i].indexePoint1();
1030  int indexPoint2 = _ListePolylines[i].indexePoint2();
1031 
1032  // les 2 segments ont ils au moins un point en commun ?
1033  bool bMemePoint1 = (indexPoint1 == indexPoint1In) || (indexPoint1 == indexPoint2In);
1034  bool bMemePoint2 = (indexPoint2 == indexPoint2In) || (indexPoint2 == indexPoint1In);
1035  bool bMemePoints = bMemePoint1 || bMemePoint2;
1036 
1037  if (!bMemePoints)
1038  {
1039  // Non => on peut faire le test
1040  TYPointParcours& P3 = _ListePoint[indexPoint1];
1041  TYPointParcours& P4 = _ListePoint[indexPoint2];
1042  if (TYPointParcours::IntersectionSegments(P1, P2, P3, P4, P, true))
1043  // if(TYPointParcours::IntersectionSegments(P1, P2, _ListePoint[indexPoint1],
1044  // _ListePoint[indexPoint2], P))
1045  {
1046  return true;
1047  }
1048  }
1049  }
1050  return false;
1051 }
1052 
1054 {
1055  bool ret = false;
1056  assert(geoPasse._nNbPolylines == 1);
1057  for (int i = 1; i < geoPasse._ListePolylines[0].nombreDePoint(); i++)
1058  {
1059  if (this->intersects(geoPasse._ListePoint[i - 1], geoPasse._ListePoint[i]))
1060  {
1061  ret = true;
1062  break;
1063  }
1064  }
1065  return ret;
1066 }
1067 
1069 {
1070  bool ret = false;
1071  assert(otherGeoPasse._nNbPolylines == 1);
1072  // On ne compare que des GeoParcours avec 1 Polyligne chacun et le même nombre de points
1073  if ((_nNbPolylines == 1) &&
1074  (_ListePolylines[0].nombreDePoint() == otherGeoPasse._ListePolylines[0].nombreDePoint()))
1075  {
1076  ret = true;
1077  for (int i = 0; i < _ListePolylines[0].nombreDePoint(); i++)
1078  {
1079  if (!(_ListePoint[i] == otherGeoPasse._ListePoint[i]))
1080  {
1081  ret = false;
1082  break;
1083  }
1084  }
1085  }
1086  return ret;
1087 }
1088 // indexePointADroite=>indexePointDuBonCote
1089 // test du bon cote : a gauche => det >0 a droite det < 0
1090 // texte de debug : en dessous <-> au dessus
1092 {
1093  determinant = TYPointParcours::ZCross(V1, V2);
1094  return (determinant < 0);
1095 }
1096 
1098 {
1099  determinant = TYPointParcours::ZCross(V1, V2);
1100  return (determinant > 0);
1101 }
1102 
1104  int nNbPoints,
1105  TYPointParcours** TableauDePointsECOut,
1106  bool bPremiersPointsLesPlusHauts)
1107 {
1108  bool (*pDuBonCote)(TYPointParcours & V1, TYPointParcours & V2, double& determinant);
1109  pDuBonCote =
1110  bPremiersPointsLesPlusHauts ? &SecondVecteurADroiteDuPremier : &SecondVecteurAGaucheDuPremier;
1111 
1112  int nNbPointsEC = 0;
1113  // On teste chaque point pour voir s'il est a gauche de SP courant (en fait, si l'angle est inferieur
1114  // a PI) Le calcul d'enveloppe convexe suppose que les 2 premiers points sont sur l'EC, et qu'ils sont
1115  // les plus bas Si le premier n'est pas le plus a gauche, on swap avec le second
1116  bool bSaGaucheDeR = TableauDePoints[0]->x < TableauDePoints[1]->x;
1117  int indexS = bSaGaucheDeR ? 0 : 1;
1118  int indexR = bSaGaucheDeR ? 1 : 0;
1119 
1120  // Vecteur SR:
1121  TYPointParcours S = *(TableauDePoints[indexS]);
1122  TYPointParcours R = *(TableauDePoints[indexR]);
1123 
1124  // S est le premier point de l'EC:
1125  TableauDePointsECOut[nNbPointsEC] = TableauDePoints[indexS];
1126 
1127  nNbPointsEC++;
1128 
1129  TYPointParcours P = S;
1130  TYPointParcours P1 = R;
1131 
1132  int i = 0;
1133  TYPointParcours P2;
1134  TYPointParcours PP1;
1135  TYPointParcours PP2;
1136  int indexePointDuBonCote = -1;
1137  do
1138  {
1139  // On calcule PP1
1140  PP1 = TYPointParcours::vecteur2D(P, P1);
1141 
1142  // Cherchons le point le plus a gauche de PP1
1143  indexePointDuBonCote = -1; // on ne l'a pas encore trouve
1144  for (i = 2; i < nNbPoints; i++)
1145  {
1146  P2 = (*TableauDePoints[i]);
1147  PP2 = TYPointParcours::vecteur2D(P, P2);
1148  // Ne pas tester le meme point
1149  if (P1.Identifiant != P2.Identifiant)
1150  {
1151  double determinant = NAN; // = TYPointParcours::ZCross(PP1, PP2);
1152  bool bDuBonCote = (*pDuBonCote)(PP1, PP2, determinant);
1153  // Attention ! Lorsque les vecteurs sont colineaires, le determinant peut etre non nul
1154  // mais tres proche de 0.
1155  //=> seuil epsilon pour le determinant
1156  // static const double epsilonDeterminant = 1E-10;
1157  bool bColineraires = (fabs(determinant) < SEUIL_DETERMNANT_COLINEAIRE);
1158  bool bBonCandidatPourRemplacement = false;
1159  if (bColineraires)
1160  {
1161  // Verifions que P2 est du meme côte que P1
1162  if (TYPointParcours::Scalaire(PP1, PP2) <
1163  0) // xbh: A koi sert ce test si les vecteurs sont colineaires ???
1164  {
1165  bBonCandidatPourRemplacement = false;
1166  }
1167  else
1168  {
1169  bBonCandidatPourRemplacement = PP2.normeCarree() > PP1.normeCarree();
1170  }
1171  }
1172  else
1173  {
1174  bBonCandidatPourRemplacement = bDuBonCote;
1175  }
1176  if (bBonCandidatPourRemplacement)
1177  {
1178  // P2 a gauche de P1 => on remplace P1 par P2
1179  P1 = P2;
1180  indexePointDuBonCote = i;
1181  // On recalcule PP1
1182  PP1 = TYPointParcours::vecteur2D(P, P1);
1183  }
1184  }
1185  }
1186  TYPointParcours* pNouveauPointEC = NULL;
1187  if (indexePointDuBonCote >= 0)
1188  {
1189  // On a trouve un point plus a gauche
1190  pNouveauPointEC = TableauDePoints[indexePointDuBonCote];
1191  // Cherchons le point suivant de l'EC
1192  P = P1;
1193  P1 = R;
1194  }
1195  else
1196  {
1197  // le dernier point de l'EC est R:
1198  pNouveauPointEC = TableauDePoints[indexR];
1199  }
1200  // Ajoutons-le a EC
1201  TableauDePointsECOut[nNbPointsEC] = pNouveauPointEC;
1202  nNbPointsEC++;
1203  } while (nNbPointsEC < nNbPoints && indexePointDuBonCote >= 0);
1204 
1205  return nNbPointsEC;
1206 }
1207 
1209  TYPointParcours** TableauDePoints,
1210  int nNbPoints)
1211 {
1212  if (NULL == TableauDePoints || 0 == nNbPoints)
1213  {
1214  return 0;
1215  }
1216  int nNbPointsSelectiones = 2;
1217 
1218  // on ajoute les points S & R en premier:
1219  // ajout de S
1220  TableauDePoints[0] = geoSR->_ListePolylines[0].pointPtr(0);
1221 
1222  // ajout de R
1223  TableauDePoints[1] = geoSR->_ListePolylines[0].pointPtr(1);
1224 
1225  // Limites en X: quel est le point le plus a gauche entre S & R ?
1226  bool bSaGaucheDeR = TableauDePoints[0]->x < TableauDePoints[1]->x;
1227  TYPointParcours G, D;
1228  if (bSaGaucheDeR)
1229  {
1230  G = *TableauDePoints[0];
1231  D = *TableauDePoints[1];
1232  }
1233  else
1234  {
1235  G = *TableauDePoints[1];
1236  D = *TableauDePoints[0];
1237  }
1238  // Vecteur GD (Point limite Gauche & Point limite Droit)
1240 
1241  int i = 0;
1242  TYPointParcours *p1 = nullptr, *p2 = nullptr;
1243  TYPointParcours p;
1244  int nbPts = 0;
1245 
1246  // 1. GD intersecte une des polylignes...
1247  bool noIntersection = true;
1248  for (i = 0; (i < _nNbPolylines) && (noIntersection); i++)
1249  {
1250  nbPts = _ListePolylines[i].nombreDePoint();
1251  for (int j = 0; (j < nbPts - 1) && (noIntersection); j++)
1252  {
1253  p1 = _ListePolylines[i].pointPtr(j);
1254  p2 = _ListePolylines[i].pointPtr(j + 1);
1255 
1256  if (TYPointParcours::IntersectionSegments(G, D, *p1, *p2, p))
1257  {
1258  noIntersection = false;
1259  }
1260  }
1261  }
1262 
1263  // Si on n'a trouve aucune intersection, il existe un trajet direct.
1264  if (noIntersection)
1265  {
1266  return nNbPointsSelectiones;
1267  }
1268 
1269  // 2. On selectionne les points interessants...
1270  // MinMax en largeur
1271  double MaxX = D.x;
1272  double MinX = G.x;
1273 
1274  // Comme le merge des points doubles a consistes a marquer en negatifs les points inutiles, on les
1275  // ecartes
1276  int racine = 0;
1277  bool bEntreSetR = false;
1278  TYPointParcours GP;
1279 
1280  for (i = 0; i < nNbPoints; i++)
1281  {
1282  // Est-ce un doublon ?
1283  int nIdentifiantRacine = _ListePoint[racine].Identifiant;
1284  while (i != 0 && i < nNbPoints && _ListePoint[i].Identifiant <= nIdentifiantRacine)
1285  {
1286  i++;
1287  }
1288  if (i >= nNbPoints)
1289  {
1290  break;
1291  }
1292  racine = i;
1293 
1294  bEntreSetR = (_ListePoint[i].x >= MinX && _ListePoint[i].x <= MaxX);
1295 
1296  // A gauche ?
1298  if (bEntreSetR && (TYPointParcours::ZCross(GD, GP) >= 0))
1299  {
1300  TableauDePoints[nNbPointsSelectiones] = &(_ListePoint[i]);
1301  nNbPointsSelectiones++;
1302  }
1303  }
1304 
1305  return nNbPointsSelectiones;
1306 }
1307 
1309  int nNbPoints, bool bSens,
1310  bool bGardeIdentifiant)
1311 {
1312  if (NULL == TableauDePoints || 0 == nNbPoints)
1313  {
1314  return;
1315  }
1316  assert(_ListePolylines == NULL);
1317  assert(_ListePoint == NULL);
1318  assert(_nNbPolylines == 0);
1319  assert(_nNbPointTotal == 0);
1320 
1321  // 1. Creer les points
1322  _ListePoint = new TYPointParcours[nNbPoints];
1323  _nNbPointTotal = nNbPoints;
1324 
1325  // 2. Creer la polyligne
1327  _nNbPolylines = 1;
1328  _ListePolylines[0].allouer(nNbPoints);
1329 
1330  // Copie des points
1331  int i = 0;
1332  if (bSens)
1333  {
1334  for (i = 0; i < nNbPoints; i++)
1335  {
1336  _ListePoint[i] = *TableauDePoints[i];
1338  }
1339  if (!bGardeIdentifiant) // a l'exterieur, on ne fait qu'un seul test...
1340  {
1341  for (i = 0; i < nNbPoints; i++)
1342  {
1343  _ListePoint[i].Identifiant = i;
1344  }
1345  }
1346  }
1347  else
1348  {
1349  for (i = 0; i < nNbPoints; i++)
1350  {
1351  _ListePoint[i] = *TableauDePoints[nNbPoints - i - 1];
1352  _ListePolylines[0].ajoutePoint(i, &(_ListePoint[nNbPoints - i - 1]));
1353  }
1354  if (!bGardeIdentifiant)
1355  {
1356  for (i = 0; i < nNbPoints; i++)
1357  {
1358  _ListePoint[i].Identifiant = nNbPoints - i - 1;
1359  }
1360  }
1361  }
1362 }
1363 
1365  TYPointParcours* c)
1366 {
1367  OVector3D v1(b->x - a->x, b->y - a->y, 0.0f);
1368  OVector3D v2(c->x - b->x, c->y - b->y, 0.0f);
1369  TYPointParcours *p = nullptr, *pp = nullptr, *pn = nullptr;
1370  int nbPts = 0;
1371  double norme1 = NAN;
1372  double norme2 = NAN;
1373  double cosVal1 = NAN;
1374  double cosVal2 = NAN;
1375 
1376  bool t1 = false, t2 = false;
1377  t1 = t2 = false;
1378 
1379  // 1. on regarde si b appartienne a une polyligne
1380  for (int i = 0; i < _nNbPolylines; i++)
1381  {
1382  nbPts = _ListePolylines[i].nombreDePoint();
1383  for (int j = 0; j < nbPts; j++)
1384  {
1385  p = _ListePolylines[i].pointPtr(j);
1386 
1387  if (TYPointParcours::Confondus(p, b))
1388  {
1389  // On regarde si les vecteurs ab et bc sont colineaires aux segments prec et suiv
1390  // de la polyligne
1391 
1392  if (j > 0)
1393  {
1394  pp = _ListePolylines[i].pointPtr(j - 1);
1395  OVector3D v3(p->x - pp->x, p->y - pp->y, 0.0f);
1396 
1397  norme1 = (v1.norme() * v3.norme());
1398  cosVal1 = v1.scalar(v3) / norme1; // should be > 0
1399  if (ABS(cosVal1 - 1.0f) < EPSILON_13)
1400  {
1401  t1 = true;
1402  }
1403 
1404  v3._x = -v3._x;
1405  v3._y = -v3._y;
1406 
1407  norme2 = (v2.norme() * v3.norme());
1408  cosVal2 = v2.scalar(v3) / norme2; // should be > 0
1409  if (ABS(cosVal2 - 1.0f) < EPSILON_13)
1410  {
1411  t2 = true;
1412  }
1413  }
1414  if (j < nbPts - 1)
1415  {
1416  pn = _ListePolylines[i].pointPtr(j + 1);
1417  OVector3D v4(pn->x - p->x, pn->y - p->y, 0.0f);
1418 
1419  norme2 = (v2.norme() * v4.norme());
1420  cosVal2 = v2.scalar(v4) / norme2; // should be > 0
1421  if (ABS(cosVal2 - 1.0f) < EPSILON_13)
1422  {
1423  t2 = true;
1424  }
1425 
1426  v4._x = -v4._x;
1427  v4._y = -v4._y;
1428 
1429  norme1 = (v1.norme() * v4.norme());
1430  cosVal1 = v1.scalar(v4) / norme1; // should be > 0
1431  if (ABS(cosVal1 - 1.0f) < EPSILON_13)
1432  {
1433  t1 = true;
1434  }
1435  }
1436  }
1437  }
1438 
1439  if (t1 && t2)
1440  {
1441  break;
1442  }
1443  }
1444 
1445  return (t1 && t2);
1446 }
1447 
1449 {
1450  assert(nNouvelleTaille >= _nNbPointTotal);
1451  TYPointParcours* newListePoint = new TYPointParcours[nNouvelleTaille];
1452  // Copie des points
1453  for (int i = 0; i < _nNbPointTotal; i++)
1454  {
1455  newListePoint[i] = this->_ListePoint[i];
1456  }
1457 
1459  this->_ListePoint = newListePoint;
1460 
1461  return NULL != this->_ListePoint;
1462 }
All base classes related to 3D manipulation.
#define EPSILON_13
Definition: 3d.h:41
double ABS(double a)
Return the absolute value.
Definition: 3d.h:67
NxReal c
Definition: NxVec3.cpp:317
#define SEUIL_DETERMNANT_COLINEAIRE
of two vectors
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
The 3D vector class.
Definition: 3d.h:298
double norme() const
Computes the length of this vector.
Definition: 3d.cpp:215
double scalar(const OVector3D &vector) const
Performs the scalar product between this object and another vector.
Definition: 3d.cpp:210
Polylines path class used by the TYSetGeometriqueParcours class.
void ajoutePoint(int indexe, TYPointParcours *p)
Add a point.
TYPointParcours point(int indexe)
Return a copy the point Pi.
TYPolyligneParcours * _PolyligneP1
Pointer to the next polyline (from P1 point)
bool allouer(int nNbPoint)
Allocate nNbPoint points to the polyline.
int indexePoint2()
Return point id of point P1.
bool extendPtrPoints(int nNouvelleTaille)
Extends the attribute array _PtrPoints.
int indexePoint1()
Return point id of point P0.
void setPoint(int indexe, TYPointParcours *p)
Change a point.
int indexePointSuivant(int IndexPoint, TYPolyligneParcours *&PolyligneSuivante)
Return the point id of the next point given by IndexPoint id.
int nombreDePoint()
Return the number of points.
TYPointParcours * pointPtr(int indexe)
Return a pointer on the point Pi.
bool isEcran()
Return true if P0 and P1 are Ecran.
TYPolyligneParcours * _PolyligneP0
Pointer to the previous polyline (from P0 point)
void Copy(TYPolyligneParcours &p)
Copy operator.
int indexePoint(int i)
Return point id of point i of the polyline.
Class to build a geometric path used by the TYCalculParcours class.
void MarquePointsADroiteEtAGauche(TYPointParcours &Srce, TYPointParcours &Dest, bool *&PointsAGauche, bool *&PointsADroite)
Mark points on the left and on the right of the current geometric path.
int ParcourtPolyligneAPartirDe(int IndexPointRacine, TYPolyligneParcours *&PolyligneRacine, std::vector< bool > &pEstUnPointIntersectant, TYSetGeometriqueParcours &geoPremierePasse)
To be commented.
bool intersects(TYPointParcours &P1, TYPointParcours &P2)
Check if [P1P2] segment can intersect the geometric path.
void Clean()
Delete polylines list and points list.
bool SecondePasse(TYSetGeometriqueParcours &geoPremierePasse, TYSetGeometriqueParcours &geoSecondePasse, bool bTrajetsAGaucheDeSR, TYPointParcours **&pTableauEC, int &nbPtsEC, int compteurIter=0, bool bIsLastSecondePasse=false)
Second pass.
bool polyligneContientSouR(int i)
Returns true if polyligne of index i contains Source or Receptor.
void RamenerPointsTraversantLaFrontiere(TYPointParcours &Srce, TYPointParcours &Dest, int *IndexePointsFrontiere, int &NbPointsFrontiere, std::vector< bool > &pEstUnPointIntersectant, bool bCoteGauche, bool *PointsAGauche, bool *PointsADroite)
To be commented.
void SwapPolyligne(int i, int j)
Swap polylines i and j.
static int EnveloppeConvexeLes2PremiersPointsEtant(TYPointParcours **TableauDePoints, int nNbPoints, TYPointParcours **TableauDePointsECOut, bool bPremiersPointsLesPlusHauts)
Compute the convex hull (arrays should be allocated before the call)
int SupressionPolylignesRedondantes()
Suppress useless polylines.
TYPolyligneParcours * _ListePolylines
Geometric path as a polylines.
void TriePointsIntersectionSuivantSR(TYPointParcours &Srce, TYPointParcours &Dest, int *IndexePointsFrontiere, int NbPointsFrontiere)
To be commented.
static TYPointParcours * _DestQSort
static access to the C function of quicksort
int SelectionnePointsEntreSetRetDuCoteDeSR(TYSetGeometriqueParcours *geoSR, TYPointParcours **TableauDePoints, int nNbPoints)
Select points from the current geometric path which are between source and receptor of the geoSR geom...
bool PolylignesInfraFermees()
Return true if all polylines from infrastructure are closed.
void CreerTrajetAPartirDuneListeDePointsTriee(TYPointParcours **TableauDePoints, int nNbPoints, bool bSens, bool bGardeIdentifiant)
Create paths from a sorted points list (Used only for vertical paths)
static TYPointParcours * _SrceQSort
static access to the C function of quicksort
void SeparationDroiteGauche(bool *PointsAGauche, bool *PointsADroite, TYSetGeometriqueParcours &geoGauche, TYSetGeometriqueParcours &geoDroite, int compteurIter=0)
Separate left and right polylines with two geometric paths.
bool coincideWith(TYSetGeometriqueParcours &otherGeoPasse)
Tests if the first polyline of this geo parcours coincide with the geo passe in argument,...
static void InverseOrdreDesPoints(TYPointParcours **ListeDePointsAInverser, int nNbPointsDeLaListe)
Invert a list of points.
int _nNbPolylines
Polylines number.
TYPointParcours * _ListePoint
List of points on the path.
void Copy(TYSetGeometriqueParcours &geoIn)
Copy operator.
int _nNbPointTotal
Total number of points.
static TYPointParcours * _ListePointQSort
static access to the C function of quicksort
bool AjoutePointALaPolyLigne(int indexPolyligne, TYPointParcours &P)
Add a point P to the polyline indexPolyligne.
void AllouerPolylignes(int nNbPolylineAllouee)
Allocation of the polylines list.
bool PremierePasse(TYPointParcours &Srce, TYPointParcours &Dest, int *IndexePointsFrontiere, int NbPointsFrontiere, std::vector< bool > &pEstUnPointIntersectant, Connexite *Connexes, TYSetGeometriqueParcours &geoPremierePasse, int compteurIter=0)
First pass to build a path along all the intersecting polylines.
bool ListerPointsConnexes(Connexite *&Connexes, std::vector< bool > &pEstUnPointIntersectant)
Fill for each point the connectivity with segments.
int MergePointsDoubles()
Detect and fix double points.
bool AppartienneMemePolyligne(TYPointParcours *a, TYPointParcours *b, TYPointParcours *c)
Check if the points a, b, c belong to the same polyline.
int AjouteLesPointsComprisEntre(TYSetGeometriqueParcours &geoPolySource, int nIndexePoly, int nIndexeNbPremierPointAAjouter, int nIndexeDernierPointAAjouter)
Add some points of the nIndexePoly polyline from the geoPolySource geometric path.
bool extendListePoint(int nNouvelleTaille)
Extends the attribute array _ListePoint.
int compareTYPolyligneParcours(const void *p1, const void *p2)
bool SecondVecteurAGaucheDuPremier(TYPointParcours &V1, TYPointParcours &V2, double &determinant)
bool SecondVecteurADroiteDuPremier(TYPointParcours &V1, TYPointParcours &V2, double &determinant)
int compareAbscissesCurvilignes(const void *p1, const void *p2)
#define SAFE_DELETE_LIST(_p)
Definition: macros.h:239
Connectivity between points and segments.
int IndexesSegment[2]
Two indexes of the segment.
int NbSegmentsConnexes
Related segments number.
Point of a path.
double z
z coordinate of the point
bool isInfra
Flag set to indicate if the point is an infrastructure.
int Identifiant
Point id.
static bool Confondus(TYPointParcours *P1, TYPointParcours *P2)
static bool IntersectionSegments(TYPointParcours &P1, TYPointParcours &P2, TYPointParcours &P3, TYPointParcours &P4, TYPointParcours &P, bool bP3OrP4MustNotCoincideWithP=false)
Return true if [P1P2] intersects [P3P4] if P1 or P2 coincide with the intersection point P,...
static double ZCross(TYPointParcours SR, TYPointParcours SP)
Return cross product applied to SR and SP points.
double y
y coordinate of the point
static double Scalaire(TYPointParcours &P1, TYPointParcours &P2, TYPointParcours &P3, TYPointParcours &P4)
Compute the scalar product of the vector P1P2 and P3P4.
double x
x coordinate of the point
bool isEcran
Flag set to indicate if the point is a screen.
static bool IntersectionDroites(TYPointParcours &P1, TYPointParcours &P2, TYPointParcours &P3, TYPointParcours &P4, TYPointParcours &P)
static double AbscisseCurviligneCarreSurSR(TYPointParcours &P, TYPointParcours &S, TYPointParcours &R)
Return the square of the curvilinear abscissa of point P on [SR].
static TYPointParcours vecteur2D(TYPointParcours &P1, TYPointParcours &P2)
Compute the 2 dimensional vector P1P2 in the XY plane.