Geant4-11
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
9namespace 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
21inline 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
162inline 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
527inline 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
1153inline 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