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