/* see Utils.h for documentation \tableofcontents */ #include "RegionInterpolator.h" using namespace std; namespace RegionInterpol { /* 1 Static Methods 1.1 getArea() */ double Utils :: getArea(LineWA linelist[], int linelistlength) { long double res = 0.0; for(int i = 0; i < linelistlength; i++) { int ip = (i + 1) % linelistlength; long double llixlliy = linelist[i].getX() * linelist[i].getY(); long double llixllipy = linelist[i].getX() * linelist[ip].getY(); long double llipxlliy = linelist[ip].getX()* linelist[i].getY(); long double llipxllipy = linelist[ip].getX()* linelist[ip].getY(); long double summe1 = llixlliy + llixllipy; long double summe2 = llipxlliy + llipxllipy; res+=(summe1-summe2) / 2.0; } return(res); } double Utils :: getArea(vector lines) { double res = 0.0; for(unsigned int i = 0; i < lines.size(); i++) { int ip = (i + 1) % lines.size(); res = res + ((lines[i]->getX() - lines[ip]->getX()) * (lines[i]->getY() + lines[ip]->getY())) / 2.0; } return(res); } double Utils :: getArea(vector *lines) { double res = 0.0; for(unsigned int i = 0; i < lines->size(); i++) { int ip = (i + 1) % lines->size(); res = res + ((lines->at(i).getX() - lines->at(ip).getX()) * (lines->at(i).getY() + lines->at(ip).getY())) / 2.0; } return(res); } double Utils :: getArea(vector lines) { double res = 0.0; for(unsigned int i = 0; i < lines.size(); i++) { int ip = (i + 1) % lines.size(); res = res + ((lines[i].getX() - lines[ip].getX()) * (lines[i].getY() + lines[ip].getY())) / 2.0; } return(res); } /* 1.1 convexHull() */ vector Utils :: convexHull(LineWA *lt, int ltlength) { //int minpoint; double miny, minx, tmpx, tmpy; vector unfinishedhull; int a, index,i; double hyp; LineWA *point1, *point2, tmp; //minpoint = 0; index = 0; miny = numeric_limits :: max(); minx = numeric_limits :: max(); for (a = 0; a < ltlength; a++) { if ((lt[a].getY() tmpvec; tmpvec.push_back(lt[0]); for (int i = 1; i < ltlength; i++) { if(!AlmostEqual(tmpvec[tmpvec.size() - 1].getAngle(), lt[i].getAngle())) { tmpvec.push_back(lt[i]); } else { tmpx = lt[0].getX() - lt[i].getX(); tmpy = lt[0].getY() - lt[i].getY(); double distli = sqrt(tmpx * tmpx + tmpy * tmpy); tmpx = lt[0].getX() - tmpvec[tmpvec.size() - 1].getX(); tmpy = lt[0].getY() - tmpvec[tmpvec.size() - 1].getY(); double disttmp = sqrt(tmpx * tmpx + tmpy * tmpy); if(distli > disttmp) { tmpvec.pop_back(); tmpvec.push_back(lt[i]); } } } ltlength = tmpvec.size(); for (int i = 0; i < ltlength; i++) { lt[i] = tmpvec[i]; } // Use graham scan to create convex hull // The point with the lowest y-coordinate is on the hull unfinishedhull.push_back(<[0]); // The point with the lowest angle with respect to the x-axis is on the // hull unfinishedhull.push_back(<[1]); i = 2; int N = ltlength; while(i < N) { point1 = unfinishedhull.back(); unfinishedhull.pop_back(); point2 = unfinishedhull.back(); unfinishedhull.push_back(point1); if(!point1->equals(point2)&& ((sameSide(point1, point2, <[i]) <= 0)|| HalfSegment(true, Point(true, point1->getX(), point1->getY()), Point(true, point2->getX(), point2->getY())) .Contains(Point(true, lt[i].getX(), lt[i].getY())))) { unfinishedhull.push_back(<[i]); i++; } else { unfinishedhull.pop_back(); } } return(unfinishedhull); } /* 1.1 compareLineWA() */ int Utils :: compareLineWA(const void *line1, const void *line2) { LineWA* tmp1 = (LineWA*) line1; LineWA* tmp2 = (LineWA*) line2; return(tmp1->compareTo(tmp2)); } /* 1.1 sameSide() */ double Utils :: sameSide(LineWA* line1, LineWA* line2, LineWA* p1) { long double l1xpy = line1->getX() *p1->getY(); long double pxl2y = p1->getX() *line2->getY(); long double pxl1y = p1->getX() *line1->getY(); long double l1xl2y = line1->getX() *line2->getY(); long double l2xpy = line2->getX() *p1->getY(); long double l2xl1y = line2->getX() *line1->getY(); long double summe2 = l2xl1y + l1xpy + pxl2y; long double summe1 = l2xpy + pxl1y + l1xl2y; return( (double) (summe1 - summe2)); } /* 1.1 indexOf() */ int Utils :: indexOf(vector array, LineWA obj) { unsigned int a; for (a=0;a *vec) { for(unsigned int i = 0; i < vec->size() / 2; i++) { LineWA tmp = vec->at(i); (*vec)[i] = (*vec)[vec->size() - 1 - i]; (*vec)[vec->size() - 1 - i] = tmp; } } /* 1.1 getHausdorfDistance() */ double Utils :: getHausdorfDistance(vector obj1, vector obj2) { if(obj2.size() == 0) return(0); double res = 0; for(unsigned int i = 0; i < obj1.size(); i++) { res = max(res, getSingleHausdorffDistance(&obj1[i], obj2)); } return(res); } /* 1.1 getDiameter() */ double Utils :: getDiameter(vector Poly) { vector >tmp; tmp.push_back(Poly); return(getMaxDistance(tmp)); } double Utils::getDiameter(vector Poly) { vector tmp2; for(unsigned int i = 0; i < Poly.size(); i++) { tmp2.push_back( (LineWA*) &Poly[i]); } vector >tmp; tmp.push_back(tmp2); return(getMaxDistance(tmp)); } /* 1.1 getMaxDistance() */ double Utils :: getMaxDistance(vector > Polys) { int count = 0; for(unsigned int i = 0; i < Polys.size(); i++) { count += Polys[i].size(); } LineWA tmp[count]; int counter = 0; for(unsigned int i = 0; i < Polys.size(); i++) { for(unsigned int j = 0 ; j < Polys[i].size(); j++) { tmp[counter++] = Polys[i][j]; } } vector conTmp = Utils :: convexHull(tmp, count); double tmpdist = 0; int pos = conTmp.size() / 2; for(unsigned int i = 0; i < conTmp.size(); i++) { pos = getLongestDistFromPoint(conTmp[i], conTmp, pos); double distxy = Utils :: getSquareDistance(conTmp[i], conTmp[pos]); if(distxy > tmpdist) { tmpdist = distxy; } } return(sqrt(tmpdist)); } /* 1.1 convertCHLine2LineWA() */ vector Utils :: convertCHLine2LineWA(vector vec) { vector res; for(unsigned int i = 0; i < vec.size(); i++) { res.push_back( (LineWA*) &vec[i]); } return(res); } /* 1.1 convertLineWA2CHLine() */ vector *Utils :: convertLineWA2CHLine(vector *vec) { vector *res = new vector; for(unsigned int i = 0; i < vec->size(); i++) { res->push_back(CHLine(&vec->at(i))); } return(res); } /* 1.1 getSquareDistance() */ double Utils :: getSquareDistance(LineWA *p1, LineWA *p2) { long double x1s = p1->getX() * p1->getX(); long double x2s = p2->getX() * p2->getX(); long double y1s = p1->getY() * p1->getY(); long double y2s = p2->getY() * p2->getY(); long double x1x2 = p1->getX() * p2->getX(); long double y1y2 = p1->getY() * p2->getY(); long double tmp = x1x2 + y1y2; long double res = x1s + x2s + y1s + y2s - 2 * tmp; return((double) res); } /* 1.1 computeLineAngles() */ void Utils :: computeLineAngles(vector *lines) { int listlength, nextpoint, a; long double lengthhyp, angle, lengthx, lengthy, sum1, sum2; listlength = lines->size()-1; for (a = 0; a < listlength; a++) { nextpoint = a + 1; sum1 = lines->at(nextpoint).getX() * lines->at(nextpoint).getX()+ lines->at(a).getX() * lines->at(a).getX()+ lines->at(nextpoint).getY() * lines->at(nextpoint).getY()+ lines->at(a).getY() * lines->at(a).getY(); sum2 = (lines->at(nextpoint).getX() * lines->at(a).getX()+ lines->at(nextpoint).getY() * lines->at(a).getY())*2; lengthx = lines->at(nextpoint).getX() - lines->at(a).getX(); lengthy = lines->at(nextpoint).getY() - lines->at(a).getY(); lengthhyp = sqrt(sum1 - sum2); angle = acos(lengthx / lengthhyp); if (lengthy < 0) angle = (M_PI * 2) - angle; lines->at(a).setAngle(angle); } a = listlength; nextpoint = 0; sum1 = lines->at(nextpoint).getX() * lines->at(nextpoint).getX()+ lines->at(a).getX() * lines->at(a).getX()+ lines->at(nextpoint).getY() * lines->at(nextpoint).getY()+ lines->at(a).getY() * lines->at(a).getY(); sum2 = (lines->at(nextpoint).getX() * lines->at(a).getX()+ lines->at(nextpoint).getY() * lines->at(a).getY())*2; lengthx = lines->at(nextpoint).getX() - lines->at(a).getX(); lengthy = lines->at(nextpoint).getY() - lines->at(a).getY(); lengthhyp = sqrt(sum1 - sum2); angle = acos(lengthx / lengthhyp); if (lengthy < 0) angle = (M_PI*2)-angle; lines->at(a).setAngle(angle); } /* 1.1 getOverlap() */ double Utils :: getOverlap(vector *l1, vector *l2) { #ifdef USE_OVERLAP Region *r1 = Utils :: convert2Region(l1); Region *r2 = Utils :: convert2Region(l2); Region* res = new Region(0); MakeOp mo; res = mo.Intersection(r1, r2); return(res->Area()); #else return(0); #endif } /* 1.1 convert2Region() */ Region* Utils :: convert2Region(vector *l1) { Region *res = new Region( (l1->size()) * 2); res->Clear(); res->StartBulkLoad(); for(unsigned int i = 0; i < l1->size(); i++) { AttrType attr = AttrType(); attr.faceno = 0; attr.cycleno = 0; attr.edgeno = i; Point p1 = Point(true, l1->at(i).getX(), l1->at(i).getY()); Point p2 = Point(true, l1->at((i + 1) % l1->size()).getX(), l1->at((i + 1) % l1->size()).getY()); if(p1.GetX() > p2.GetX()) { attr.insideAbove=true; } else { if(p1.GetX() == p1.GetX() && p1.GetY() < p1.GetY()) { attr.insideAbove = true; } else { attr.insideAbove = false; } } if(!AlmostEqual(p1, p2)) { HalfSegment hs1 = HalfSegment(true, p1, p2); hs1.SetAttr(attr); (*res)+=hs1; hs1.SetLeftDomPoint(false); (*res)+=hs1; } } res->EndBulkLoad(true,true,true,true); res->SetDefined(true); return(res); } /* 1.1 toString() */ string Utils :: toString(const int &t) { std :: ostringstream oss; // create a stream // oss << t; // insert value to stream return oss.str(); // return as a string } /* 1.1 getRectangularDistance() */ double Utils::getRectangularDistance(LineWA *lineA,LineWA *lineB,LineWA *point) { long double t1 = lineA->getX()* lineB->getX()+ lineA->getX()* point->getX()+ lineA->getY() * lineB->getY() + lineA->getY() * point->getY(); long double t2 = lineB->getX()* point->getX()+ lineA->getX()* lineA->getX()+ lineB->getY() * point->getY() + lineA->getY() * lineA->getY(); long double denom1 = lineA->getX()*lineA->getX()+lineB->getX()*lineB->getX()+ lineA->getY() * lineA->getY() + lineB->getY() * lineB->getY(); long double denom2 = lineA->getX() * lineB->getX() + lineA->getY() * lineB->getY(); long double denom = denom1 - 2 * denom2; long double t = -1 * (t1 - t2) / denom; if(denom == 0) { return(numeric_limits :: quiet_NaN()); } if(t < 0 || t > 1) { return(numeric_limits :: quiet_NaN()); } long double xfac = lineA->getX() + lineB->getX() * t - (lineA->getX() * t + point->getX()); long double yfac = lineA->getY() + lineB->getY() * t - (lineA->getY() * t + point->getY()); double res = sqrt(xfac * xfac + yfac * yfac); if(Utils :: sameSide(lineA, lineB, point) > 0) { res = res * -1; } return res; } /* 1.1 getIntersections() */ vector *Utils :: getIntersections(LineWA *lineA, LineWA *lineB, vector *poly) { vector *intersections = new vector; for(unsigned int i = 0; i < poly->size(); i++) { LineWA *inter = Utils :: getIntersection(lineA, lineB, (LineWA*) &poly->at(i), (LineWA*)&poly->at((i + 1) % poly->size())); if(inter != NULL) intersections->push_back(inter); } return(intersections); } /* 1.1 getIntersection() */ LineWA *Utils :: getIntersection(LineWA *line1A, LineWA *line1B, LineWA *line2A, LineWA *line2B) { double minx1, maxx1, miny1, maxy1; if(line1A->getX() > line1B->getX()) { minx1 = line1B->getX(); maxx1 = line1A->getX(); } else { minx1 = line1A->getX(); maxx1 = line1B->getX(); } if(line1A->getY() > line1B->getY()) { miny1 = line1B->getY(); maxy1 = line1A->getY(); } else { miny1 = line1A->getY(); maxy1 = line1B->getY(); } if(line2A->getX() < minx1 && line2B->getX() < minx1) return(NULL); if(line2A->getX() > maxx1 && line2B->getX() > maxx1) return(NULL); if(line2A->getY() < miny1 && line2B->getY()getY() > maxy1 && line2B->getY() > maxy1) return(NULL); LineWA *res; double xlk = line1B->getX() - line1A->getX(); double ylk = line1B->getY() - line1A->getY(); double xnm = line2B->getX() - line2A->getX(); double ynm = line2B->getY() - line2A->getY(); double xmk = line2A->getX() - line1A->getX(); double ymk = line2A->getY() - line1A->getY(); double det = xnm * ylk - ynm * xlk; if(det == 0) { return(NULL); } else { double detinv = 1.0 / det; double s = (xnm * ymk - ynm * xmk) * detinv; double t = (xlk * ymk - ylk * xmk) * detinv; if(s < 0 || s > 1 || t < 0 || t > 1) { return(NULL); } else { double x = line1A->getX() + xlk * s; double y = line1A->getY() + ylk * s; res=new LineWA(x, y); } } return(res); } /* 1.1 joinLinelists() */ vector *Utils :: joinLinelists(vector *first, vector *second) { try { Region cycle1 = *Utils :: convert2Region( Utils :: convertLineWA2CHLine(first)); Region cycle2 = *Utils :: convert2Region( Utils :: convertLineWA2CHLine(second)); double area = Utils :: getArea(first); if(area < 0) { vector *tmplistrev = new vector(first->size()); for (unsigned int i = 0; i < first->size(); i++) { tmplistrev->at(first->size() - i - 1) = first->at(i); } first = tmplistrev; } area = Utils :: getArea(second); if(area > 0) { vector *tmplistrev = new vector(second->size()); for (unsigned int i = 0; i < second->size(); i++) { tmplistrev->at(second->size() - i - 1) = second->at(i); } second = tmplistrev; } vector *resV = new vector; unsigned int startIndex = 0; while(cycle2.OnBorder(Point(true, first->at(startIndex).getX(), first->at(startIndex).getY()))) startIndex++; unsigned int i = startIndex; while(!Utils :: PointsOnLine(second, &first->at(i), &first->at(i + 1))) { resV->push_back(first->at(i)); i++; } resV->push_back(first->at(i)); i++; LineWA *inter = Utils :: getClosestBoundaryPoint(&first->at(i-1), &first->at(i), second); int j = 0; while(!second->at(j).equals(inter)) j++; resV->push_back(second->at(j)); j=(j + 1) % second->size(); while(!cycle1.OnBorder( Point(true, second->at(j).getX(), second->at(j).getY()))) { resV->push_back(second->at(j)); j=(j + 1) % second->size(); } resV->push_back(second->at(j)); while(cycle2.OnBorder( Point(true, first->at(i).getX(), first->at(i).getY()))) { i++; } for(; isize(); i++) { resV->push_back(first->at(i)); } for(i = 0; i < startIndex; i++) { resV->push_back(first->at(i)); } return(resV); } catch(...) { return(first); } } /* 1.1 getClosestBoundaryPoint() */ LineWA *Utils :: getClosestBoundaryPoint(LineWA *lineA, LineWA *lineB, vector *poly) { vector intersections; for(unsigned int i = 0; i < poly->size(); i++) { if(HalfSegment(true, Point(true, lineA->getX(), lineA->getY()), Point(true, lineB->getX(), lineB->getY())). Contains(Point(true, poly->at(i).getX(), poly->at(i).getY()))) { intersections.push_back(poly->at(i)); } } if(intersections.size() == 0) return(NULL); if(intersections.size() == 1) return(new LineWA(intersections[0])); double minSquareDist = numeric_limits :: max(); unsigned int minIndex = 0; for(unsigned int i = 0; i < intersections.size(); i++) { double squareDist = (intersections[i].getX() - lineA->getX()) * (intersections[i].getX() - lineA->getX()) + (intersections[i].getY() - lineA->getY()) * (intersections[i].getY() - lineA->getY()); if(squareDist < minSquareDist) { minSquareDist = squareDist; minIndex = i; } } return(new LineWA(intersections[minIndex])); } /* 1.1 PointsOnLine() */ bool Utils :: PointsOnLine(vector *points, LineWA *lineA, LineWA *lineB) { bool res = false; for(unsigned int i = 0; i < points->size(); i++) { if(HalfSegment(true, Point(true, lineA->getX(), lineA->getY()), Point(true, lineB->getX(), lineB->getY())) .Contains(Point(true, points->at(i).getX(), points->at(i).getY()))) { res = true; break; } } return(res); } /* 1 Operators 1.1 $<<$ */ ostream& operator << (ostream& s, vector vector) { for(unsigned int i = 0; i < vector.size(); i++) { s << setw(3) << i << ": " << vector[i]; } s << endl; return s; } /* 1 Private Methods() 1.1 getSingleHausdorffDistance() */ double Utils :: getSingleHausdorffDistance(LineWA *obj1, vector obj2) { double res = (obj1->getX() - obj2[0].getX()) * (obj1->getX() - obj2[0].getX()) + (obj1->getY()-obj2[0].getY()) * (obj1->getY() - obj2[0].getY()); for(unsigned int i = 1; i < obj2.size(); i++) { res = std :: min(res, (obj1->getX() - obj2[i].getX()) * (obj1->getX() - obj2[i].getX()) + (obj1->getY() - obj2[i].getY()) * (obj1->getY() - obj2[i].getY())); } return(sqrt(res)); } /* 1.1 PointsOnLine() */ int Utils :: getLongestDistFromPoint(LineWA *from, vector list,int pos) { double d = Utils :: getSquareDistance(from, list[pos]); double dp = Utils :: getSquareDistance(from, list[(pos + 1) % list.size()]); double dm = Utils :: getSquareDistance(from, list[(pos - 1 + list.size()) % list.size()]); if(d >= dp && d >= dm) { return(pos); } else { if(dp > d) { return(getLongestDistFromPoint(from, list, (pos+1) % list.size())); } else { return(getLongestDistFromPoint(from, list, (pos - 1 + list.size()) % list.size())); } } } }