g4tools  5.4.0
hatcher.icc
Go to the documentation of this file.
1 // Created by Laurent Garnier on Fri Jan 30 2004.
2 
3 //#define TOOLS_HATCHER_DEBUG
4 
5 #ifdef TOOLS_HATCHER_DEBUG
6 #include <cstdio>
7 #endif
8 
9 namespace tools {
10 
11 //////////////////////////////////////////////////////////////////////////////
12 // test if the polygone given is correct for hatching
13 // return FALSE if :
14 // - All points are not in the same plan
15 // - Number of points <3
16 // - Offset point is not in the same plan
17 // - There is less than three different points
18 // - The vector from point[0],point[1] is colinear to point[0],lastPoint
19 //////////////////////////////////////////////////////////////////////////////
20 
21 inline bool hatcher::check_polyline(vec3f* listPoints,unsigned int aNumber){
22 
23  unsigned int firstOffset =0;
24 
25  if ( listPoints[0].equals(listPoints[1],FLT_EPSILON*FLT_EPSILON*10)) {
26  firstOffset =1;
27  }
28 
29  if ( listPoints[0].equals(listPoints[aNumber-1],FLT_EPSILON*FLT_EPSILON*10)) {
30  aNumber --;
31  }
32 
33  if ((int)aNumber-firstOffset <3) {
34 #ifdef TOOLS_HATCHER_DEBUG
35  ::printf("hatcher::check_polyline : ERROR the polygone you give have not enought points!\n\n");
36 #endif
37  return false;
38  }
39 
40 
41  // use to test the polyline and to build the shift vector. A is the first point,
42  // B second and C the last (in fact, the last-1)!
43  vec3f AB,AC;
44  AB.setValue(listPoints[1+firstOffset].getValue()[0]-listPoints[0].getValue()[0],
45  listPoints[1+firstOffset].getValue()[1]-listPoints[0].getValue()[1],
46  listPoints[1+firstOffset].getValue()[2]-listPoints[0].getValue()[2]); // Vector A->B
47 
48 
49  fResolveResult = RESOLVE_COLINEAR;
50  unsigned int test = aNumber;
51  while ((fResolveResult !=0) && (test>2+firstOffset)) {
52  test--;
53  AC.setValue(listPoints[test].getValue()[0]-listPoints[0].getValue()[0],
54  listPoints[test].getValue()[1]-listPoints[0].getValue()[1],
55  listPoints[test].getValue()[2]-listPoints[0].getValue()[2]);
56 
57  // test if AB != AC*i
58  resolve_system( AB,
59  AC,
60  vec3f(.0f,.0f,.0f));
61  }
62  if (fResolveResult == RESOLVE_COLINEAR) {
63 #ifdef TOOLS_HATCHER_DEBUG
64  ::printf("hatcher::check_polyline : ERROR all the point you give are colinear!\n\n");
65  for (unsigned int a =0;a<aNumber;a++) {
66  printf(" %f %f %f \n",listPoints[a][0],listPoints[a][1],listPoints[a][2]); }
67 #endif
68  return false;
69  }
70 
71  ///////////////////////////////////////////////////////////////
72  // test if all points of the polyline are on the same plan
73  ///////////////////////////////////////////////////////////////
74 
75  int falsePoints =0;
76  for (unsigned int a=2+firstOffset;a<aNumber;a++) {
77  resolve_system( AB,
78  AC,
79  vec3f((listPoints[a].getValue()[0]-listPoints[0].getValue()[0]),
80  (listPoints[a].getValue()[1]-listPoints[0].getValue()[1]),
81  (listPoints[a].getValue()[2]-listPoints[0].getValue()[2])));
82  if (fResolveResult != 0){
83  falsePoints++;
84  }
85  }
86 
87  if (falsePoints !=0) {
88 #ifdef TOOLS_HATCHER_DEBUG
89  ::printf("hatcher::check_polyline : ERROR there is %d points on the polyline witch are not on the same plan!\n\n",falsePoints);
90 #endif
91  return false;
92  }
93 
94  // test offset
95  if (! ((fOffset[0] == FLT_MAX) && (fOffset[1] == FLT_MAX) && (fOffset[2] == FLT_MAX))){
96  resolve_system( AB,
97  AC,
98  fOffset-listPoints[0]);
99  if (fResolveResult != 0) {
100 #ifdef TOOLS_HATCHER_DEBUG
101  ::printf("hatcher::check_polyline : ERROR Offset vector has to be on the same plan!\n\n");
102 #endif
103  return false;
104  }
105  }
106  return true;
107 }
108 
109 
110 //////////////////////////////////////////////////////////////////////////////
111 // draw the hatch into the polyline bounding box giving in argument
112 // return false if :
113 // - All points are not in the same plan
114 // - There is a precision error on one or more point
115 // Compute a first sequence of hacth, store results, compute a second sequence
116 // and match all results to get the correct strip points
117 //////////////////////////////////////////////////////////////////////////////
118 /** Compute stripWidth
119  * We have to use the conflictNumHatchLineTab, hatchNumber,listHatchStartPoint tables
120  * also the HatchShiftToMacthPoint tab.
121  * and the hatch line just compute below
122  * We try to made a polyline with all points witch are on the current hatch and on the next hacth
123  * (distant of stripwidth form current hatch)
124  * conflictNumHatchLineTab give us something like this for current and next hatch
125  * current next current next
126  * 4 4 if we consider that ,4 ,4
127  * 0 5 we know the compute hatch '0 '5
128  * 1 3 lines, we could link ,1 ,3
129  * 3 2 some of theses line numbers '3 '2
130  * 5 so ->> ,5
131  * 2 '2
132  * And we have to add some points when HatchShiftToMacthPoint(point) is between current
133  * and next hatch : We add a point B on intersection of line 0 and 1
134  * current next current next
135  * ,4 ,4
136  * '0 B(0,1) '5
137  * ,1
138  * '3 ,3
139  * ,5 '2
140  * '2
141  *
142  * Now we have to match a way to traverse all of theses lines. We have 3 solutions to go from
143  * one line to another :
144  * - go to the next point if there is one between current and next hatch
145  * - go to the same line but on another hatch
146  * - go to the next tach point
147  * If there is no solution, we have to close the polyline strip and go to another point until
148  * all are compute
149  */
150 
151 /** first, we have to match 7 different cases
152  * 1- all strip hatch are entirely in the polyline
153  * 2- the first strip begin before the polyline and the last end in the polyline
154  * 3- the first strip begin before the polyline and the last ends after
155  * 4- the first strip is entierly in the polyline and the last ends after
156  * 5- the strip has only an intersection with the second hatch sequence (if it has only an intersection
157  * with the first hatch sequence, it is case 2
158  * 6- the strip has a full intersection
159  * 7- the strip has no intersection !
160  */
161 
162 inline bool hatcher::compute_polyline (vec3f* tabPoints,unsigned int aNumber) {
163  std::vector<vec3f> firstComputePoints; // copy first Points in
164  std::vector<vec3f> secondComputePoints; // copy first Points in
165  std::vector<bool> firstComputePointsEnable; // table of already compute points for first hatch
166  std::vector<bool> secondComputePointsEnable;// table of already compute points for second hatch
167  std::vector< std::vector<int> > firstComputeConflictNumHatchLineTab; // copy firstComputeConflictNumHatchLineTab in
168 
169  int firstComputeFirstNumHatch =0;
170  unsigned int firstComputeNumberHatchToDraw =0;
171  float firstHatchShiftToMatchFirstPoint = FLT_MAX; // use in one case when there is no intersection points: to test we have to fill all the polygone
172  float secondHatchShiftToMatchFirstPoint = FLT_MAX; // use in one case when there is no intersection points: to test we have to fill all the polygone
173  //call compute for first set of hatch
174  if ( !compute_single_polyline (tabPoints,aNumber))
175  return false;
176  if (fStripWidth ==0)
177  return true;
178 
179 
180  //save values
181  for (unsigned int a =0;a<fPoints.size();a++){
182  firstComputePoints.push_back(fPoints[a]);
183  }
184 
185  firstComputeConflictNumHatchLineTab.resize(fConflictNumHatchLineTab.size());
186  for (unsigned int a=0;a<fConflictNumHatchLineTab.size();a++){
187  firstComputeConflictNumHatchLineTab[a].clear();
188  for (unsigned int b=0;b<fConflictNumHatchLineTab[a].size();b++){
189  firstComputeConflictNumHatchLineTab[a].push_back(fConflictNumHatchLineTab[a][b]);
190  }
191  }
192  firstComputeFirstNumHatch = fFirstNumHatch;
193  firstComputeNumberHatchToDraw = fNumberHatchToDraw;
194  firstHatchShiftToMatchFirstPoint = fHatchShiftToMatchPointVec[0];
195  //change the offset vector
196  fOffset = fOffset+fShiftVec*fStripWidth;
197 
198  //call compute for second set of hatch
199  if ( !compute_single_polyline (tabPoints,aNumber))
200  return false;
201 
202  //save values
203  for (unsigned int a =0;a<fPoints.size();a++){
204  secondComputePoints.push_back(fPoints[a]);
205  }
206 
207  secondHatchShiftToMatchFirstPoint = fHatchShiftToMatchPointVec[0];
208 
209 
210  // initialize values
211  fPoints.clear();
212  fVertices.clear();
213 
214  int specialCase=1;
215 
216  //first hatch, case 1
217  if ((firstComputeFirstNumHatch == fFirstNumHatch) && (firstComputeNumberHatchToDraw == fNumberHatchToDraw) && (firstComputeNumberHatchToDraw !=0)) {
218  specialCase =1;
219  }
220  //first hatch, case 2
221  else if ((firstComputeFirstNumHatch > fFirstNumHatch) && (firstComputeNumberHatchToDraw < fNumberHatchToDraw) && (firstComputeNumberHatchToDraw !=0)) {
222  //insert a empty element at the beginning
223  firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(), firstComputeConflictNumHatchLineTab.back());
224  firstComputeConflictNumHatchLineTab[0].resize(0);
225  firstComputeFirstNumHatch--;
226  firstComputeNumberHatchToDraw ++;
227  firstComputeConflictNumHatchLineTab[0].clear();
228  specialCase =2;
229 
230  } //second hatch, case 3
231  else if (((firstComputeFirstNumHatch > fFirstNumHatch) && (firstComputeNumberHatchToDraw == fNumberHatchToDraw)) && (firstComputeNumberHatchToDraw !=0)) {
232  //insert a empty element at the beginning
233  firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(),firstComputeConflictNumHatchLineTab.back());
234  firstComputeConflictNumHatchLineTab[0].resize(0);
235  firstComputeConflictNumHatchLineTab[0].clear();
236  //insert a empty element at the end
237  fConflictNumHatchLineTab.push_back(firstComputeConflictNumHatchLineTab.back());
238  fConflictNumHatchLineTab.back().resize(0);
239  fConflictNumHatchLineTab.back().clear();
240  firstComputeFirstNumHatch--;
241  firstComputeNumberHatchToDraw ++;
242  specialCase =3;
243  } //second hatch, case 4
244  else if (((firstComputeFirstNumHatch == fFirstNumHatch) && (firstComputeNumberHatchToDraw > fNumberHatchToDraw)) && (firstComputeNumberHatchToDraw !=0)) {
245  //insert a empty element at the end
246  fConflictNumHatchLineTab.push_back(firstComputeConflictNumHatchLineTab.back());
247  fConflictNumHatchLineTab.back().resize(0);
248  fConflictNumHatchLineTab.back().clear();
249  specialCase =4;
250 
251  } //second hatch, case 5
252  else if ((firstComputeNumberHatchToDraw ==0) && (fNumberHatchToDraw !=0)) {
253  //insert a empty element at the beginning
254  firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(),firstComputeConflictNumHatchLineTab.back());
255  firstComputeConflictNumHatchLineTab[0].resize(0);
256  firstComputeConflictNumHatchLineTab[0].clear();
257  firstComputeNumberHatchToDraw ++;
258  specialCase =5;
259 
260  } //second hatch, case 6
261  else if (floorf(firstHatchShiftToMatchFirstPoint) != floorf(secondHatchShiftToMatchFirstPoint)) {
262  specialCase =6;
263 
264  //fill all the polygone !
265  fVertices.push_back(aNumber);
266  for (unsigned int a =0;a<aNumber;a++){
267  fPoints.push_back(tabPoints[a]);
268  }
269  return true;
270  }
271  else if (floorf(firstHatchShiftToMatchFirstPoint) == floorf(secondHatchShiftToMatchFirstPoint)) {
272  specialCase =7;
273  return true;
274  } else {
275 #ifdef TOOLS_HATCHER_DEBUG
276  ::printf("hatcher::drawStripPolyline : WARNING there is a case witch was not done in the algotithm...possibly some drawing problems.\n\n");
277 #endif
278 
279  }
280 
281 
282  bool result;
283  bool find; // temp variable
284  int firstHatchComputePoint = 0; //first point number
285  int secondHatchComputePoint = 0; //first point number
286  unsigned int lineNumber;
287  unsigned int firstPointTabInd =0;
288  unsigned int secondPointTabInd=0;
289  unsigned int currentHatch; // 0 is first, 1 is second, 2 is one or other !!
290  unsigned int solution; //default for beginning
291  unsigned int indTmp;
292  unsigned int oldSolution;
293  for (unsigned int indHatch =0;indHatch<firstComputeNumberHatchToDraw;indHatch++) {
294 
295 
296  currentHatch =0; // 0 is first, 1 is second
297  solution =99; //default for beginning
298  indTmp = 0;
299  lineNumber = 0;
300  secondComputePointsEnable.clear();
301  firstComputePointsEnable.clear();
302  for (unsigned int a=0;a<firstComputeConflictNumHatchLineTab[indHatch].size();a++){
303  firstComputePointsEnable.push_back(false);}
304  for (unsigned int a=0;a<fConflictNumHatchLineTab[indHatch].size();a++){
305  secondComputePointsEnable.push_back(false);}
306 
307  if ((indHatch == 0) && ((specialCase ==2) || (specialCase ==3) || (specialCase ==5))) {
308  for (unsigned int a=0;a<firstComputeConflictNumHatchLineTab[indHatch].size();a++){
309  firstComputePointsEnable[a] = true;
310  }
311  }
312  if ((indHatch == (firstComputeNumberHatchToDraw-1)) && ((specialCase ==3) || (specialCase ==4))) {
313  for (unsigned int a=0;a<fConflictNumHatchLineTab[indHatch].size();a++){
314  secondComputePointsEnable[a] = true;
315  }
316  }
317 
318  result = false;
319  while (result == false) {
320 
321 
322  //find a uncompute point for this set of hatch
323  result =true;
324  unsigned int b=0;
325  while ((result == true) && (b<firstComputeConflictNumHatchLineTab[indHatch].size())) {
326  if (firstComputePointsEnable[b] == false) {
327  result =false;
328  firstHatchComputePoint = b;
329  lineNumber = firstComputeConflictNumHatchLineTab[indHatch][b];
330  fPoints.push_back(firstComputePoints[b+firstPointTabInd]);
331  fVertices.push_back(1);
332  firstComputePointsEnable[b] = true;
333  currentHatch = 0;
334  }
335  b++;
336  }
337  if (result ==true) {
338  //find a uncompute point for this set of hatch
339 
340  while ((result == true) && (b<fConflictNumHatchLineTab[indHatch].size())) {
341  if (secondComputePointsEnable[b] == false) {
342  result =false;
343  secondHatchComputePoint = b;
344  lineNumber = fConflictNumHatchLineTab[indHatch][b];
345  fPoints.push_back(secondComputePoints[b+secondPointTabInd]);
346  fVertices.push_back(1);
347  secondComputePointsEnable[b] = true;
348  currentHatch = 1;
349  }
350  b++;
351  }
352  }
353  if (result == true) {
354  }
355  solution =99; // to enter in the while
356  while (solution !=0) {
357  oldSolution = solution;
358  solution =0; //default
359  // get the line number for this point
360  /** Now we have to match a way to traverse all of theses lines. We have 3 solutions to go from
361  * one line to another :
362  * - go to the next point if there is one between current and next hatch
363  * - go to the same line but on another hatch
364  * - go to the next hatch point
365  */
366  if (currentHatch != 1) {
367 
368  if (oldSolution != 3) { // could go to first solution
369  int index =0;
370  if ((firstHatchComputePoint % 2 == 0) && (firstComputePointsEnable[firstHatchComputePoint+1] == false)) index =1;
371  else if ((firstHatchComputePoint % 2 != 0) && (firstComputePointsEnable[firstHatchComputePoint-1] == false)) index = -1;
372  if (index !=0) {
373  solution = 1;
374  oldSolution = 0;
375  firstHatchComputePoint = firstHatchComputePoint+index;
376  fPoints.push_back(firstComputePoints[firstHatchComputePoint+firstPointTabInd]);
377  fVertices.back() ++;
378  firstComputePointsEnable[firstHatchComputePoint] = true;
379  lineNumber = firstComputeConflictNumHatchLineTab[indHatch][firstHatchComputePoint];
380  }
381  }
382  if (solution == 0) { // could go to second solution
383  indTmp = 0;
384  while ((solution == 0) && (indTmp < fConflictNumHatchLineTab[indHatch].size())) {
385  if ((fConflictNumHatchLineTab[indHatch][indTmp] == (int)lineNumber) && (secondComputePointsEnable[indTmp] == false)) {
386  solution =2;
387  oldSolution = 0;
388  fPoints.push_back(secondComputePoints[indTmp+secondPointTabInd]);
389  fVertices.back() ++;
390  secondComputePointsEnable[indTmp] = true;
391  lineNumber = fConflictNumHatchLineTab[indHatch][indTmp];
392  secondHatchComputePoint = indTmp;
393  currentHatch =1;
394  }
395  indTmp ++;
396  }
397  }
398  if (solution == 0) { // could go to first solution
399  indTmp = 0;
400  while ((solution == 0) && (indTmp < aNumber)) {
401 
402  if ((fHatchShiftToMatchPointVec[indTmp] > ((float)firstComputeFirstNumHatch+(float)indHatch-fStripWidth))
403  && (fHatchShiftToMatchPointVec[indTmp] < ((float)firstComputeFirstNumHatch+(float)indHatch))
404  && ((indTmp == lineNumber) || (indTmp==lineNumber+1) || ((lineNumber == (aNumber-1)) && (indTmp ==0)))) {
405  find = false;
406  unsigned a =0;
407  while ((a<fVertices.back()) && (find == false)) {
408  if ((tabPoints[indTmp][0] == fPoints[a][0]) && (tabPoints[indTmp][1] == fPoints[a][1]) && (tabPoints[indTmp][2] == fPoints[a][2])) find = true;
409  a++;
410  }
411  if (find == false){
412  solution = 3;
413  oldSolution = 0;
414  currentHatch =2;
415  fPoints.push_back(tabPoints[indTmp]);
416  fVertices.back() ++;
417  if (lineNumber == indTmp) {
418  if (indTmp >0) lineNumber = indTmp-1;
419  else lineNumber = aNumber-1;
420  }
421  else {
422  if (indTmp < aNumber-1) lineNumber = indTmp;
423  else lineNumber = 0;
424  }
425  }
426  }
427  indTmp++;
428  }
429  }
430  } // end of current hatch
431 
432  //test of second hatch if currentHatch is second
433  if ((oldSolution != 0) && (solution !=2) && (currentHatch !=0)) {
434 
435  if (oldSolution != 3){ // could go to first solution
436  int index =0;
437  if ((secondHatchComputePoint % 2 == 0) && (secondComputePointsEnable[secondHatchComputePoint+1] == false)) index =1;
438  else if ((secondHatchComputePoint % 2 != 0) && (secondComputePointsEnable[secondHatchComputePoint-1] == false)) index = -1;
439  if (index !=0){
440  solution = 1;
441  secondHatchComputePoint = secondHatchComputePoint+index;
442  fPoints.push_back(secondComputePoints[secondHatchComputePoint+secondPointTabInd]);
443  fVertices.back() ++;
444  secondComputePointsEnable[secondHatchComputePoint] = true;
445  lineNumber = fConflictNumHatchLineTab[indHatch][secondHatchComputePoint];
446  }
447  }
448  if (solution == 0) { // could go to second solution
449  indTmp = 0;
450  while ((solution == 0) && (indTmp < firstComputeConflictNumHatchLineTab[indHatch].size())) {
451  if ((firstComputeConflictNumHatchLineTab[indHatch][indTmp] == (int)lineNumber) && (firstComputePointsEnable[indTmp] == false)) {
452  solution =2;
453  fPoints.push_back(firstComputePoints[indTmp+firstPointTabInd]);
454  fVertices.back() ++;
455  firstComputePointsEnable[indTmp] = true;
456  lineNumber = firstComputeConflictNumHatchLineTab[indHatch][indTmp];
457  firstHatchComputePoint = indTmp;
458  currentHatch =0;
459  }
460  indTmp ++;
461  }
462  }
463  if (solution == 0) { // could go to first solution
464  indTmp = 0;
465  while ((solution == 0) && (indTmp < aNumber)) {
466 
467  if ((fHatchShiftToMatchPointVec[indTmp] > ((float)fFirstNumHatch+(float)indHatch-fStripWidth))
468  && (fHatchShiftToMatchPointVec[indTmp] < ((float)fFirstNumHatch+(float)indHatch))
469  && ((indTmp == lineNumber) || (indTmp==lineNumber+1) || ((lineNumber == (aNumber-1)) && (indTmp ==0)))) {
470  find = false;
471  unsigned a =0;
472  while ((a<fVertices.back()) && (find == false)) {
473  if ((tabPoints[indTmp][0] == fPoints[a][0]) && (tabPoints[indTmp][1] == fPoints[a][1]) && (tabPoints[indTmp][2] == fPoints[a][2])) find = true;
474  a++;
475  }
476  if (find == false){
477  currentHatch =2;
478  solution = 3;
479  fPoints.push_back(tabPoints[indTmp]);
480  fVertices.back() ++;
481  if (lineNumber == indTmp) {
482  if (indTmp >0) lineNumber = indTmp-1;
483  else lineNumber = aNumber-1;
484  }
485  else {
486  if (indTmp < aNumber-1) lineNumber = indTmp;
487  else lineNumber = 0;
488  }
489  }
490  }
491  indTmp++;
492  }
493  }
494  } // end of current hatch
495  if (solution == 0) {
496  // the end for this polyline
497  // close polyline
498  fPoints.push_back(fPoints[fPoints.size()-fVertices.back()]);
499  fVertices.back() ++;
500  result =true;
501  }
502  } // while solution !=0
503  // } // if result
504  } // while result
505  for (unsigned int a =0;a<fVertices.size();a++){
506 #ifdef TOOLS_HATCHER_DEBUG
507  if (fVertices[a] <4) ::printf("hatcher::drawStripPolyline : WARNING A strip polyline has been compute with less than 3 points, it could be an error in the algorithm or a special case.\n\n");
508 #endif
509  }
510 
511  firstPointTabInd += firstComputeConflictNumHatchLineTab[indHatch].size();
512  secondPointTabInd += fConflictNumHatchLineTab[indHatch].size();
513  } //end for
514  return true;
515 }
516 
517 
518 
519 
520 //////////////////////////////////////////////////////////////////////////////
521 // draw the hatch into the polyline bounding box giving in argument
522 // return false if :
523 // - All points are not in the same plan
524 // - There is a precision error on one or more point
525 //////////////////////////////////////////////////////////////////////////////
526 
527 inline bool hatcher::compute_single_polyline (vec3f* tabPoints,unsigned int aNumber) {
528  std::vector<vec3f> listNormalVec;
529  int numberOfPolylinePoints =0;
530  fPoints.resize(0);
531  fPoints.clear();
532  int precisionError =0;
533  unsigned int firstOffset =0;
534  fFirstNumHatch =0;
535  fNumberHatchToDraw =0;
536  fVertices.resize(0);
537  fVertices.clear();
538 
539  if ( tabPoints[0].equals(tabPoints[1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
540  firstOffset =1; }
541 
542  vec3f* listPoints = new vec3f[aNumber+1-firstOffset];
543 
544  for (unsigned int i=0;i<aNumber;i++){
545  if ((i==0) || (listPoints[i-1] !=tabPoints[i+firstOffset])) {
546  listPoints[numberOfPolylinePoints] = tabPoints[i+firstOffset];
547  numberOfPolylinePoints++;
548  }
549  }
550 
551  // add the first point on last position to close the line
552  if ( ! listPoints[0].equals(listPoints[numberOfPolylinePoints-1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
553  listPoints[numberOfPolylinePoints]=listPoints[0];
554  numberOfPolylinePoints ++;
555  }
556 
557  // use to test the polyline and to build the shift vector. A is the first point,
558  // B second and C the last (in fact, the last-1)!
559  vec3f AB,AC;
560  AB.setValue(listPoints[1].getValue()[0]-listPoints[0].getValue()[0],
561  listPoints[1].getValue()[1]-listPoints[0].getValue()[1],
562  listPoints[1].getValue()[2]-listPoints[0].getValue()[2]); // Vector A->B
563 
564  fResolveResult = RESOLVE_COLINEAR;
565  unsigned int test = numberOfPolylinePoints-1;
566  while ((fResolveResult !=0) && (test>1)) {
567  test--;
568  AC.setValue(listPoints[test].getValue()[0]-listPoints[0].getValue()[0],
569  listPoints[test].getValue()[1]-listPoints[0].getValue()[1],
570  listPoints[test].getValue()[2]-listPoints[0].getValue()[2]);
571 
572  // test if AB != AC*i
573  resolve_system( AB,
574  AC,
575  vec3f(.0f,.0f,.0f));
576  }
577  if (fResolveResult == RESOLVE_COLINEAR) {
578 #ifdef TOOLS_HATCHER_DEBUG
579  ::printf("hatcher::drawPolyline : ERROR all the point you give are colinear!\n\n");
580  for (unsigned int a =0;a<aNumber;a++) {
581  printf(" %f %f %f \n",listPoints[a][0],listPoints[a][1],listPoints[a][2]); }
582 #endif
583  delete [] listPoints;
584  return false;
585  }
586 
587  ///////////////////////////////////////////////////////////////
588  // creation of the dirVec. It is done with the dirAngle field
589  // The angle is the one between the first line (point 1-point0)
590  // and the dirVec, on the plan delimited by polyline
591  // Given in the direct axis ((point1-point0),(lastPoint-point0),normalPlanVec)
592  // Normal plane Vector = AB x AC
593  ///////////////////////////////////////////////////////////////
594  if (fFirstPolyline) {
595 
596  fFirstPolyline = false;
597 
598  fNormal.setValue(AB[1]*AC[2]-AB[2]*AC[1],
599  AB[2]*AC[0]-AB[0]*AC[2],
600  AB[0]*AC[1]-AB[1]*AC[0]);
601 
602 
603  // ABPerp Vector = normal x AB
604  vec3f ABPerpVector;
605  ABPerpVector.setValue(fNormal[1]*AB[2]-fNormal[2]*AB[1],
606  fNormal[2]*AB[0]-fNormal[0]*AB[2],
607  fNormal[0]*AB[1]-fNormal[1]*AB[0]);
608 
609  float normAB =(float)std::sqrt(std::pow(AB[0],2)+
610  std::pow(AB[1],2)+
611  std::pow(AB[2],2));
612  float normABPerpVector =(float)std::sqrt(std::pow(ABPerpVector[0],2)+
613  std::pow(ABPerpVector[1],2)+
614  std::pow(ABPerpVector[2],2));
615 
616  float j = std::tan(fDirAngle)*normAB/normABPerpVector;
617 
618  if (normABPerpVector == 0){ // never done (should be test before)
619 #ifdef TOOLS_HATCHER_DEBUG
620  ::printf("hatcher::drawPolyline : ERROR Impossible to compute the dir vector for hatch. Normal for this plan is null (normal for : point[0],point[1],lastPoint) point[0], point[1], last point are probably aligned\n\n");
621 #endif
622  delete [] listPoints;
623  return false;
624  }
625 
626  fDirVec = AB +(float)j*ABPerpVector;
627  // normalize vector to unit on X or on Y
628  if (fDirVec.getValue()[0] ==0){
629  fDirVec[0] = fPrecisionFactor; // to get rid of somes errors
630  fDirVec = fDirVec/fDirVec.getValue()[1]; // normalize on Y because X will be a big value
631  } else {
632  fDirVec = fDirVec/fDirVec.getValue()[0];
633  }
634 
635  ///////////////////////////////////////////////////////////////
636  // creation of the shiftVec thanks to the shift field
637  ///////////////////////////////////////////////////////////////
638 
639  vec3f dirShiftVector;
640  dirShiftVector.setValue(fNormal[1]*fDirVec.getValue()[2]-fNormal[2]*fDirVec.getValue()[1],
641  fNormal[2]*fDirVec.getValue()[0]-fNormal[0]*fDirVec.getValue()[2],
642  fNormal[0]*fDirVec.getValue()[1]-fNormal[1]*fDirVec.getValue()[0]);
643 
644  // normalize vector to match the shift size
645  float param = 1.0f;
646  param = (float)std::sqrt((std::pow(fShift,2))/(
647  std::pow(dirShiftVector[0],2)+
648  std::pow(dirShiftVector[1],2)+
649  std::pow(dirShiftVector[2],2)));
650  fShiftVec = dirShiftVector*param;
651 
652  // compute offset only if it was not given
653  if ((fOffset[0] == FLT_MAX) && (fOffset[1] == FLT_MAX) && (fOffset[2] == FLT_MAX)){
654  fOffset = listPoints[0]+fShiftVec*fOffsetValue;
655  }
656  }
657 
658 
659  /////////////////////////////////////////////
660  // START to compute
661  // We compute each line one by one to know witch hatch will be draw thrue this line
662  // we try to know the result of
663  // (origin_point_of_hatch)+i*(directionVector)+j*(shiftVector) = each_point_of_polyline
664  // We will be interest only on j factor for the moment. This factor represent the offset
665  // between the Origin point of the hatch and the compute point of the polyline
666  // We put results in a float table
667  //
668  // We also have to memorize the min and max number of the hatch to be draw
669  // Point 0 1 2 3 4 5 6 ...n 1
670  // hatchShiftToMatchPoint 5 7 2 6 7 8 5 ...2 5
671  // min = 1 max = 8 -> 8 hatch to draw
672  ////////////////////////////////////////////
673 
674  fHatchShiftToMatchPointVec.resize(numberOfPolylinePoints+1);
675  float minShiftHatch =FLT_MAX;
676  float maxShiftHatch =-FLT_MAX;
677  vec2f res;
678 
679  for (int a=0;a<numberOfPolylinePoints;a++) {
680  res = resolve_system(fDirVec.getValue(),
681  fShiftVec,
682  listPoints[a]-fOffset);
683  // test result
684  if (fResolveResult ==0 ) {
685  fHatchShiftToMatchPointVec[a] = res[1];
686  if (res[1]>maxShiftHatch) {
687  maxShiftHatch = res[1];
688  }
689  if (res[1]<minShiftHatch) {
690  minShiftHatch = res[1];
691  }
692  }
693  else { // never done (should be test before)
694 #ifdef TOOLS_HATCHER_DEBUG
695  ::printf("hatcher::drawPolyline : ERROR one or more of your polyline points are not on the same plan ! Testing point %d/%d error:%d\n\n",a,numberOfPolylinePoints,fResolveResult);
696 #endif
697  delete [] listPoints;
698  return false;
699  }
700  }
701  // for the first point to close the polyline
702  fHatchShiftToMatchPointVec[numberOfPolylinePoints] = fHatchShiftToMatchPointVec[0];
703  fFirstNumHatch = (int)(ceilf(minShiftHatch));
704  fNumberHatchToDraw = (int)(floorf(maxShiftHatch)-fFirstNumHatch+1);
705  if ((int)(floorf(maxShiftHatch)-fFirstNumHatch+1) <0) fNumberHatchToDraw =0;
706 
707  int moreNumberHatchToDraw = fNumberHatchToDraw+1;
708  std::vector<vec3f> listHatchStartPoint;
709  std::vector<vec3f> listHatchEndPoint;
710  std::vector<int> numberOfStartEndPointsVec;
711 
712  fConflictNumHatchLineTab.resize(moreNumberHatchToDraw);
713 
714  // initialize tab
715  for (int a=0;a<moreNumberHatchToDraw;a++) {
716  numberOfStartEndPointsVec.push_back(0);
717  listHatchStartPoint.push_back(vec3f(.0f,.0f,.0f));
718  listHatchEndPoint.push_back(vec3f(.0f,.0f,.0f));
719  fConflictNumHatchLineTab[a].clear();
720  }
721 
722  /////////////////////////////////////////////
723  // Compute the normalize shift vector for all lines
724  // the normal Vector for point 3 to 4 will be listNormalvec[2]
725  /////////////////////////////////////////////
726 
727  for (int a=0;a<numberOfPolylinePoints-1;a++) {
728  res = resolve_system(fDirVec.getValue(),
729  vec3f(listPoints[a].getValue()[0]-listPoints[a+1].getValue()[0],
730  listPoints[a].getValue()[1]-listPoints[a+1].getValue()[1],
731  listPoints[a].getValue()[2]-listPoints[a+1].getValue()[2]),
732  -fShiftVec);
733  if (fResolveResult ==0 ) {
734  listNormalVec.push_back(vec3f(res[1]*(listPoints[a+1].getValue()[0]-listPoints[a].getValue()[0]),
735  res[1]*(listPoints[a+1].getValue()[1]-listPoints[a].getValue()[1]),
736  res[1]*(listPoints[a+1].getValue()[2]-listPoints[a].getValue()[2])
737  ));
738  }
739  else if (fResolveResult == RESOLVE_Z_ERROR ) { // never done (should be test before)
740 #ifdef TOOLS_HATCHER_DEBUG
741  ::printf("hatcher::drawPolyline : ERROR one or more of your polyline points are not on the same plan !\n\n");
742 #endif
743  delete [] listPoints;
744  return false;
745  }
746  else{
747  listNormalVec.push_back(vec3f(FLT_MAX,FLT_MAX,FLT_MAX));
748  // listNormalVec.append(new vec3f(FLT_MAX,FLT_MAX,FLT_MAX));
749  }
750  }
751 
752  /////////////////////////////////////////////
753  // Compute the hatchShiftToMatchPointVec table to try to get the start
754  // and end point of each hatch
755  // if there is more than one start/end point, we will resolve it later. For the moment,
756  // we put confict points into a table
757  // HatchNumber 1 2 3 4 5 6 7 8 9
758  // listHatchStartPoint 1,0,0 1,1,0 0,0,1 0,1,0 1,1,0 0,2,0 1,1,4
759  // listHatchEndPoint ..............
760  // conflictNumHatchLineTab 5 6 7
761  // line Number is 0 for (point[0]->point[1])
762  // We put each line number into the conflict table to be sure to get all the lines
763  // in conflict. When we will thest the value of the conflicy table, it should
764  // be greater than 2 to have a conflict
765  /////////////////////////////////////////////
766 
767  vec3f newPoint;
768  int minHatch;
769  int maxHatch;
770  int hatchIndice =0;
771 
772  for (int indPolyline=0;indPolyline<numberOfPolylinePoints-1;indPolyline++) {
773  minHatch = (int)(ceilf(fHatchShiftToMatchPointVec[indPolyline]));
774  maxHatch = (int)(floorf(fHatchShiftToMatchPointVec[indPolyline+1]));
775 
776  if (fHatchShiftToMatchPointVec[indPolyline+1] <fHatchShiftToMatchPointVec[indPolyline]) {
777  minHatch =(int)(ceilf(fHatchShiftToMatchPointVec[indPolyline+1]));
778  maxHatch = (int)(floorf(fHatchShiftToMatchPointVec[indPolyline]));
779  }
780  for (int b=minHatch;b<=maxHatch;b++) { // for all number of hatch fund
781  // compute new point
782  hatchIndice = b-fFirstNumHatch;
783 
784  newPoint.setValue(listPoints[indPolyline].getValue()[0]+
785  listNormalVec[indPolyline][0]*(b-fHatchShiftToMatchPointVec[indPolyline]),
786  listPoints[indPolyline].getValue()[1]+
787  listNormalVec[indPolyline][1]*(b-fHatchShiftToMatchPointVec[indPolyline]),
788  listPoints[indPolyline].getValue()[2]+
789  listNormalVec[indPolyline][2]*(b-fHatchShiftToMatchPointVec[indPolyline]));
790 
791  if (numberOfStartEndPointsVec[hatchIndice] == 0) {// it is the first point
792  //compute point and save it
793  // the start point will be :
794  // Point_of_the_line + normalVec *
795  //(number_of_hatch_to_compute - number_of_hatch_corresponding_to_first_point_of_line)
796  //
797  if ( (listNormalVec[indPolyline][0] != FLT_MAX)
798  && (listNormalVec[indPolyline][1] != FLT_MAX)
799  && (listNormalVec[indPolyline][2] != FLT_MAX)) {
800  listHatchStartPoint[hatchIndice] = vec3f(newPoint);
801  fConflictNumHatchLineTab[hatchIndice].push_back(indPolyline);
802  numberOfStartEndPointsVec[hatchIndice]++;
803  }
804  } else if (numberOfStartEndPointsVec[hatchIndice] == 1) { // it is the second point
805  //compute point and save it (same point as previous )
806  // the start point will be :
807  // Point_of_the_line + normalVec *
808  // (number_of_hatch_to_compute - number_of_hatch_corresponding_to_first_point_of_line)
809  // store only if newPoint is != start
810  if ((listNormalVec[indPolyline][0] != FLT_MAX)
811  && (listNormalVec[indPolyline][1] != FLT_MAX)
812  && (listNormalVec[indPolyline][2] != FLT_MAX)) {
813  listHatchEndPoint[hatchIndice] = vec3f(newPoint);
814  fConflictNumHatchLineTab[hatchIndice].push_back(indPolyline);
815  numberOfStartEndPointsVec[hatchIndice]++;
816  }
817  } else { // there is a conflict, we don't compute anything except for conflicts on points
818  // witch are already compute
819  // case of the hatch will be draw on a point of the polyline,
820  // so it match 2 lines + another
821  fConflictNumHatchLineTab[hatchIndice].push_back(indPolyline); // put the line number in conflict table
822  }
823  }
824  }
825 
826  /////////////////////////////////////////////
827  // Compute the numHatchLine tab and draw correct points
828  /////////////////////////////////////////////
829  std::vector<float> listCoefDirHatch(fNumberHatchToDraw);
830  std::vector<vec3f> listConflictPoints(numberOfPolylinePoints);
831 
832  vec3f ABVec,tempVec;
833  int valid =false;
834  bool drawEnabled = false; // true : we could draw second point, false we wait for the first
835  float temp=0;
836  int tempInt =0;
837  float nextPointConflictHatchNumber = -FLT_MAX;
838  float currentPointConflictHatchNumber = -FLT_MAX;
839  std::vector<unsigned int> orderConflictLineNumber;
840 
841  for (unsigned int hatchNumber =0;hatchNumber<fNumberHatchToDraw;hatchNumber++) {
842  if ( fConflictNumHatchLineTab[hatchNumber].size() <= 2) {
843  if (!listHatchStartPoint[hatchNumber].equals(listHatchEndPoint[hatchNumber],FLT_EPSILON*FLT_EPSILON*10)) {
844  fPoints.push_back(listHatchStartPoint[hatchNumber]);
845  fPoints.push_back(listHatchEndPoint[hatchNumber]);
846  fVertices.push_back(2);
847  }
848  } else { // there is a conflict
849  // We read the conflict table and compute all the conflict lines
850  // conflict is on hatch number hatchNumber+ firstNumHatch
851  // Compute the equation on the conflict line (called ABVec ):
852  // i*dirVec - j*ABVec = A-(offset + shiftVec * numberHatchToDraw)
853  // and store the i parameter
854  // then we
855 
856  listConflictPoints.clear();
857  listCoefDirHatch.clear();
858  std::vector <unsigned int> toRemove;
859  for (unsigned int conflictLineNumber=0;conflictLineNumber<fConflictNumHatchLineTab[hatchNumber].size();conflictLineNumber++ )
860  {
861 
862  ABVec.setValue(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]+1].getValue()[0]-listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[0],
863  listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]+1].getValue()[1]-listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[1],
864  listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]+1].getValue()[2]-listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[2]);
865 
866  res = resolve_system(fDirVec.getValue(),
867  ABVec,
868  vec3f(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[0]-fOffset[0]-((float)hatchNumber+(float)fFirstNumHatch)*fShiftVec[0],
869  listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[1]-fOffset[1]-((float)hatchNumber+(float)fFirstNumHatch)*fShiftVec[1],
870  listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]].getValue()[2]-fOffset[2]-((float)hatchNumber+(float)fFirstNumHatch)*fShiftVec[2]));
871 
872  if (fResolveResult ==0 ) {
873  // we store results
874  listCoefDirHatch.push_back(2);
875  listCoefDirHatch.pop_back();
876  listCoefDirHatch.push_back(res[0]);
877  res[1] = -res[1];
878  listConflictPoints.push_back(vec3f(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictLineNumber]]+ABVec*res[1]));
879  }
880  else if (fResolveResult != RESOLVE_COLINEAR){
881 #ifdef TOOLS_HATCHER_DEBUG
882  printf("hatcher : Precision error during compute on hatch number%d\n\n",hatchNumber);
883 #endif
884  precisionError++;
885  } else {
886  toRemove.push_back(conflictLineNumber);
887  }
888  }
889 
890  if (toRemove.size()) {
891  for (unsigned int conflictLineNumber=0;conflictLineNumber<fConflictNumHatchLineTab[hatchNumber].size();conflictLineNumber++ ) {
892  }
893  // remove potential colinear problems
894  for (unsigned int aa=0;aa<toRemove.size();aa++) {
895  unsigned int ind = 0;
896  for (std::vector<int>::iterator it = fConflictNumHatchLineTab[hatchNumber].begin();it !=fConflictNumHatchLineTab[hatchNumber].end();it++) {
897  if (ind == toRemove[aa]) {
898  fConflictNumHatchLineTab[hatchNumber].erase(it);
899  break;
900  }
901  ind++;
902  }
903  }
904  for (unsigned int conflictLineNumber=0;conflictLineNumber<fConflictNumHatchLineTab[hatchNumber].size();conflictLineNumber++ ) {
905  }
906  }
907  if (listCoefDirHatch.size() != 0) { // all points are resolve_system errors (RESOLVE_COLINEAR or RESOLVE_Z_ERROR
908 
909  // now, we have to sort all coef dir from minus to max
910  // and at the same time, reorder the conflict ponts and the conflict line number
911  // this algorithm is not optimum...
912  valid = false;
913  while (valid ==false )
914  {
915  valid = true;
916  for (unsigned int sort =0;sort< listCoefDirHatch.size()-1;sort++)
917  {
918  if (listCoefDirHatch[sort]>listCoefDirHatch[sort+1]) {
919 
920  temp = listCoefDirHatch[sort];
921  listCoefDirHatch[sort] = listCoefDirHatch[sort+1];
922  listCoefDirHatch[sort+1] =temp;
923  tempVec = listConflictPoints[sort];
924  listConflictPoints[sort] = listConflictPoints[sort+1];
925  listConflictPoints[sort+1] = tempVec;
926  tempInt = fConflictNumHatchLineTab[hatchNumber][sort];
927  fConflictNumHatchLineTab[hatchNumber][sort] = fConflictNumHatchLineTab[hatchNumber][sort+1];
928  fConflictNumHatchLineTab[hatchNumber][sort+1] = tempInt;
929  valid= false;
930  }
931  }
932  }
933 
934  // once dir coef have been sort, we could draw lines !!
935  //witch line had made a conflict ??? conflictNumHatchLineTab[a]
936  unsigned int conflictNumber =0;
937  orderConflictLineNumber.clear();
938 
939  drawEnabled = false;
940  while (conflictNumber < fConflictNumHatchLineTab[hatchNumber].size()) { // while
941  if (conflictNumber+1 == fConflictNumHatchLineTab[hatchNumber].size()) {
942  if(drawEnabled) {
943  drawEnabled = false;
944  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
945  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
946  }
947  }
948  else {
949  // if the conflict point == next conflict point : that is a end/begin line conflict
950  // else, this is not a big problem, we just have to invert the drawEnabled
951  // (if we were drawing, we have to finish a line, else, we have to begin a line
952  if ( !(listConflictPoints[conflictNumber].equals(listConflictPoints[conflictNumber+1],FLT_EPSILON*FLT_EPSILON*10))) {
953  // special case of nextPointline=nextConflict point : hatch//line
954  unsigned int follow=conflictNumber+1;
955  bool overContour = false;
956  while ((follow <fConflictNumHatchLineTab[hatchNumber].size()) &&
957  (listConflictPoints[conflictNumber].equals(listConflictPoints[follow],FLT_EPSILON*FLT_EPSILON*10))) {
958  follow++;
959  }
960  //test if next point is on the contour
961  if(follow < fConflictNumHatchLineTab[hatchNumber].size()) {
962  if ((listConflictPoints[follow].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][follow]].getValue(),FLT_EPSILON*FLT_EPSILON*10))) {
963  if ((fConflictNumHatchLineTab[hatchNumber][follow] != 0) &&
964  (fConflictNumHatchLineTab[hatchNumber][follow] != numberOfPolylinePoints-1)) {
965  if ((listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][follow]-1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) ||
966  (listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][follow]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10))) {
967  overContour = true;
968  }
969  }
970  }
971  }
972  int previous=conflictNumber-1;
973  while ((previous >=0) &&
974  (listConflictPoints[conflictNumber].equals(listConflictPoints[previous],FLT_EPSILON*FLT_EPSILON*10))) {
975  previous--;
976  }
977  //test if next point is on the contour
978  if(previous >= 0) {
979  if ((listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]].getValue(),FLT_EPSILON*FLT_EPSILON*10))) {
980  if ((listConflictPoints[previous].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]-1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) ||
981  (listConflictPoints[previous].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10))) {
982  overContour = true;
983  }
984  }
985  }
986  if (!overContour) { // we are not on a contour, we can draw
987  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
988  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
989  drawEnabled = drawEnabled?false:true;
990  if (drawEnabled) {
991  fVertices.push_back(2);
992  }
993  } else { // else we have to stop drawing
994  if (drawEnabled) {
995  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
996  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
997  drawEnabled = false;
998  }
999  }
1000  }
1001  else { // next point == current
1002  bool currentPointCrossLine = false;
1003  bool nextPointCrossLine = false;
1004  // if the conflict is on a line point, we have to look the hatch number
1005  // of the previous and next point to see if the hatch had to be draw or not
1006 
1007  // test if conflictPoint == first line point
1008  if (listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
1009  // we look second point hatchNumber
1010  currentPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1];
1011  }
1012  else if (listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
1013  // we look first point hatchNumber
1014  currentPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]];
1015  }
1016  else { // case of two lines have intersection point on a hatch
1017  // it is the same case as a "end of line" and a "begin of line" conflict
1018  currentPointCrossLine = true;
1019  currentPointConflictHatchNumber =-1 ;
1020  }
1021  // test if conflictPoint == second line point
1022  if (listConflictPoints[conflictNumber+1].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
1023  // we look second point hatchNumber
1024  nextPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]+1];
1025  }
1026  else if (listConflictPoints[conflictNumber+1].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) {
1027  // we look first point hatchNumber
1028  nextPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]];
1029  }
1030  else { // case of two lines have intersection point on a hatch
1031  // it is the same case as a "end of line" and a "begin of line" conflict
1032  nextPointConflictHatchNumber = -1;
1033  nextPointCrossLine = true;
1034  }
1035 
1036  // we have to compute the currentPointConflictHatchNumber and
1037  // nextPointConflictHatchNumber
1038  // if they are all the same side of the hatch, we have to ignore points
1039  // else, we have to draw a line
1040  if (currentPointCrossLine && nextPointCrossLine) {
1041  // do not draw anything, this is the case of a hatch crossing
1042  // two identical line
1043  }
1044  // case of two points on conflict on a contour point where nothing has to be draw
1045  else if ((!currentPointCrossLine && !nextPointCrossLine) && (currentPointConflictHatchNumber == nextPointConflictHatchNumber) && (currentPointConflictHatchNumber == fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]])) {
1046  if (drawEnabled) {
1047  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
1048  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
1049  drawEnabled = false;
1050  }
1051  }
1052  // we draw
1053  else if( ( (currentPointConflictHatchNumber -
1054  fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]]) *
1055  (nextPointConflictHatchNumber -
1056  fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]]))
1057  <=FLT_EPSILON) {
1058  // try to see if we are trying to draw a hatch OVER a contour
1059  unsigned int follow=conflictNumber+1;
1060  bool overContour = false;
1061  while ((follow <fConflictNumHatchLineTab[hatchNumber].size()) &&
1062  (listConflictPoints[conflictNumber].equals(listConflictPoints[follow],FLT_EPSILON*FLT_EPSILON*10))) {
1063  follow++;
1064  }
1065  if(follow < fConflictNumHatchLineTab[hatchNumber].size()) {
1066  float alpha = 0;
1067  bool findAlpha = true;
1068  if (listConflictPoints[follow][0] != listConflictPoints[conflictNumber][0]) {
1069  alpha = (listPoints[fConflictNumHatchLineTab[hatchNumber][follow]][0]-listConflictPoints[conflictNumber][0])/(listConflictPoints[follow][0]-listConflictPoints[conflictNumber][0]);
1070  }
1071  else if (listConflictPoints[follow][1] != listConflictPoints[conflictNumber][1]) {
1072  alpha = (listPoints[fConflictNumHatchLineTab[hatchNumber][follow]][1]-listConflictPoints[conflictNumber][1])/(listConflictPoints[follow][1]-listConflictPoints[conflictNumber][1]);
1073  }
1074  else if (listConflictPoints[follow][2] != listConflictPoints[conflictNumber][2]) {
1075  alpha = (listPoints[fConflictNumHatchLineTab[hatchNumber][follow]][2]-listConflictPoints[conflictNumber][2])/(listConflictPoints[follow][2]-listConflictPoints[conflictNumber][2]);
1076  }
1077  else {
1078  findAlpha =false;
1079  }
1080  if (findAlpha) {
1081  if ((alpha*(listConflictPoints[follow]-listConflictPoints[conflictNumber])).equals(listPoints[fConflictNumHatchLineTab[hatchNumber][follow]]-listConflictPoints[conflictNumber],FLT_EPSILON*FLT_EPSILON*10)) {
1082  overContour = true;
1083  }
1084  }
1085  }
1086  if (!overContour) { // if we are not on a contour, no problem
1087  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
1088  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
1089  drawEnabled = drawEnabled?false:true;
1090  if (drawEnabled) {
1091  fVertices.push_back(2);
1092  }
1093  } else { // else we have to stop drawing
1094  if (drawEnabled) {
1095  fPoints.push_back(listConflictPoints[conflictNumber].getValue());
1096  orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]);
1097  drawEnabled = false;
1098  }
1099  }
1100  }
1101  conflictNumber ++;
1102  } // end next== current
1103  }
1104  conflictNumber ++;
1105  } // end while
1106  if (drawEnabled) {
1107  fPoints.push_back(fPoints[fPoints.size()-1]);
1108 #ifdef TOOLS_HATCHER_DEBUG
1109  printf("hatcher : Probably a error during conflict resolution on hatch number %d :\nWe have close this line by putting two times the same point.\n\n",hatchNumber);
1110 #endif
1111  }
1112  //re put the order conflictNumHatchLineTab witch could be use by stripWidth
1113  fConflictNumHatchLineTab[hatchNumber].clear();
1114  for(unsigned int a=0;a<orderConflictLineNumber.size();a++) {
1115  fConflictNumHatchLineTab[hatchNumber].push_back(orderConflictLineNumber[a]);}
1116 
1117  // test if it is correct
1118  } // end resolve system errors
1119  } // end conflict
1120  }
1121 
1122  if (fPoints.size() >0){
1123 
1124  if (precisionError == 0){
1125  delete [] listPoints;
1126  return true;
1127  }
1128  else {
1129 #ifdef TOOLS_HATCHER_DEBUG
1130  printf("hatcher : Exit with %d precision error during compute\n\n",precisionError);
1131 #endif
1132  delete [] listPoints;
1133  return false;
1134  }
1135  }
1136  delete [] listPoints;
1137  return true;
1138 }
1139 
1140 
1141 
1142 //////////////////////////////////////////////////////////////////////////////
1143 // Compute a vector system equation aA+bB=C
1144 // return vec2f(0,0) if there is an error
1145 // set the resolveResult variable to the error code :
1146 // COLINEAR if A and B are
1147 // PRECISION_ERROR if there is a lack of precision in computing
1148 // Z_ERROR if there s no solution for Z
1149 // UNDEFINED never throw
1150 // return a vec2f for result. a is 'x' value and b is 'y' if it is correct
1151 //////////////////////////////////////////////////////////////////////////////
1152 
1153 inline vec2f hatcher::resolve_system(const vec3f& A,const vec3f& B,const vec3f& C) {
1154 
1155  fResolveResult = RESOLVE_UNDEFINED;
1156 
1157  double Ax = A[0];
1158  double Ay = A[1];
1159  double Az = A[2];
1160  double Bx = B[0];
1161  double By = B[1];
1162  double Bz = B[2];
1163  double Cx = C[0];
1164  double Cy = C[1];
1165  double Cz = C[2];
1166 
1167  double bDiv = (By*Ax-Ay*Bx);
1168  if (ffabs(float(bDiv)) <=FLT_EPSILON) {
1169  // we have to test in a other order
1170  double tmp;
1171  tmp = Ax; Ax = Ay; Ay = Az; Az = tmp;
1172  tmp = Bx; Bx = By; By = Bz; Bz = tmp;
1173  tmp = Cx; Cx = Cy; Cy = Cz; Cz = tmp;
1174 
1175  bDiv = (By*Ax-Ay*Bx);
1176 
1177  if (ffabs(float(bDiv)) <=FLT_EPSILON) {
1178  // we have to test in a other order
1179  tmp = Ax; Ax = Ay; Ay = Az; Az = tmp;
1180  tmp = Bx; Bx = By; By = Bz; Bz = tmp;
1181  tmp = Cx; Cx = Cy; Cy = Cz; Cz = tmp;
1182 
1183  bDiv = (By*Ax-Ay*Bx);
1184  if (ffabs(float(bDiv)) <=FLT_EPSILON) {
1185  fResolveResult = RESOLVE_COLINEAR;
1186  return vec2f(0,0);
1187  }
1188  }
1189  }
1190  double b= (Cy*Ax-Ay*Cx)/bDiv;
1191  double a= -(Cy*Bx-By*Cx)/bDiv;
1192  double bid = ffabs(float(a*Az+b*Bz - Cz));
1193 
1194  if (bid <= FLT_EPSILON) {
1195  fResolveResult = RESOLVE_OK;
1196  return vec2f((float)a,(float)b);
1197  }
1198  else {
1199 
1200  double minBoxValue = 1;
1201 
1202  double minXValue =FLT_MAX;
1203  double minYValue =FLT_MAX;
1204  double minZValue =FLT_MAX;
1205  if ((A[0] !=0) && ((A[0]) <minXValue)) minXValue = (A[0]);
1206  if ((B[0] !=0) && ((B[0]) <minXValue)) minXValue = (B[0]);
1207  if ((C[0] !=0) && ((C[0]) <minXValue)) minXValue = (C[0]);
1208  if ((A[1] !=0) && ((A[1]) <minYValue)) minYValue = (A[1]);
1209  if ((B[1] !=0) && ((B[1]) <minYValue)) minYValue = (B[1]);
1210  if ((C[1] !=0) && ((C[1]) <minYValue)) minYValue = (C[1]);
1211  if ((A[2] !=0) && ((A[2]) <minZValue)) minZValue = (A[2]);
1212  if ((B[2] !=0) && ((B[2]) <minZValue)) minZValue = (B[2]);
1213  if ((C[2] !=0) && ((C[2]) <minZValue)) minZValue = (C[2]);
1214 
1215 
1216  double maxXValue =-FLT_MAX;
1217  double maxYValue =-FLT_MAX;
1218  double maxZValue =-FLT_MAX;
1219  if ((A[0] !=0) && ((A[0]) >maxXValue)) maxXValue = (A[0]);
1220  if ((B[0] !=0) && ((B[0]) >maxXValue)) maxXValue = (B[0]);
1221  if ((C[0] !=0) && ((C[0]) >maxXValue)) maxXValue = (C[0]);
1222  if ((A[1] !=0) && ((A[1]) >maxYValue)) maxYValue = (A[1]);
1223  if ((B[1] !=0) && ((B[1]) >maxYValue)) maxYValue = (B[1]);
1224  if ((C[1] !=0) && ((C[1]) >maxYValue)) maxYValue = (C[1]);
1225  if ((A[2] !=0) && ((A[2]) >maxZValue)) maxZValue = (A[2]);
1226  if ((B[2] !=0) && ((B[2]) >maxZValue)) maxZValue = (B[2]);
1227  if ((C[2] !=0) && ((C[2]) >maxZValue)) maxZValue = (C[2]);
1228 
1229  if (((maxXValue-minXValue) <= (maxYValue-minYValue)) && ((maxXValue-minXValue) <= (maxZValue-minZValue))) { minBoxValue = maxXValue-minXValue; }
1230  else
1231  if (((maxYValue-minYValue) <= (maxXValue-minXValue)) && ((maxYValue-minYValue) <= (maxZValue-minZValue))) { minBoxValue = maxYValue-minYValue; }
1232  else
1233  { minBoxValue = maxZValue-minZValue; }
1234 
1235  minBoxValue *= fPrecisionFactor;
1236 
1237  if (bid <= minBoxValue) {
1238  fResolveResult = RESOLVE_OK;
1239  return vec2f((float)a,(float)b);
1240  }
1241  else {
1242  if (bid>100*minBoxValue) {
1243 #ifdef TOOLS_HATCHER_DEBUG
1244  printf("hatcher : ***** PRECISON ERROR ON Z ******* compare %f > %f res :%f %f test %f %f bDiv %e\n\n",bid,100*minBoxValue,a,b,a*Ax+b*Bx-Cx,a*Ay+b*By-Cy,bDiv);
1245 #endif
1246  fResolveResult = RESOLVE_Z_ERROR;
1247  }
1248  else
1249  {
1250 #ifdef TOOLS_HATCHER_DEBUG
1251  printf("hatcher : ***** PRECISON ERROR ******* compare %f > %f res :%f %f test %f %f bDiv %e\n\n",bid,100*minBoxValue,a,b,a*Ax+b*Bx-Cx,a*Ay+b*By-Cy,bDiv);
1252 #endif
1253  fResolveResult = RESOLVE_PRECISION_ERROR;
1254  }
1255  //return vec2f(0,0); //G.Barrand : commented out to quiet Coverity.
1256  }
1257  }
1258  return vec2f(0,0);
1259 }
1260 
1261 }
1262 
1263 //#undef TOOLS_HATCHER_DEBUG