// Created by Laurent Garnier on Fri Jan 30 2004. namespace tools { ////////////////////////////////////////////////////////////////////////////// // test if the polygone given is correct for hatching // return FALSE if : // - All points are not in the same plan // - Number of points <3 // - Offset point is not in the same plan // - There is less than three different points // - The vector from point[0],point[1] is colinear to point[0],lastPoint ////////////////////////////////////////////////////////////////////////////// inline bool hatcher::check_polyline(vec3f* listPoints,unsigned int aNumber){ unsigned int firstOffset =0; if ( listPoints[0].equals(listPoints[1],FLT_EPSILON*FLT_EPSILON*10)) { firstOffset =1; } if ( listPoints[0].equals(listPoints[aNumber-1],FLT_EPSILON*FLT_EPSILON*10)) { aNumber --; } if ((int)aNumber-firstOffset <3) { return false; } // use to test the polyline and to build the shift vector. A is the first point, // B second and C the last (in fact, the last-1)! vec3f AB,AC; AB.setValue(listPoints[1+firstOffset].getValue()[0]-listPoints[0].getValue()[0], listPoints[1+firstOffset].getValue()[1]-listPoints[0].getValue()[1], listPoints[1+firstOffset].getValue()[2]-listPoints[0].getValue()[2]); // Vector A->B fResolveResult = RESOLVE_COLINEAR; unsigned int test = aNumber; while ((fResolveResult !=0) && (test>2+firstOffset)) { test--; AC.setValue(listPoints[test].getValue()[0]-listPoints[0].getValue()[0], listPoints[test].getValue()[1]-listPoints[0].getValue()[1], listPoints[test].getValue()[2]-listPoints[0].getValue()[2]); // test if AB != AC*i resolve_system( AB, AC, vec3f(.0f,.0f,.0f)); } if (fResolveResult == RESOLVE_COLINEAR) { return false; } /////////////////////////////////////////////////////////////// // test if all points of the polyline are on the same plan /////////////////////////////////////////////////////////////// int falsePoints =0; for (unsigned int a=2+firstOffset;a> ,5 * 2 '2 * And we have to add some points when HatchShiftToMacthPoint(point) is between current * and next hatch : We add a point B on intersection of line 0 and 1 * current next current next * ,4 ,4 * '0 B(0,1) '5 * ,1 * '3 ,3 * ,5 '2 * '2 * * Now we have to match a way to traverse all of theses lines. We have 3 solutions to go from * one line to another : * - go to the next point if there is one between current and next hatch * - go to the same line but on another hatch * - go to the next tach point * If there is no solution, we have to close the polyline strip and go to another point until * all are compute */ /** first, we have to match 7 different cases * 1- all strip hatch are entirely in the polyline * 2- the first strip begin before the polyline and the last end in the polyline * 3- the first strip begin before the polyline and the last ends after * 4- the first strip is entierly in the polyline and the last ends after * 5- the strip has only an intersection with the second hatch sequence (if it has only an intersection * with the first hatch sequence, it is case 2 * 6- the strip has a full intersection * 7- the strip has no intersection ! */ inline bool hatcher::compute_polyline (vec3f* tabPoints,unsigned int aNumber) { std::vector firstComputePoints; // copy first Points in std::vector secondComputePoints; // copy first Points in std::vector firstComputePointsEnable; // table of already compute points for first hatch std::vector secondComputePointsEnable;// table of already compute points for second hatch std::vector< std::vector > firstComputeConflictNumHatchLineTab; // copy firstComputeConflictNumHatchLineTab in int firstComputeFirstNumHatch =0; unsigned int firstComputeNumberHatchToDraw =0; float firstHatchShiftToMatchFirstPoint = FLT_MAX; // use in one case when there is no intersection points: to test we have to fill all the polygone float secondHatchShiftToMatchFirstPoint = FLT_MAX; // use in one case when there is no intersection points: to test we have to fill all the polygone //call compute for first set of hatch if ( !compute_single_polyline (tabPoints,aNumber)) return false; if (fStripWidth ==0) return true; //save values for (unsigned int a =0;a fFirstNumHatch) && (firstComputeNumberHatchToDraw < fNumberHatchToDraw) && (firstComputeNumberHatchToDraw !=0)) { //insert a empty element at the beginning firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(), firstComputeConflictNumHatchLineTab.back()); firstComputeConflictNumHatchLineTab[0].resize(0); firstComputeFirstNumHatch--; firstComputeNumberHatchToDraw ++; firstComputeConflictNumHatchLineTab[0].clear(); specialCase =2; } //second hatch, case 3 else if (((firstComputeFirstNumHatch > fFirstNumHatch) && (firstComputeNumberHatchToDraw == fNumberHatchToDraw)) && (firstComputeNumberHatchToDraw !=0)) { //insert a empty element at the beginning firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(),firstComputeConflictNumHatchLineTab.back()); firstComputeConflictNumHatchLineTab[0].resize(0); firstComputeConflictNumHatchLineTab[0].clear(); //insert a empty element at the end fConflictNumHatchLineTab.push_back(firstComputeConflictNumHatchLineTab.back()); fConflictNumHatchLineTab.back().resize(0); fConflictNumHatchLineTab.back().clear(); firstComputeFirstNumHatch--; firstComputeNumberHatchToDraw ++; specialCase =3; } //second hatch, case 4 else if (((firstComputeFirstNumHatch == fFirstNumHatch) && (firstComputeNumberHatchToDraw > fNumberHatchToDraw)) && (firstComputeNumberHatchToDraw !=0)) { //insert a empty element at the end fConflictNumHatchLineTab.push_back(firstComputeConflictNumHatchLineTab.back()); fConflictNumHatchLineTab.back().resize(0); fConflictNumHatchLineTab.back().clear(); specialCase =4; } //second hatch, case 5 else if ((firstComputeNumberHatchToDraw ==0) && (fNumberHatchToDraw !=0)) { //insert a empty element at the beginning firstComputeConflictNumHatchLineTab.insert(firstComputeConflictNumHatchLineTab.begin(),firstComputeConflictNumHatchLineTab.back()); firstComputeConflictNumHatchLineTab[0].resize(0); firstComputeConflictNumHatchLineTab[0].clear(); firstComputeNumberHatchToDraw ++; specialCase =5; } //second hatch, case 6 else if (floorf(firstHatchShiftToMatchFirstPoint) != floorf(secondHatchShiftToMatchFirstPoint)) { specialCase =6; //fill all the polygone ! fVertices.push_back(aNumber); for (unsigned int a =0;a ((float)firstComputeFirstNumHatch+(float)indHatch-fStripWidth)) && (fHatchShiftToMatchPointVec[indTmp] < ((float)firstComputeFirstNumHatch+(float)indHatch)) && ((indTmp == lineNumber) || (indTmp==lineNumber+1) || ((lineNumber == (aNumber-1)) && (indTmp ==0)))) { find = false; unsigned a =0; while ((a0) lineNumber = indTmp-1; else lineNumber = aNumber-1; } else { if (indTmp < aNumber-1) lineNumber = indTmp; else lineNumber = 0; } } } indTmp++; } } } // end of current hatch //test of second hatch if currentHatch is second if ((oldSolution != 0) && (solution !=2) && (currentHatch !=0)) { if (oldSolution != 3){ // could go to first solution int index =0; if ((secondHatchComputePoint % 2 == 0) && (secondComputePointsEnable[secondHatchComputePoint+1] == false)) index =1; else if ((secondHatchComputePoint % 2 != 0) && (secondComputePointsEnable[secondHatchComputePoint-1] == false)) index = -1; if (index !=0){ solution = 1; secondHatchComputePoint = secondHatchComputePoint+index; fPoints.push_back(secondComputePoints[secondHatchComputePoint+secondPointTabInd]); fVertices.back() ++; secondComputePointsEnable[secondHatchComputePoint] = true; lineNumber = fConflictNumHatchLineTab[indHatch][secondHatchComputePoint]; } } if (solution == 0) { // could go to second solution indTmp = 0; while ((solution == 0) && (indTmp < firstComputeConflictNumHatchLineTab[indHatch].size())) { if ((firstComputeConflictNumHatchLineTab[indHatch][indTmp] == (int)lineNumber) && (firstComputePointsEnable[indTmp] == false)) { solution =2; fPoints.push_back(firstComputePoints[indTmp+firstPointTabInd]); fVertices.back() ++; firstComputePointsEnable[indTmp] = true; lineNumber = firstComputeConflictNumHatchLineTab[indHatch][indTmp]; firstHatchComputePoint = indTmp; currentHatch =0; } indTmp ++; } } if (solution == 0) { // could go to first solution indTmp = 0; while ((solution == 0) && (indTmp < aNumber)) { if ((fHatchShiftToMatchPointVec[indTmp] > ((float)fFirstNumHatch+(float)indHatch-fStripWidth)) && (fHatchShiftToMatchPointVec[indTmp] < ((float)fFirstNumHatch+(float)indHatch)) && ((indTmp == lineNumber) || (indTmp==lineNumber+1) || ((lineNumber == (aNumber-1)) && (indTmp ==0)))) { find = false; unsigned a =0; while ((a0) lineNumber = indTmp-1; else lineNumber = aNumber-1; } else { if (indTmp < aNumber-1) lineNumber = indTmp; else lineNumber = 0; } } } indTmp++; } } } // end of current hatch if (solution == 0) { // the end for this polyline // close polyline fPoints.push_back(fPoints[fPoints.size()-fVertices.back()]); fVertices.back() ++; result =true; } } // while solution !=0 // } // if result } // while result for (unsigned int a =0;a listNormalVec; int numberOfPolylinePoints =0; fPoints.resize(0); fPoints.clear(); int precisionError =0; unsigned int firstOffset =0; fFirstNumHatch =0; fNumberHatchToDraw =0; fVertices.resize(0); fVertices.clear(); if ( tabPoints[0].equals(tabPoints[1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) { firstOffset =1; } vec3f* listPoints = new vec3f[aNumber+1-firstOffset]; for (unsigned int i=0;iB fResolveResult = RESOLVE_COLINEAR; unsigned int test = numberOfPolylinePoints-1; while ((fResolveResult !=0) && (test>1)) { test--; AC.setValue(listPoints[test].getValue()[0]-listPoints[0].getValue()[0], listPoints[test].getValue()[1]-listPoints[0].getValue()[1], listPoints[test].getValue()[2]-listPoints[0].getValue()[2]); // test if AB != AC*i resolve_system( AB, AC, vec3f(.0f,.0f,.0f)); } if (fResolveResult == RESOLVE_COLINEAR) { delete [] listPoints; return false; } /////////////////////////////////////////////////////////////// // creation of the dirVec. It is done with the dirAngle field // The angle is the one between the first line (point 1-point0) // and the dirVec, on the plan delimited by polyline // Given in the direct axis ((point1-point0),(lastPoint-point0),normalPlanVec) // Normal plane Vector = AB x AC /////////////////////////////////////////////////////////////// if (fFirstPolyline) { fFirstPolyline = false; fNormal.setValue(AB[1]*AC[2]-AB[2]*AC[1], AB[2]*AC[0]-AB[0]*AC[2], AB[0]*AC[1]-AB[1]*AC[0]); // ABPerp Vector = normal x AB vec3f ABPerpVector; ABPerpVector.setValue(fNormal[1]*AB[2]-fNormal[2]*AB[1], fNormal[2]*AB[0]-fNormal[0]*AB[2], fNormal[0]*AB[1]-fNormal[1]*AB[0]); float normAB =(float)std::sqrt(std::pow(AB[0],2)+ std::pow(AB[1],2)+ std::pow(AB[2],2)); float normABPerpVector =(float)std::sqrt(std::pow(ABPerpVector[0],2)+ std::pow(ABPerpVector[1],2)+ std::pow(ABPerpVector[2],2)); float j = std::tan(fDirAngle)*normAB/normABPerpVector; if (normABPerpVector == 0){ // never done (should be test before) delete [] listPoints; return false; } fDirVec = AB +(float)j*ABPerpVector; // normalize vector to unit on X or on Y if (fDirVec.getValue()[0] ==0){ fDirVec[0] = fPrecisionFactor; // to get rid of somes errors fDirVec = fDirVec/fDirVec.getValue()[1]; // normalize on Y because X will be a big value } else { fDirVec = fDirVec/fDirVec.getValue()[0]; } /////////////////////////////////////////////////////////////// // creation of the shiftVec thanks to the shift field /////////////////////////////////////////////////////////////// vec3f dirShiftVector; dirShiftVector.setValue(fNormal[1]*fDirVec.getValue()[2]-fNormal[2]*fDirVec.getValue()[1], fNormal[2]*fDirVec.getValue()[0]-fNormal[0]*fDirVec.getValue()[2], fNormal[0]*fDirVec.getValue()[1]-fNormal[1]*fDirVec.getValue()[0]); // normalize vector to match the shift size float param = 1.0f; param = (float)std::sqrt((std::pow(fShift,2))/( std::pow(dirShiftVector[0],2)+ std::pow(dirShiftVector[1],2)+ std::pow(dirShiftVector[2],2))); fShiftVec = dirShiftVector*param; // compute offset only if it was not given if ((fOffset[0] == FLT_MAX) && (fOffset[1] == FLT_MAX) && (fOffset[2] == FLT_MAX)){ fOffset = listPoints[0]+fShiftVec*fOffsetValue; } } ///////////////////////////////////////////// // START to compute // We compute each line one by one to know witch hatch will be draw thrue this line // we try to know the result of // (origin_point_of_hatch)+i*(directionVector)+j*(shiftVector) = each_point_of_polyline // We will be interest only on j factor for the moment. This factor represent the offset // between the Origin point of the hatch and the compute point of the polyline // We put results in a float table // // We also have to memorize the min and max number of the hatch to be draw // Point 0 1 2 3 4 5 6 ...n 1 // hatchShiftToMatchPoint 5 7 2 6 7 8 5 ...2 5 // min = 1 max = 8 -> 8 hatch to draw //////////////////////////////////////////// fHatchShiftToMatchPointVec.resize(numberOfPolylinePoints+1); float minShiftHatch =FLT_MAX; float maxShiftHatch =-FLT_MAX; vec2f res; for (int a=0;amaxShiftHatch) { maxShiftHatch = res[1]; } if (res[1] listHatchStartPoint; std::vector listHatchEndPoint; std::vector numberOfStartEndPointsVec; fConflictNumHatchLineTab.resize(moreNumberHatchToDraw); // initialize tab for (int a=0;apoint[1]) // We put each line number into the conflict table to be sure to get all the lines // in conflict. When we will thest the value of the conflicy table, it should // be greater than 2 to have a conflict ///////////////////////////////////////////// vec3f newPoint; int minHatch; int maxHatch; int hatchIndice =0; for (int indPolyline=0;indPolyline listCoefDirHatch(fNumberHatchToDraw); std::vector listConflictPoints(numberOfPolylinePoints); vec3f ABVec,tempVec; int valid =false; bool drawEnabled = false; // true : we could draw second point, false we wait for the first float temp=0; int tempInt =0; float nextPointConflictHatchNumber = -FLT_MAX; float currentPointConflictHatchNumber = -FLT_MAX; std::vector orderConflictLineNumber; for (unsigned int hatchNumber =0;hatchNumber toRemove; for (unsigned int conflictLineNumber=0;conflictLineNumber::iterator it = fConflictNumHatchLineTab[hatchNumber].begin();it !=fConflictNumHatchLineTab[hatchNumber].end();it++) { if (ind == toRemove[aa]) { fConflictNumHatchLineTab[hatchNumber].erase(it); break; } ind++; } } for (unsigned int conflictLineNumber=0;conflictLineNumberlistCoefDirHatch[sort+1]) { temp = listCoefDirHatch[sort]; listCoefDirHatch[sort] = listCoefDirHatch[sort+1]; listCoefDirHatch[sort+1] =temp; tempVec = listConflictPoints[sort]; listConflictPoints[sort] = listConflictPoints[sort+1]; listConflictPoints[sort+1] = tempVec; tempInt = fConflictNumHatchLineTab[hatchNumber][sort]; fConflictNumHatchLineTab[hatchNumber][sort] = fConflictNumHatchLineTab[hatchNumber][sort+1]; fConflictNumHatchLineTab[hatchNumber][sort+1] = tempInt; valid= false; } } } // once dir coef have been sort, we could draw lines !! //witch line had made a conflict ??? conflictNumHatchLineTab[a] unsigned int conflictNumber =0; orderConflictLineNumber.clear(); drawEnabled = false; while (conflictNumber < fConflictNumHatchLineTab[hatchNumber].size()) { // while if (conflictNumber+1 == fConflictNumHatchLineTab[hatchNumber].size()) { if(drawEnabled) { drawEnabled = false; fPoints.push_back(listConflictPoints[conflictNumber].getValue()); orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]); } } else { // if the conflict point == next conflict point : that is a end/begin line conflict // else, this is not a big problem, we just have to invert the drawEnabled // (if we were drawing, we have to finish a line, else, we have to begin a line if ( !(listConflictPoints[conflictNumber].equals(listConflictPoints[conflictNumber+1],FLT_EPSILON*FLT_EPSILON*10))) { // special case of nextPointline=nextConflict point : hatch//line unsigned int follow=conflictNumber+1; bool overContour = false; while ((follow =0) && (listConflictPoints[conflictNumber].equals(listConflictPoints[previous],FLT_EPSILON*FLT_EPSILON*10))) { previous--; } //test if next point is on the contour if(previous >= 0) { if ((listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]].getValue(),FLT_EPSILON*FLT_EPSILON*10))) { if ((listConflictPoints[previous].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]-1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) || (listConflictPoints[previous].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10))) { overContour = true; } } } if (!overContour) { // we are not on a contour, we can draw fPoints.push_back(listConflictPoints[conflictNumber].getValue()); orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]); drawEnabled = drawEnabled?false:true; if (drawEnabled) { fVertices.push_back(2); } } else { // else we have to stop drawing if (drawEnabled) { fPoints.push_back(listConflictPoints[conflictNumber].getValue()); orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]); drawEnabled = false; } } } else { // next point == current bool currentPointCrossLine = false; bool nextPointCrossLine = false; // if the conflict is on a line point, we have to look the hatch number // of the previous and next point to see if the hatch had to be draw or not // test if conflictPoint == first line point if (listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]].getValue(),FLT_EPSILON*FLT_EPSILON*10)) { // we look second point hatchNumber currentPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1]; } else if (listConflictPoints[conflictNumber].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) { // we look first point hatchNumber currentPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]]; } else { // case of two lines have intersection point on a hatch // it is the same case as a "end of line" and a "begin of line" conflict currentPointCrossLine = true; currentPointConflictHatchNumber =-1 ; } // test if conflictPoint == second line point if (listConflictPoints[conflictNumber+1].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]].getValue(),FLT_EPSILON*FLT_EPSILON*10)) { // we look second point hatchNumber nextPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]+1]; } else if (listConflictPoints[conflictNumber+1].equals(listPoints[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]+1].getValue(),FLT_EPSILON*FLT_EPSILON*10)) { // we look first point hatchNumber nextPointConflictHatchNumber = fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber+1]]; } else { // case of two lines have intersection point on a hatch // it is the same case as a "end of line" and a "begin of line" conflict nextPointConflictHatchNumber = -1; nextPointCrossLine = true; } // we have to compute the currentPointConflictHatchNumber and // nextPointConflictHatchNumber // if they are all the same side of the hatch, we have to ignore points // else, we have to draw a line if (currentPointCrossLine && nextPointCrossLine) { // do not draw anything, this is the case of a hatch crossing // two identical line } // case of two points on conflict on a contour point where nothing has to be draw else if ((!currentPointCrossLine && !nextPointCrossLine) && (currentPointConflictHatchNumber == nextPointConflictHatchNumber) && (currentPointConflictHatchNumber == fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]])) { if (drawEnabled) { fPoints.push_back(listConflictPoints[conflictNumber].getValue()); orderConflictLineNumber.push_back(fConflictNumHatchLineTab[hatchNumber][conflictNumber]); drawEnabled = false; } } // we draw else if( ( (currentPointConflictHatchNumber - fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]]) * (nextPointConflictHatchNumber - fHatchShiftToMatchPointVec[fConflictNumHatchLineTab[hatchNumber][conflictNumber]])) <=FLT_EPSILON) { // try to see if we are trying to draw a hatch OVER a contour unsigned int follow=conflictNumber+1; bool overContour = false; while ((follow 0){ if (precisionError == 0){ delete [] listPoints; return true; } else { delete [] listPoints; return false; } } delete [] listPoints; return true; } ////////////////////////////////////////////////////////////////////////////// // Compute a vector system equation aA+bB=C // return vec2f(0,0) if there is an error // set the resolveResult variable to the error code : // COLINEAR if A and B are // PRECISION_ERROR if there is a lack of precision in computing // Z_ERROR if there s no solution for Z // UNDEFINED never throw // return a vec2f for result. a is 'x' value and b is 'y' if it is correct ////////////////////////////////////////////////////////////////////////////// inline vec2f hatcher::resolve_system(const vec3f& A,const vec3f& B,const vec3f& C) { fResolveResult = RESOLVE_UNDEFINED; double Ax = A[0]; double Ay = A[1]; double Az = A[2]; double Bx = B[0]; double By = B[1]; double Bz = B[2]; double Cx = C[0]; double Cy = C[1]; double Cz = C[2]; double bDiv = (By*Ax-Ay*Bx); if (ffabs(float(bDiv)) <=FLT_EPSILON) { // we have to test in a other order double tmp; tmp = Ax; Ax = Ay; Ay = Az; Az = tmp; tmp = Bx; Bx = By; By = Bz; Bz = tmp; tmp = Cx; Cx = Cy; Cy = Cz; Cz = tmp; bDiv = (By*Ax-Ay*Bx); if (ffabs(float(bDiv)) <=FLT_EPSILON) { // we have to test in a other order tmp = Ax; Ax = Ay; Ay = Az; Az = tmp; tmp = Bx; Bx = By; By = Bz; Bz = tmp; tmp = Cx; Cx = Cy; Cy = Cz; Cz = tmp; bDiv = (By*Ax-Ay*Bx); if (ffabs(float(bDiv)) <=FLT_EPSILON) { fResolveResult = RESOLVE_COLINEAR; return vec2f(0,0); } } } double b= (Cy*Ax-Ay*Cx)/bDiv; double a= -(Cy*Bx-By*Cx)/bDiv; double bid = ffabs(float(a*Az+b*Bz - Cz)); if (bid <= FLT_EPSILON) { fResolveResult = RESOLVE_OK; return vec2f((float)a,(float)b); } else { double minBoxValue = 1; double minXValue =FLT_MAX; double minYValue =FLT_MAX; double minZValue =FLT_MAX; if ((A[0] !=0) && ((A[0]) maxXValue)) maxXValue = (A[0]); if ((B[0] !=0) && ((B[0]) >maxXValue)) maxXValue = (B[0]); if ((C[0] !=0) && ((C[0]) >maxXValue)) maxXValue = (C[0]); if ((A[1] !=0) && ((A[1]) >maxYValue)) maxYValue = (A[1]); if ((B[1] !=0) && ((B[1]) >maxYValue)) maxYValue = (B[1]); if ((C[1] !=0) && ((C[1]) >maxYValue)) maxYValue = (C[1]); if ((A[2] !=0) && ((A[2]) >maxZValue)) maxZValue = (A[2]); if ((B[2] !=0) && ((B[2]) >maxZValue)) maxZValue = (B[2]); if ((C[2] !=0) && ((C[2]) >maxZValue)) maxZValue = (C[2]); if (((maxXValue-minXValue) <= (maxYValue-minYValue)) && ((maxXValue-minXValue) <= (maxZValue-minZValue))) { minBoxValue = maxXValue-minXValue; } else if (((maxYValue-minYValue) <= (maxXValue-minXValue)) && ((maxYValue-minYValue) <= (maxZValue-minZValue))) { minBoxValue = maxYValue-minYValue; } else { minBoxValue = maxZValue-minZValue; } minBoxValue *= fPrecisionFactor; if (bid <= minBoxValue) { fResolveResult = RESOLVE_OK; return vec2f((float)a,(float)b); } else { if (bid>100*minBoxValue) { fResolveResult = RESOLVE_Z_ERROR; } else { fResolveResult = RESOLVE_PRECISION_ERROR; } } } return vec2f(0,0); } }