TeGeometryAlgorithms.cpp

Go to the documentation of this file.
00001 /************************************************************************************
00002 TerraLib - a library for developing GIS applications.
00003 Copyright  2001-2004 INPE and Tecgraf/PUC-Rio.
00004 
00005 This code is part of the TerraLib library.
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 You should have received a copy of the GNU Lesser General Public
00012 License along with this library.
00013 
00014 The authors reassure the license terms regarding the warranties.
00015 They specifically disclaim any warranties, including, but not limited to,
00016 the implied warranties of merchantability and fitness for a particular purpose.
00017 The library provided hereunder is on an "as is" basis, and the authors have no
00018 obligation to provide maintenance, support, updates, enhancements, or modifications.
00019 In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
00020 indirect, special, incidental, or consequential damages arising out of the use
00021 of this library and its documentation.
00022 *************************************************************************************/
00023 
00024 #include "TeAssertions.h"
00025 #include "TeGeometryAlgorithms.h"
00026 #include "TeDefines.h"
00027 
00028 #include "TeIntersector.h"
00029 #include "TeFragmentation.h"
00030 
00031 #include <algorithm>
00032 #include <iterator>
00033 #include <set>
00034 
00035 
00036 using namespace std;
00037 
00038 //---------- Local Functions ans Structures ----------//
00039 
00040 //! Instead of using arctan, use this to compare angles, so given two points return a number to be used in place of the angle formed by the segment.
00041 double Theta(const TeCoord2D& c1, const TeCoord2D& c2)
00042 {
00043         register double dx = c2.x() - c1.x();
00044         register double ax = fabs(dx);
00045         register double dy = c2.y() - c1.y();
00046         register double ay = fabs(dy);
00047         register double t = 0.0;
00048 
00049         if((dx == 0.0) && (dy == 0.0))
00050                 t = 0.0;
00051         else
00052                 t = dy / (ax + ay);
00053 
00054         if(dx < 0.0)
00055                 t = 2 - t;
00056         else
00057                 if(dy < 0.0)
00058                         t = 4.0 + t;
00059 
00060         return t * 90.0;
00061 }
00062 
00063 //! This struct is used for compare angles between two points and an anchor.
00064 struct ThetaOrder
00065 {
00066         //! A fixed coordinate to be used to compare.
00067         TeCoord2D anchor;
00068 
00069         ThetaOrder(const TeCoord2D& c)
00070                 : anchor(c)
00071         {
00072         }
00073 
00074         // Return true if c1 and anchor has a smaller angle than c2 and anchor.
00075         bool operator()(const TeCoord2D& c1, const TeCoord2D& c2) const
00076         {
00077                 register double t1 = Theta(anchor, c1);
00078                 register double t2 = Theta(anchor, c2);
00079 
00080                 if(t1 < t2)
00081                         return true;
00082                 
00083                 if(t1 > t2)
00084                         return false;
00085 
00086                 if(c1.x() < c2.x())
00087                         return true;
00088 
00089                 if(c1.x() > c2.x())
00090                         return false;
00091 
00092                 return false;           
00093         }
00094 };
00095 
00096 /*! \struct xOrder
00097     \brief  Returns true if c1 < c2 otherwise, returns false.
00098  */
00099 template<class T> struct xOrder
00100 {
00101         bool operator()(T c1, T c2)
00102         {
00103                 if(c1.x() < c2.x())
00104                         return true;
00105 
00106                 if(c1.x() > c2.x())
00107                         return false;
00108 
00109                 if(c1.y() < c2.y())
00110                         return true;            
00111 
00112                 return false;
00113         }
00114 };
00115 
00116 /*! \fn double TeArea(TeLinearRing& r);
00117     \brief This function returns twice the area of a ring treated as a simple polygon (no holes).
00118         \param r  The ring.
00119 
00120         This function returns twice the area of a ring treated as a simple polygon (no holes).
00121         May return a negative number => it will be used in Orientation tests.
00122 */
00123 double Te2Area(const TeLinearRing& r)
00124 {
00125         double S2 = 0.0;
00126 
00127         TeLinearRing::iterator it = r.begin();
00128         TeLinearRing::iterator end = r.end() - 1;
00129         while(it != end)
00130         {
00131                 S2 += (it->x() + (it + 1)->x()) * ((it + 1)->y() - it->y());
00132                 ++it;
00133         }
00134 
00135         return S2;
00136 }
00137 
00138 /*! \fn short TeConverseRelation(const short& rel)
00139     \brief This function returns the complements relation of one given relation.
00140         \param rel  The relation.
00141 */
00142 inline short ConverseRelation(const short& rel)
00143 {
00144         switch(rel)
00145         {
00146                 case TeCOVEREDBY  :  return TeCOVERS;
00147                 case TeWITHIN     :  return TeCONTAINS;
00148                 case TeCOVERS     :  return TeCOVEREDBY;
00149                 case TeCONTAINS   :  return TeWITHIN;
00150                 default                   :  return rel;
00151         }       
00152 }
00153 
00154 /*! \fn bool MayTouches(const TeLine2D& lRed, const TeLine2D& lBlue, TeINTERSECTOR2::TeReportTree& report)
00155     \brief This function verifies if the two lines may touches.
00156         \param lRed   The first line.
00157         \param lBlue  The second line.
00158         \param report The intersection point list.
00159 */
00160 bool MayTouches(const TeLine2D& lRed, const TeLine2D& lBlue, TeINTERSECTOR2::TeVectorBoundaryIP& report)
00161 {
00162         if(lRed.isRing() && lBlue.isRing())
00163                 return false;
00164 
00165         TeINTERSECTOR2::TeVectorBoundaryIP::iterator it = report.begin();
00166         TeINTERSECTOR2::TeVectorBoundaryIP::iterator it_end = report.end();
00167 
00168 
00169         // Get the boundaries' coordinate.
00170         TeCoord2D line1_boundary1 = lRed[0];
00171         TeCoord2D line1_boundary2 = lRed[lRed.size() - 1u];
00172 
00173         TeCoord2D line2_boundary1 = lBlue[0];
00174         TeCoord2D line2_boundary2 = lBlue[lBlue.size() - 1u];
00175 
00176         // Verifies if intersection points are on boundary of one of the blue line
00177         while(it != it_end)
00178         {       // Get intersection point coordinate.
00179 
00180                 for(unsigned int i = 0; i < it->coords_.size(); ++i)
00181                 {
00182                         TeCoord2D ip_coord = it->coords_[i];
00183 
00184                         if(lRed.isRing())
00185                         {
00186                                 if(!(TeEquals(ip_coord, line2_boundary1) || TeEquals(ip_coord, line2_boundary2)))
00187                                         return false;
00188                         }
00189                         else if(lBlue.isRing())
00190                         {
00191                                 if(!(TeEquals(ip_coord, line1_boundary1) || TeEquals(ip_coord, line1_boundary2)))
00192                                         return false;
00193                         }
00194                         else
00195                         {
00196                                 if(!(TeEquals(ip_coord, line1_boundary1) || TeEquals(ip_coord, line1_boundary2) || TeEquals(ip_coord, line2_boundary1) || TeEquals(ip_coord, line2_boundary2)))
00197                                         return false;
00198                         }
00199                 }
00200 
00201                 ++it;
00202         }
00203 
00204         return true;            // The lines touches.
00205 }
00206 
00207 /*! \fn short Relation(const TeLine2D& lRed, const TeLine2D& lBlue, TeINTERSECTOR2::TeReportTree& report, const short& relation)
00208     \brief This function returns the relation between two lines.
00209         \param lRed     The first line.
00210         \param lBlue    The second line.
00211         \param report   The intersection point list.
00212         \param relation The relation that stop the search.
00213 
00214         This function returns the relation between lines. May be: TeDISJOINT, TeTOUCHES, TeWITHIN, TeCROSSES, TeCOVEREDBY, TeEQUALS.
00215         Obs: Doesn't do box elimination. You must implement the test in your own functions.
00216 */
00217 short Relation(const TeLine2D& lRed, const TeLine2D& lBlue, TeINTERSECTOR2::TeVectorBoundaryIP& report, const short& relation)
00218 {
00219         if(report.size() == 0u)
00220                 return TeDISJOINT;
00221 
00222         // Do fragmentation
00223         //bool hasContour = false;      // This will decide between CROSSES and OVERLAPS.
00224 
00225         bool mayTouches = MayTouches(lRed, lBlue, report);
00226 
00227         // Stop to check, because touches can't occur anymore
00228         if(relation == TeTOUCHES && !mayTouches)
00229                 return TeUNDEFINEDREL;
00230 
00231 
00232         TeLineSet redFragments;
00233         TeLineSet redBoundaryFragments;
00234         TeLine2D lRedAux;
00235         lRedAux.copyElements(lRed);
00236         TeLineSet lSet; lSet.add(lRedAux);
00237 
00238         TeFragmentBoundary(lSet, report, redBoundaryFragments, redFragments);
00239 
00240         unsigned int redFragmentsSize = redFragments.size();
00241 
00242         short mask = TeUNKNOWNPOSITION;
00243 
00244         if(redBoundaryFragments.size() > 0u)
00245                 mask |= TeINSIDE;
00246 
00247         // Do a position test for each fragment and stop if all relations have been found.
00248         for(unsigned int j = 0u; j < redFragmentsSize; ++j)
00249         {       
00250                 TeCoord2D middle;                       
00251 
00252                 if(redFragments[j].size() ==  2u)       // If the fragment has two points I need to check the middle point of this fragment.
00253                         TeGetMiddlePoint(redFragments[j][0u], redFragments[j][1u], middle);
00254                 else    // If the fragment has more than two points so I check one point between the end points.
00255                         middle = redFragments[j][(unsigned int)((double(redFragments[j].size()) / 2.0 + 0.5)) - 1];
00256 
00257                 if(TeIsOnLine(middle, lBlue))
00258                         mask |= TeINSIDE;
00259                 else
00260                         mask |= TeOUTSIDE;              
00261 
00262                 if((mask & TeOUTSIDE) && (mask & TeINSIDE))
00263                         break;          
00264         }
00265 
00266         // If the intersection is only at end points and there is no part of red line inside blue line so they touches
00267         if(mayTouches && mask == TeOUTSIDE)
00268         {
00269                 return TeTOUCHES;
00270         }
00271         
00272         // Stop to check, because touches can't occur anymore
00273         if(relation == TeTOUCHES)
00274                 return TeUNDEFINEDREL;
00275 
00276 
00277         // if there is no fragments in line blue interiors, so line red cross line blue
00278         if(mask == TeOUTSIDE)
00279                 return TeCROSSES;
00280 
00281         // Stop to check, because crosses can't occur anymore
00282         if(relation == TeCROSSES)
00283                 return TeUNDEFINEDREL;
00284 
00285         TeCoord2D firstRedCoord = lRed[0];
00286         TeCoord2D lastRedCoord  = lRed[lRed.size() - 1];
00287 
00288         TeCoord2D firstBlueCoord = lBlue[0];
00289         TeCoord2D lastBlueCoord  = lBlue[lBlue.size() - 1];             
00290 
00291 
00292         // If there is no part of red line outside blue line => must decide within, covered by and equals
00293         if(!(mask & TeOUTSIDE))
00294         {
00295                 // So, if we arrived here, blue line contains red line, but needs to decide between equal, coveredby and within.
00296 
00297                 if(TeEquals(firstRedCoord, firstBlueCoord) || TeEquals(firstRedCoord, lastBlueCoord))
00298                 {
00299                         if(TeEquals(lastRedCoord, firstBlueCoord) || TeEquals(lastRedCoord, lastBlueCoord))
00300                         {
00301                                 return TeEQUALS;
00302                         }
00303                         else
00304                         {
00305                                 if(lBlue.isRing())
00306                                         return TeWITHIN;
00307                                 else
00308                                         return TeCOVEREDBY;
00309                         }
00310                 }
00311 
00312                 if(TeEquals(lastRedCoord, firstBlueCoord) || TeEquals(lastRedCoord, lastBlueCoord))
00313                 {
00314                         if(lBlue.isRing())
00315                                 return TeWITHIN;
00316                         else
00317                                 return TeCOVEREDBY;
00318                 }
00319 
00320                 return TeWITHIN;
00321         }
00322 
00323         return TeUNDEFINEDREL;
00324 }
00325 
00326 /*! \fn short Relation(const TeLine2D& line, const TeLinearRing& ring, const short& relation)
00327     \brief This function returns the relation between a line and a linear ring (treated as a simple polygon with no holes).
00328         \param line     The line.
00329         \param ring     The simple polygon ring.
00330         
00331         This function returns how the points of input line are related with interior, boundary, and
00332         exterior of polygon. The mask may be a combination of the following values: TeOUTSIDE, TeINSIDE and TeBOUNDARY.
00333         Obs: Do box elimination.
00334 */
00335 short Relation(const TeLine2D& line, const TeLinearRing& ring)
00336 {
00337         if(TeDisjoint(line.box(), ring.box()))
00338                 return TeOUTSIDE;
00339 
00340         TeINTERSECTOR2::TeVectorBoundaryIP report;
00341 
00342         if(TeINTERSECTOR2::TeSafeIntersections(line, ring, report))
00343         {
00344                 short mask = TeBOUNDARY;        // It will be at least intersections between boundaries.
00345 
00346                 // Fragments line.
00347                 TeLineSet lSet;
00348                 TeLineSet boundaryFragments;
00349                 TeLine2D lineAux;
00350                 lineAux.copyElements(line);
00351                 TeLineSet auxLineSet; auxLineSet.add(lineAux);
00352                 
00353                 TeFragmentBoundary(auxLineSet, report, boundaryFragments, lSet);
00354 
00355 
00356                 unsigned int lSetSize = lSet.size();
00357 
00358                 // Do a position test for each fragment and stop if al relations has been found.
00359                 for(unsigned int j = 0; j < lSetSize; ++j)
00360                 {       
00361                         TeCoord2D middle;
00362                         
00363                         if(lSet[j].size() ==  2)        // If the fragment has two points I need to check the middle point of this fragment.
00364                                 TeGetMiddlePoint(lSet[j][0], lSet[j][1], middle);
00365                         else    // If the fragment has more than two points so I check one point between the end points.
00366                                 middle = lSet[j][(unsigned int)((double(lSet[j].size()) / 2.0 + 0.5)) - 1];
00367 
00368                         
00369                         mask |= TeRelation(middle, ring);
00370 
00371                         if((mask & TeOUTSIDE) && (mask & TeINSIDE))
00372                                 break;                  
00373                 }
00374 
00375                 return mask;
00376         }
00377         else
00378                 return TeRelation(line[0], ring);       // Needs to test only one point of the line, and its location defines the line location.
00379 }
00380 
00381 /*! \fn short TopologicRelation(const TeLine2D& line, const TeLinearRing& r)
00382     \brief This function returns the relation between a line and a linear ring (treated as a simple polygon with no holes).
00383         \param line     The line.
00384         \param r        The simple polygon ring.
00385 
00386         This function returns the topologic relation between the line and
00387         the ring. The result may be: DISJOINT, WITHIN, TOUCHES, CROSSES or COVERED BY.
00388         Obs: Doesn't do box elimination. Just uses from TeRelation.
00389 */
00390 short TopologicRelation(const TeLine2D& line, const TeLinearRing& r)
00391 {
00392         short mask = Relation(line, r);
00393 
00394         if(mask & TeBOUNDARY)   // TOUCHES or CROSSES or COVERED BY
00395         {
00396                 if(mask & TeOUTSIDE)    // TOUCHES or CROSSES
00397                 {
00398                         if(mask & TeINSIDE)
00399                                 return TeCROSSES;
00400                         else
00401                                 return TeTOUCHES;
00402                 }
00403                 else    // COVERED BY
00404                         return TeCOVEREDBY;
00405 
00406         }
00407         else    // DISJOINT or WITHIN
00408         {
00409                 if(mask & TeINSIDE)     
00410                         return TeWITHIN;
00411                 else                            
00412                         return TeDISJOINT;
00413         }
00414 }
00415 
00416 /*! \fn short TopologicRelation(const TeLinearRing& rRed, const TeLinearRing& rBlue)
00417     \brief This function returns the relationship between two rings (treated as simple polygons with no holes).
00418         \param rRed  The ring to test relationship.
00419         \param rBlue The ring to test relationship.
00420 
00421         This function returns the relationship between two rings.
00422 */
00423 short TopologicRelation(const TeLinearRing& rRed, const TeLinearRing& rBlue)
00424 {
00425         // See the intersection between the points of rRed and the three components of rBlue (Boundary, Exterior, Interior)
00426         short rel = Relation(rRed, rBlue);
00427 
00428         if((rel & TeOUTSIDE) && (rel & TeINSIDE) && (rel & TeBOUNDARY))
00429                 return TeOVERLAPS;
00430 
00431         if((rel & TeOUTSIDE) && !(rel & TeINSIDE) && (rel & TeBOUNDARY))
00432         {
00433                 if(TeWithinOrCoveredByOrEquals(rBlue.box(), rRed.box()))
00434                 {
00435                         short rel_aux = Relation(rBlue, rRed);
00436 
00437                         if(rel_aux == TeBOUNDARY) //mario
00438                                 return TeCOVERS;
00439 
00440                         if((rel_aux & TeINSIDE) && !(rel_aux & TeOUTSIDE) && (rel_aux & TeBOUNDARY))
00441                                 return TeCOVERS;
00442                 }
00443                 
00444                 return TeTOUCHES;
00445         }
00446 
00447         if((rel & TeOUTSIDE) && !(rel & TeINSIDE) && !(rel & TeBOUNDARY))
00448         {
00449                 if(TeWithinOrCoveredByOrEquals(rBlue.box(), rRed.box()))
00450                 {
00451                         if(TeRelation(rBlue[0], rRed) == TeINSIDE)
00452                                 return TeCONTAINS;
00453                 }
00454                 
00455                 return TeDISJOINT;
00456         }
00457 
00458         if(!(rel & TeOUTSIDE) && (rel & TeINSIDE) && !(rel & TeBOUNDARY))
00459                 return TeWITHIN;
00460 
00461         if(!(rel & TeOUTSIDE) && (rel & TeINSIDE) && (rel & TeBOUNDARY))
00462                 return TeCOVEREDBY;
00463 
00464         if(rel == TeBOUNDARY)
00465                 return TeEQUALS;
00466 
00467         return TeINTERSECTS;
00468 }
00469 
00470 /*! \fn short TeTopologicRelation(const TeLinearRing& rRed, const TeLinearRing& rBlue, vector<TeLinearRing>& rings, short& rel)
00471     \brief This function returns the relationship between the ring and the polygon inner rings.
00472         \param rRed  The ring to test relationship.
00473         \param pBlue The polygon to test relationship.
00474         \param rings Inner rings from blue polygon that is inside or is covered by red external polygon.
00475         \param rel   The relation between external red ring and external blue ring.
00476 
00477         This function returns the relationship between the ring and the polygon inner rings.
00478 */
00479 short LookAtInnerRings(const TeLinearRing& rRed, const TePolygon& pBlue, vector<TeLinearRing>& rings, short& rel)
00480 {
00481         register unsigned int i = 1;
00482         register unsigned int nRings = pBlue.size();
00483 
00484         for(; i < nRings; ++i)
00485         {
00486                 switch(TopologicRelation(rRed, pBlue[i]))
00487                 {
00488                         case TeCOVEREDBY : return TeTOUCHES;
00489 
00490                         case TeWITHIN    : return TeDISJOINT;
00491 
00492                         case TeOVERLAPS  : return TeOVERLAPS;
00493 
00494                         case TeEQUALS    : return TeTOUCHES;
00495 
00496                         case TeDISJOINT  : continue;    // this ring is outside the external ring, so it doesn't contribute to the relationship.
00497 
00498                         case TeTOUCHES    : rel = TeCOVEREDBY;  // change rel if rel is within.
00499                                                 continue;
00500 
00501                         case TeCOVERS    : rings.push_back(pBlue[i]);
00502                                                            rel = TeCOVEREDBY;   // we know they share boundary!!!!
00503                                                            break;
00504 
00505                         case TeCONTAINS  : rings.push_back(pBlue[i]);
00506                                                            break;                               // doesn't share boundary
00507                 }
00508         }
00509 
00510         return TeUNDEFINEDREL;
00511 }
00512 
00513 /*! \fn short TestInnerRings(const TePolygon& pRed, vector<TeLinearRing>& rings)
00514     \brief This function returns the relationship between the ring and the polygon inner rings.
00515         \param pRed  The inner rings from pRed to test relationship.
00516         \param rings Inner rings from blue polygon that is inside or is covered by red external polygon.
00517 
00518         This function returns the relationship between the inner ring of pRed and the inner rings in rings.
00519 */
00520 short TestInnerRings(const TePolygon& pRed, vector<TeLinearRing>& rings)
00521 {
00522         unsigned int nRedRings = pRed.size();
00523         unsigned int nBlueRings = rings.size();
00524 
00525         //if((nRedRings - 1) != nBlueRings)
00526         //      return TeOVERLAPS;
00527 
00528         unsigned int i = 1;
00529         unsigned int j = 0;
00530 
00531         bool find = false;
00532 
00533         set<unsigned int> blueRingsProcessed;
00534 
00535         set<unsigned int> redRingsContainsCovers;
00536 
00537         short rel = 0;
00538 
00539         for(; i < nRedRings; ++i)
00540         {
00541                 find = false;
00542 
00543                 for(j = 0; j < nBlueRings; ++j)
00544                 {
00545                         if(blueRingsProcessed.find(j) != blueRingsProcessed.end())
00546                                 continue;
00547 
00548                         switch(TopologicRelation(pRed[i], rings[j]))
00549                         {
00550                                 case TeDISJOINT  : continue;    // so it doesn't contribute to the relationship yet.
00551 
00552                                 case TeEQUALS    :
00553                                                                         rel |= TeEQUALS;
00554                                                         blueRingsProcessed.insert(j);
00555                                                                         find = true;
00556                                                                         break;
00557 
00558                                 case TeCONTAINS  :
00559                                                                         if(redRingsContainsCovers.find(i) != redRingsContainsCovers.end())
00560                                                                                 return TeOVERLAPS;
00561                                                                         
00562                                                                         rel |= TeCONTAINS;
00563 
00564                                                                         redRingsContainsCovers.insert(i);
00565                                                                         blueRingsProcessed.insert(j);
00566                                                                         find = true;
00567                                                                         break;
00568 
00569                                 case TeCOVERS   :
00570                                                                         if(redRingsContainsCovers.find(i) != redRingsContainsCovers.end())
00571                                                                                 return TeOVERLAPS;
00572                                                                         
00573                                                                         rel |= TeCOVERS;
00574 
00575                                                                         redRingsContainsCovers.insert(i);
00576                                                                         blueRingsProcessed.insert(j);
00577                                                                         find = true;
00578                                                                         break;
00579                                                                         
00580 
00581                                 default          :  return TeOVERLAPS;
00582                         }
00583 
00584                         if(find)
00585                                 break;
00586                 }
00587 
00588                 if(!find)
00589                         return TeOVERLAPS;
00590         }
00591 
00592         return rel;
00593 }
00594 
00595 //---------- Topological Function ----------//
00596 
00597 // EQUALS
00598 template<> bool TeEquals(const TeCoord2D& c1, const TeCoord2D& c2)
00599 {
00600         if(TeGeometryAlgorithmsPrecision::IsDifferent(c1.x(), c2.x()))
00601                 return false;
00602 
00603         if(TeGeometryAlgorithmsPrecision::IsDifferent(c1.y(), c2.y()))
00604                 return false;
00605 
00606         return true;
00607 }
00608 
00609 template<> bool TeEquals(const TePoint& p1, const TePoint& p2)
00610 {
00611         return TeEquals(p1.location(), p2.location());
00612 }
00613 
00614 template<> bool TeEquals(const TeLine2D& redLine, const TeLine2D& blueLine)
00615 {
00616         if(TeEquals(redLine.box(), blueLine.box()))
00617                 return TeRelation(redLine, blueLine, TeEQUALS) == TeEQUALS;
00618         else
00619                 return false;
00620 }
00621 
00622 template<> bool TeEquals(const TePolygon& redPol, const TePolygon& bluePol)
00623 {
00624         if(TeEquals(redPol.box(), bluePol.box()))
00625         {
00626                 if(redPol.size() != bluePol.size())
00627                         return false;
00628 
00629                 return TeRelation(redPol, bluePol) == TeEQUALS;
00630         }
00631         else
00632                 return false;
00633 }
00634 
00635 template<> bool TeEquals( const TePolygonSet& ps1, const TePolygonSet& ps2 )
00636 {
00637   if( ps1.size() == ps2.size() ) {
00638     TePolygonSet::iterator it1 = ps1.begin();
00639     TePolygonSet::iterator it1_end = ps1.end();
00640     TePolygonSet::iterator it2 = ps2.begin();
00641     
00642     while( it1 != it1_end ) {
00643       if( ! TeEquals( (*it1), (*it2) ) ) {
00644         return false;
00645       }
00646       
00647       ++it1;
00648       ++it2;
00649     }
00650   
00651     return true;
00652   } else {
00653     return false;
00654   }
00655 }
00656 
00657 template<> bool TeEquals(const TeBox& bx1, const TeBox& bx2)
00658 {
00659         if(TeGeometryAlgorithmsPrecision::IsDifferent(bx1.x1(), bx2.x1()))
00660                 return false;
00661 
00662         if(TeGeometryAlgorithmsPrecision::IsDifferent(bx1.y1(), bx2.y1()))
00663                 return false;
00664 
00665         if(TeGeometryAlgorithmsPrecision::IsDifferent(bx1.x2(), bx2.x2()))
00666                 return false;
00667         
00668         if(TeGeometryAlgorithmsPrecision::IsDifferent(bx1.y2(), bx2.y2()))
00669                 return false;
00670 
00671         return true;
00672 }
00673 
00674 template<> bool TeEquals(const TeCell& cell1, const TeCell& cell2)
00675 {
00676         return TeEquals(cell1.box(), cell2.box());
00677 }
00678 
00679 
00680 // DISJOINT
00681 bool TeDisjoint(const TeCoord2D& c1, const TeCoord2D& c2)
00682 {
00683         if(TeGeometryAlgorithmsPrecision::IsDifferent(c1.x(), c2.x()))
00684                 return true;
00685 
00686         if(TeGeometryAlgorithmsPrecision::IsDifferent(c1.y(), c2.y()))
00687                 return true;
00688 
00689         return false;
00690 }
00691 
00692 bool TeDisjoint(const TeCoord2D& c, const TeBox& b)
00693 {
00694         // c to the right of b
00695         if(TeGeometryAlgorithmsPrecision::IsGreater(c.x(), b.x2())) 
00696                 return true;
00697 
00698         // c to the left of b
00699         if(TeGeometryAlgorithmsPrecision::IsGreater(b.x1(), c.x())) 
00700                 return true;
00701 
00702         // c is above b
00703         if(TeGeometryAlgorithmsPrecision::IsGreater(c.y(), b.y2())) 
00704                 return true;
00705 
00706         // c is below b 
00707         if(TeGeometryAlgorithmsPrecision::IsGreater(b.y1(), c.y())) 
00708                 return true;
00709 
00710         return false;
00711 }
00712 
00713 bool TeDisjoint(const TeBox& bx1, const TeBox& bx2)
00714 {
00715         // B1 to the right of B2
00716         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.x1(), bx2.x2())) 
00717                 return true;
00718 
00719         // B1 to the left of B2
00720         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.x1(), bx1.x2())) 
00721                 return true;
00722 
00723         // B2 is above B1
00724         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.y1(), bx1.y2())) 
00725                 return true;
00726 
00727         // B2 is below B1 
00728         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.y1(), bx2.y2())) 
00729                 return true;
00730 
00731         return false;
00732 }
00733 
00734 bool TeDisjoint(const TeCoord2D& c, const TeLine2D& l)
00735 {
00736         return TeRelation(c, l) == TeOUTSIDE;
00737 }
00738 
00739 bool TeDisjoint(const TeCoord2D& c, const TePolygon& pol)
00740 {
00741         return TeRelation(c, pol) == TeOUTSIDE;
00742 }
00743 
00744 bool TeDisjoint(const TePoint& p1, const TePoint& p2)
00745 {
00746         return TeDisjoint(p1.location(), p2.location());
00747 }
00748 
00749 bool TeDisjoint(const TePoint& p, const TeLine2D& l)
00750 {
00751         return TeDisjoint(p.location(), l);
00752 }
00753 
00754 bool TeDisjoint(const TePoint& p, const TePolygon& pol)
00755 {
00756         return TeDisjoint(p.location(), pol);
00757 }
00758 
00759 bool TeDisjoint(const TeLine2D& redLine, const TeLine2D& blueLine)
00760 {
00761         if(TeDisjoint(redLine.box(), blueLine.box()))
00762                 return true;
00763 
00764         return !TeINTERSECTOR2::TeIntersects(redLine, blueLine);
00765 }
00766 
00767 bool TeDisjoint(const TeLine2D& l, const TePolygon& pol)
00768 {
00769         if(TeDisjoint(l.box(), pol.box()))
00770                 return true;
00771 
00772         return TeRelation(l, pol) == TeDISJOINT;
00773 }
00774 
00775 bool TeDisjoint(const TePolygon& redPol, const TePolygon& bluePol)
00776 {
00777         if(TeDisjoint(redPol.box(), bluePol.box()))
00778                 return true;
00779         else
00780                 return TeRelation(redPol, bluePol) == TeDISJOINT;
00781 }
00782 
00783 bool TeDisjoint(const TeCell& cell1, const TeCell& cell2)
00784 {
00785         return TeDisjoint(cell1.box(), cell2.box());
00786 }
00787 
00788 bool TeDisjoint(const TeCell& cell, const TeLine2D& line)
00789 {
00790         return TeDisjoint(line, TeMakePolygon(cell.box()));
00791 }
00792 
00793 bool TeDisjoint(const TeCell& cell, const TePolygon& pol)
00794 {
00795         return TeDisjoint(pol, TeMakePolygon(cell.box()));
00796 }
00797 
00798 bool TeDisjoint(const TeCell& cell, const TePoint& point)
00799 {
00800         return TeDisjoint(point.location(), cell.box());
00801 }
00802 
00803 
00804 // INTERSECTS
00805 
00806 template<> bool TeIntersects(const TeCoord2D& c, const TeBox& b)
00807 {
00808         // c to the right of b
00809         if(TeGeometryAlgorithmsPrecision::IsGreater(c.x(), b.x2())) 
00810                 return false;
00811 
00812         // c to the left of b
00813         if(TeGeometryAlgorithmsPrecision::IsGreater(b.x1(), c.x())) 
00814                 return false;
00815 
00816         // c is above b
00817         if(TeGeometryAlgorithmsPrecision::IsGreater(c.y(), b.y2())) 
00818                 return false;
00819 
00820         // c is below b 
00821         if(TeGeometryAlgorithmsPrecision::IsGreater(b.y1(), c.y())) 
00822                 return false;
00823 
00824         return true;
00825 }
00826 
00827 template<> bool TeIntersects(const TePoint& p, const TeBox& b)
00828 {
00829         return TeIntersects(p.location(), b);
00830 }
00831 
00832 template<> bool TeIntersects(const TeBox& bx1, const TeBox& bx2)
00833 {
00834         // B1 to the right of B2
00835         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.x1(), bx2.x2())) 
00836                 return false;
00837 
00838         // B1 to the left of B2
00839         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.x1(), bx1.x2())) 
00840                 return false;
00841 
00842         // B2 is above B1
00843         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.y1(), bx1.y2())) 
00844                 return false;
00845 
00846         // B2 is below B1 
00847         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.y1(), bx2.y2())) 
00848                 return false;
00849 
00850         return true;
00851 }
00852 
00853 
00854 // TOUCHES
00855 bool TeTouches(const TeCoord2D& c, const TeLine2D& l)
00856 {
00857         return TeRelation(c, l) == TeBOUNDARY;
00858 }
00859 
00860 bool TeTouches(const TeCoord2D& c, const TePolygon& pol)
00861 {
00862         return TeRelation(c, pol) == TeBOUNDARY;
00863 }
00864 
00865 bool TeTouches(const TePoint& p, const TeLine2D& l)
00866 {
00867         return TeTouches(p.location(), l);
00868 }
00869 
00870 bool TeTouches(const TePoint& p, const TePolygon& pol)
00871 {
00872         return TeTouches(p.location(), pol);
00873 }
00874 
00875 bool TeTouches(const TeLine2D& redLine, const TeLine2D& blueLine)
00876 {
00877         if(TeDisjoint(redLine.box(), blueLine.box()))
00878                 return false;
00879 
00880         return TeRelation(redLine, blueLine, TeTOUCHES) == TeTOUCHES;   
00881 }
00882 
00883 bool TeTouches(const TeLine2D& l, const TePolygon& pol)
00884 {
00885         if(TeDisjoint(l.box(), pol.box()))
00886                 return false;
00887 
00888         return TeRelation(l, pol) == TeTOUCHES;
00889 }
00890 
00891 bool TeTouches(const TePolygon& redPol, const TePolygon& bluePol)
00892 {
00893         if(TeDisjoint(redPol.box(), bluePol.box()))
00894                 return false;
00895 
00896         return TeRelation(redPol, bluePol) == TeTOUCHES;
00897 }
00898 
00899 bool TeTouches(const TeBox& bx1, const TeBox& bx2)
00900 {       
00901         // bx1 may touches its right wall in bx2 left wall
00902         // or bx1 may touches its left wall in bx2 right wall
00903         if(TeGeometryAlgorithmsPrecision::IsEqual(bx1.x2(), bx2.x1()) || TeGeometryAlgorithmsPrecision::IsEqual(bx1.x1(), bx2.x2()))
00904         {
00905                 // bx1 is below bx2
00906                 if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.y1(), bx1.y2()))
00907                         return false;
00908 
00909                 // bx1 is above bx2
00910                 if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.y1(), bx2.y2()))
00911                         return false;
00912 
00913                 // touches
00914                 return true;    
00915         }
00916 
00917         // bx1 may touches its bottom wall in bx2 top wall
00918         // or bx1 may touches its top wall in bx2 bottom wall
00919         if(TeGeometryAlgorithmsPrecision::IsEqual(bx1.y1(), bx2.y2()) || TeGeometryAlgorithmsPrecision::IsEqual(bx1.y2(), bx2.y1()))
00920         {
00921                 // bx1 is left of bx2
00922                 if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.x1(), bx1.x2()))
00923                         return false;
00924 
00925                 // bx1 is right of bx2
00926                 if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.x1(), bx2.x2()))
00927                         return false;
00928 
00929                 // touches
00930                 return true;
00931         }
00932 
00933         // doesn't touches
00934         return false;
00935 }
00936 
00937 bool TeTouches(const TeCell& c1, const TeCell& c2)
00938 {
00939         return TeTouches(c1.box(), c2.box());
00940 }
00941 
00942 bool TeTouches(const TeLine2D& line, const TeCell& cell)
00943 {
00944         return TeTouches(line, TeMakePolygon(cell.box()));
00945 }
00946 
00947 bool TeTouches(const TeCell& c1, const TePolygon& poly)
00948 {
00949         return  TeTouches (poly, TeMakePolygon(c1.box()));
00950 }
00951 
00952 bool TeTouches(const TePoint& point,const TeCell& c1)
00953 {
00954         return TeTouches(point.location(), TeMakePolygon(c1.box()));
00955 }
00956 
00957 
00958 // CROSSES
00959 bool TeCrosses(const TeLine2D& redLine, const TeLine2D& blueLine)
00960 {
00961         if(TeDisjoint(redLine.box(), blueLine.box()))
00962                 return false;
00963         else
00964                 return TeRelation(redLine, blueLine, TeCROSSES) == TeCROSSES;
00965 }
00966 
00967 bool TeCrosses(const TeLine2D& l, const TePolygon& pol)
00968 {
00969         if(TeDisjointOrTouches(l.box(), pol.box()))
00970                 return false;
00971         else
00972                 return TeRelation(l, pol) == TeCROSSES;
00973 }
00974 
00975 bool TeCrosses(const TeLine2D& l, const TeCell& cell)
00976 {
00977         return TeCrosses(l, TeMakePolygon(cell.box()));
00978 }
00979 
00980 
00981 // WITHIN
00982 bool TeWithin(const TeCoord2D& c1, const TeCoord2D& c2)
00983 {
00984         return TeEquals(c1, c2);
00985 }
00986 
00987 bool TeWithin(const TeCoord2D& c, const TeBox& b)
00988 {
00989         // c to the right of b left wall AND c to the left of b right wall
00990         // AND c below b top wall AND c above b bottom wall => then c is on b interior.
00991         return (TeGeometryAlgorithmsPrecision::IsGreater(c.x(), b.x1()) && TeGeometryAlgorithmsPrecision::IsGreater(b.x2(), c.x()) && TeGeometryAlgorithmsPrecision::IsGreater(b.y2(), c.y()) && TeGeometryAlgorithmsPrecision::IsGreater(c.y(), b.y1()));
00992 }
00993 
00994 bool TeWithin(const TeCoord2D& c, const TeLine2D& l)
00995 {
00996         return TeRelation(c, l) == TeINSIDE;
00997 }
00998 
00999 bool TeWithin(const TeCoord2D& c, const TePolygon& pol)
01000 {
01001         return TeRelation(c, pol) == TeINSIDE;
01002 }
01003 
01004 bool TeWithin(const TePoint& p1, const TePoint& p2)
01005 {
01006         return TeWithin(p1.location(), p2.location());
01007 }
01008 
01009 bool TeWithin(const TePoint& p, const TeLine2D& l)
01010 {
01011         return TeWithin(p.location(), l);
01012 }
01013 
01014 bool TeWithin(const TePoint& p, const TePolygon& pol)
01015 {
01016         return TeWithin(p.location(), pol);
01017 }
01018 
01019 bool TeWithin(const TeLine2D& redLine, const TeLine2D& blueLine)
01020 {
01021         if(TeWithinOrCoveredByOrEquals(redLine.box(), blueLine.box()))
01022                 return TeRelation(redLine, blueLine, TeWITHIN) == TeWITHIN;     
01023         else
01024                 return false;
01025 }
01026 
01027 bool TeWithin(const TeLine2D& l, const TePolygon& pol)
01028 {
01029         if(TeWithinOrCoveredByOrEquals(l.box(), pol.box()))     
01030                 return TeRelation(l, pol) == TeWITHIN;
01031 
01032 
01033         return false;
01034 }
01035 
01036 bool TeWithin(const TePolygon& redPol, const TePolygon& bluePol)
01037 {
01038         if(TeWithinOrCoveredByOrEquals(redPol.box(), bluePol.box()))    
01039                 return TeRelation(redPol, bluePol) == TeWITHIN;
01040         else
01041                 return false;
01042 }
01043 
01044 bool TeWithin(const TeBox& bx1, const TeBox& bx2)
01045 {
01046         // bx1 left wall is left of or on bx2 left wall
01047         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx2.x1(), bx1.x1()))
01048                 return false;
01049 
01050         // bx1 right wall is right of or on bx2 right wall
01051         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx1.x2(), bx2.x2()))
01052                 return false;
01053 
01054         // bx1 is below bx2 or on.
01055         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx2.y1(), bx1.y1()))
01056                 return false;
01057 
01058         // bx1 is above bx2 or on
01059         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx1.y2(), bx2.y2()))
01060                 return false;
01061 
01062         return true;    
01063 }
01064 
01065 bool TeWithin(const TeCell& cell1, const TeCell& cell2)
01066 {
01067         return TeWithin(cell1.box(), cell2.box());
01068 }
01069 
01070 bool TeWithin(const TeLine2D& line, const TeCell& cell)
01071 {
01072         return TeWithin(line, TeMakePolygon(cell.box()));
01073 }
01074 
01075 
01076 bool TeWithin(const TeCell& cell, const TePolygon& poly)
01077 {
01078         return TeWithin(TeMakePolygon(cell.box()), poly);
01079 }
01080 
01081 bool TeWithin(const TePoint& point, const TeCell& cell)
01082 {
01083         return TeWithin(point.location(), cell.box());
01084 }
01085 
01086 
01087 // OVERLAPS
01088 bool TeOverlaps(const TeLine2D& redLine, const TeLine2D& blueLine)
01089 {
01090         if(TeDisjoint(redLine.box(), blueLine.box()))
01091                 return false;
01092         else
01093                 return TeRelation(redLine, blueLine, TeOVERLAPS) == TeOVERLAPS;
01094 }
01095 
01096 bool TeOverlaps(const TePolygon& redPol, const TePolygon& bluePol)
01097 {
01098         //if(TeDisjoint(redPol.box(), bluePol.box()))
01099         if(TeDisjointOrTouches(redPol.box(), bluePol.box()))
01100                 return false;
01101         else
01102                 return TeRelation(redPol, bluePol) == TeOVERLAPS;
01103 }
01104 
01105 bool TeOverlaps(const TeCell& cell1, const TeCell& cell2)
01106 {
01107         return TeOverlaps(TeMakePolygon(cell1.box()), TeMakePolygon(cell2.box()));
01108 }
01109 
01110 bool TeOverlaps(const TeCell& cell, const TePolygon& poly)
01111 {
01112         return TeOverlaps(TeMakePolygon(cell.box()), poly);
01113 }
01114 
01115 
01116 // COVERED BY
01117 bool TeCoveredBy(const TeLine2D& redLine, const TeLine2D& blueLine)
01118 {
01119         if(TeWithinOrCoveredByOrEquals(redLine.box(), blueLine.box()))
01120                 return TeRelation(redLine, blueLine, TeCOVEREDBY) == TeCOVEREDBY;
01121         else
01122                 return false;
01123 }
01124 
01125 bool TeCoveredBy(const TeLine2D& l, const TePolygon& pol)
01126 {
01127         if(TeWithinOrCoveredByOrEquals(l.box(), pol.box()))
01128                 return TeRelation(l, pol) == TeCOVEREDBY;
01129         else
01130                 return false;
01131 }
01132 
01133 bool TeCoveredBy(const TePolygon& redPol, const TePolygon& bluePol)
01134 {
01135         if(TeWithinOrCoveredByOrEquals(redPol.box(), bluePol.box()))
01136                 return TeRelation(redPol, bluePol) == TeCOVEREDBY;
01137         else
01138                 return false;
01139 }
01140 
01141 bool TeCoveredBy(const TeCell& cell1, const TeCell& cell2)
01142 {
01143         return TeCoveredBy(TeMakePolygon(cell1.box()), TeMakePolygon(cell2.box()));
01144 }
01145 
01146 bool TeCoveredBy(const TePolygon& poly, const TeCell& cell)
01147 {
01148         return TeCoveredBy(poly, TeMakePolygon(cell.box()));
01149 }
01150 
01151 bool TeCoveredBy(const TeLine2D& line, const TeCell& cell)
01152 {
01153         return TeCoveredBy(line, TeMakePolygon(cell.box()));
01154 }
01155 
01156 //---------- Box Tests ----------//
01157 
01158 bool TeDisjointOrTouches(const TeBox& bx1, const TeBox& bx2)
01159 {
01160         // B1 to the right of or on B2
01161         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx1.x1(), bx2.x2())) 
01162                 return true;
01163 
01164         // B1 to the left of or on B2
01165         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx2.x1(), bx1.x2())) 
01166                 return true;
01167 
01168         // B2 is above or on B1
01169         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx2.y1(), bx1.y2())) 
01170                 return true;
01171 
01172         // B2 is below or on B1 
01173         if(TeGeometryAlgorithmsPrecision::IsGreaterEqual(bx1.y1(), bx2.y2())) 
01174                 return true;
01175 
01176         return false;
01177 }
01178 
01179 template<>
01180 bool TeWithinOrCoveredByOrEquals(const TeBox& bx1, const TeBox& bx2)
01181 {
01182         // bx1 left wall is left of bx2 left wall
01183         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.x1(), bx1.x1()))
01184                 return false;
01185 
01186         // bx1 right wall is right of bx2 right wall
01187         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.x2(), bx2.x2()))
01188                 return false;
01189 
01190         // bx1 is below bx2
01191         if(TeGeometryAlgorithmsPrecision::IsGreater(bx2.y1(), bx1.y1()))
01192                 return false;
01193 
01194         // bx1 is above bx2
01195         if(TeGeometryAlgorithmsPrecision::IsGreater(bx1.y2(), bx2.y2()))
01196                 return false;
01197 
01198         return true;    
01199 }
01200 
01201 template<>
01202 bool TeWithinOrCoveredByOrEquals(const TeLine2D& line1, const TeLine2D& line2)
01203 {
01204         if(TeWithinOrCoveredByOrEquals(line1.box(), line2.box()))
01205         {
01206                 short r;
01207                 short rel = TeRelation(line1, line1, r);
01208 
01209                 if((rel&TeWITHIN) || (rel&TeCOVEREDBY) || (rel&TeEQUALS))
01210                    return true;
01211 
01212                 return false;
01213         }
01214         return false;
01215 }
01216 
01217 template<>
01218 bool TeWithinOrCoveredByOrEquals(const TeLine2D& line1, const TePolygon& pol)
01219 {
01220         if(TeWithinOrCoveredByOrEquals(line1.box(), pol.box()))
01221         {
01222                 short rel = TeRelation(line1, pol);
01223 
01224                 if((rel&TeWITHIN) || (rel&TeCOVEREDBY))
01225                    return true;
01226 
01227                 return false;
01228         }
01229         return false;
01230 }
01231 
01232 template<>
01233 bool TeWithinOrCoveredByOrEquals(const TePolygon& pol1, const TePolygon& pol2)
01234 {
01235         if(TeWithinOrCoveredByOrEquals(pol1.box(), pol2.box()))
01236         {
01237                 short rel = TeRelation(pol1, pol2);
01238 
01239                 if((rel&TeWITHIN) || (rel&TeCOVEREDBY) || (rel&TeEQUALS))
01240                    return true;
01241 
01242                 return false;
01243         }
01244         return false;
01245 }
01246 
01247 
01248 bool TeWithinOrTouches(const TeCoord2D& c, const TeCoord2D& c1, const TeCoord2D& c2)
01249 {
01250         // c is to the right of c1 and c2
01251         if(TeGeometryAlgorithmsPrecision::IsGreater(c.x(), c1.x()) && TeGeometryAlgorithmsPrecision::IsGreater(c.x(), c2.x()))
01252                 return false;
01253 
01254         // c is above c1 and c2
01255         if(TeGeometryAlgorithmsPrecision::IsGreater(c.y(), c1.y()) && TeGeometryAlgorithmsPrecision::IsGreater(c.y(), c2.y()))
01256                 return false;
01257 
01258         // c is to the left of c1 and c2
01259         if(TeGeometryAlgorithmsPrecision::IsSmaller(c.x(), c1.x()) && TeGeometryAlgorithmsPrecision::IsSmaller(c.x(), c2.x()))
01260                 return false;
01261 
01262         // c is below c1 and c2
01263         if(TeGeometryAlgorithmsPrecision::IsSmaller(c.y(), c1.y()) && TeGeometryAlgorithmsPrecision::IsSmaller(c.y(), c2.y()))
01264                 return false;
01265 
01266         return true;    
01267 }
01268 
01269 
01270 //---------- Intersection Functions ----------//
01271 
01272 bool TeIntersection(const TeBox& bx1, const TeBox& bx2, TeBox& bout)
01273 {
01274         if(TeDisjoint(bx1, bx2))
01275                 return false;
01276 
01277         double x1 = MAX(bx1.x1(),bx2.x1());
01278         double x2 = MIN(bx1.x2(),bx2.x2());
01279         double y1 = MAX(bx1.y1(),bx2.y1());
01280         double y2 = MIN(bx1.y2(),bx2.y2());
01281 
01282         bout = TeBox(x1, y1, x2, y2);
01283 
01284         return true;
01285 }
01286 
01287 TeCoordPairVect TeGetIntersections(const TePolygon &poly, const double& y)
01288 {
01289         TeCoordPairVect         Segments;
01290         vector<double>          crossList, segListInY;
01291         unsigned int            nholes = poly.size();
01292                         
01293         //for each ring of the polygon
01294         for (unsigned int count=0; count<nholes; count++ )              
01295         {
01296                 TeLinearRing coords = poly[count];
01297                 //for each segment of the ring
01298                 for  (unsigned int j=0;  j < (coords.size() - 1); j++ )                 
01299                 {
01300                         // Get one segment
01301                         TeCoord2D coord0 = coords[j];
01302                         TeCoord2D coord1 = coords[j+1];
01303 
01304                         bool yflag0 = ( coord0.y() > y );  
01305                         bool yflag1 = ( coord1.y() > y ); 
01306 
01307                         //treating a special case: when the segment touches or is ON the y axe  
01308                         //if there is a special case, we must test if the middle point
01309                         //of each segment is inside or outside of the polygon 
01310                         if((coord0.y()!=y) && (coord1.y()==y)) 
01311                         {
01312                                 bool pointsInY = true;
01313                                 bool lowerY1 = coord0.y()<y;
01314                 unsigned int i = j+2;
01315                                 
01316                                 TeCoord2D lastPointInY;
01317                                 TeCoord2D firstPointOutY = coord1;
01318                                 
01319                                 while(pointsInY) 
01320                                 {
01321                                         lastPointInY = firstPointOutY; 
01322 
01323                                         // Get the next point 
01324                                         if(i>=coords.size())
01325                                                 i=1;
01326                     firstPointOutY = coords[i];
01327                                         ++i;
01328 
01329                                         //Verify if it is on the y axe
01330                                         pointsInY = firstPointOutY.y()==y;
01331                                 }
01332 
01333                                 bool lowerY2 = firstPointOutY.y()<y;
01334                                 //the segment touches the y axe only in one point and cross the axe Y
01335                                 if((lastPointInY==coord1) && (lowerY1!=lowerY2)) 
01336                                         crossList.push_back(coord1.x());        
01337                                 else 
01338                                 {
01339                                         segListInY.push_back (coord1.x());
01340                                         segListInY.push_back (lastPointInY.x());
01341                                 }
01342                         }
01343                         else if(coord0.y()==y)
01344                                 continue;
01345                         // line crosses ring horizontally 
01346                         else if ( yflag0 != yflag1 )
01347                         { 
01348                                 double slope =  ( coord1.x() - coord0.x() ) / ( coord1.y() - coord0.y());
01349                                 double xcross = ( y -   coord0.y() )* slope + coord0.x();
01350                                 crossList.push_back (xcross);   
01351                         }
01352                 }
01353         }
01354         
01355         if(crossList.empty())
01356                 crossList = segListInY;
01357         else if(!segListInY.empty())
01358         {
01359                 //insert segListInY in the cross list 
01360                 for(unsigned i=0; i<segListInY.size(); ++i) 
01361                         crossList.push_back (segListInY[i]);
01362 
01363                 sort (crossList.begin(), crossList.end());
01364 
01365                 vector<double> aux;
01366                 //Verify if the segment middle point intersects the polygon 
01367                 for(unsigned i=1; i<crossList.size(); ++i)
01368                 {
01369                         //calculates the middle point
01370                         double x0 = crossList[i-1];
01371                         double x1 = crossList[i];
01372                         double x = x0 + (x1-x0)/2;
01373                         
01374                         TeCoord2D pt (x, y);
01375                         if (!TeDisjoint(pt, poly)) 
01376                         {
01377                                 aux.push_back (x0);
01378                                 aux.push_back (x1);
01379                         }
01380                 }
01381                 crossList.clear();
01382                 crossList = aux;
01383     }
01384         
01385         // Sort the x-intersections
01386         sort (crossList.begin(), crossList.end());
01387         
01388         // Make the result segments
01389         vector<double>::iterator it = crossList.begin();
01390         while ( it != crossList.end())
01391         {
01392                 TeCoordPair cp;
01393 
01394                 cp.pt1 = TeCoord2D ( (*it), y);
01395                 ++it;
01396                 if ( it == crossList.end() ) 
01397                         break;
01398 
01399                 cp.pt2 = TeCoord2D ( (*it), y);
01400                 ++it;
01401 
01402                 Segments.push_back ( cp );
01403         }
01404         return Segments;
01405 }
01406 
01407 //---------- Union Operators ----------//
01408 
01409 TeBox TeUnion(const TeBox& bx1, const TeBox& bx2)
01410 {
01411         double x1 = MIN(bx1.x1(), bx2.x1());
01412         double y1 = MIN(bx1.y1(), bx2.y1());
01413                 
01414         double x2 = MAX(bx1.x2(), bx2.x2());
01415         double y2 = MAX(bx1.y2(), bx2.y2());            
01416 
01417         return TeBox(x1, y1, x2, y2);
01418 }
01419 
01420 
01421 //---------- Localization Functions ----------//
01422 
01423 bool TePointInPoly(const TeCoord2D& c, const TeLinearRing& r)
01424 {
01425         if(r.size() < 4)
01426                 return false;
01427 
01428         register double ty, tx;
01429 
01430         register const unsigned int nVertices = r.size();
01431 
01432         register bool inside_flag = false;
01433 
01434         register int j, yflag0, yflag1;
01435 
01436         TeLinearRing::iterator vtx0, vtx1;
01437 
01438         tx = c.x();
01439     ty = c.y();
01440     
01441         vtx0 = r.end() - 2;
01442 
01443     yflag0 = (vtx0->y() >= ty);
01444 
01445     vtx1 = r.begin();
01446 
01447     for(j = nVertices; --j; )
01448         {
01449                 yflag1 = (vtx1->y() >= ty);
01450                 
01451                 if(yflag0 != yflag1)
01452                 {
01453                         if(((vtx1->y() - ty) * (vtx0->x() - vtx1->x()) >=
01454                         (vtx1->x() - tx) * (vtx0->y() - vtx1->y())) == yflag1)
01455                         {
01456                                 inside_flag = !inside_flag ;
01457                         }
01458                 }
01459 
01460                 yflag0 = yflag1 ;
01461                 vtx0 = vtx1 ;
01462                 vtx1++;
01463     }
01464 
01465         return inside_flag;
01466 }
01467 
01468 bool TeIsOnSegment(const TeCoord2D& c, const TeCoord2D& c1, const TeCoord2D& c2)
01469 {
01470         if(TeWithinOrTouches(c, c1, c2))
01471         {
01472                 bool aux = false;
01473 
01474                 return TeINTERSECTOR2::TeCCW(c1, c2, c, aux) == TeNOTURN;
01475         }
01476 
01477         return false;   
01478 }
01479 
01480 bool TeIsOnLine(const TeCoord2D& c, const TeLine2D& l)
01481 {
01482         if(l.size() < 2)
01483                 return false;
01484 
01485         if(TeDisjoint(c, l.box()))
01486                 return false;
01487 
01488         TeLine2D::iterator it = l.begin();
01489 
01490         unsigned int nstep = l.size() - 1;
01491 
01492         for(unsigned int i = 0; i < nstep; ++i)
01493         {
01494                 if(TeIsOnSegment(c, *(it), *(it + 1)))
01495                         return true;
01496                 
01497                 ++it;
01498         }
01499         
01500         return false;
01501 }
01502 
01503 bool TeLocateLineSegment (TeCoord2D& pin, TeLine2D& line, int& segment, double /*tol*/)
01504 {
01505         if (line.size() < 2) 
01506                 return false;
01507 
01508         TeCoord2D pout;
01509                 
01510         segment = 0;
01511         double min_dist = TeMinimumDistance(line[0], line[1], pin, pout);
01512         
01513         for (unsigned int i = 2; i < line.size(); i++)
01514         {
01515                 double dist;
01516                 if ((dist = TeMinimumDistance (line[i-1],line[i], pin, pout)) < min_dist)
01517                 {               
01518                                 min_dist = dist;
01519                                 segment = i - 1;
01520                 }
01521         }
01522 
01523         return true;
01524 }
01525 
01526 
01527 //---------- Area Functions ----------//
01528 
01529 template<> double TeGeometryArea(const TePolygon& p)
01530 {
01531         if(p.size() > 0)
01532         {
01533                 TePolygon::iterator it = p.begin();
01534         
01535                 double area = fabs(Te2Area(*it));
01536 
01537                 ++it;
01538                 
01539                 // subtract inner rings area.
01540                 while(it != p.end())
01541                 {
01542                         area -= fabs(Te2Area(*it));
01543                         ++it;
01544                 }
01545 
01546                 return (area / 2.0);
01547         }
01548         
01549         return 0.0;
01550 }
01551 
01552 template<> double TeGeometryArea(const TePolygonSet& ps)
01553 {
01554         TePolygonSet::iterator it = ps.begin();
01555         
01556         double area = 0.0;
01557         
01558         while(it != ps.end())
01559         {
01560                 area += TeGeometryArea(*it);
01561                 ++it;
01562         }
01563 
01564         return (area);
01565 }
01566 
01567 template<> double TeGeometryArea(const TeBox& b)
01568 {
01569         return ((b.x2() - b.x1()) * (b.y2() - b.y1()));
01570 }
01571 
01572 template<> double TeGeometryArea(const TeMultiGeometry& mGeom)
01573 {
01574         if(mGeom.hasPolygons())
01575         {
01576                 TePolygonSet pSet;
01577                 mGeom.getGeometry(pSet);
01578                 return TeGeometryArea(pSet);
01579         }
01580         else if(mGeom.hasCells())
01581         {
01582                 TeCellSet cSet;
01583                 mGeom.getGeometry(cSet);
01584                 return TeGeometryArea(cSet);
01585         }
01586         return 0.;
01587 }
01588 
01589 //---------- ConvexHull ----------//
01590 
01591 //! If we have the  two end point equals, so we remove it.
01592 void removeDuplicatedCoords(vector<TeCoord2D>& coordSet)
01593 {
01594         if(coordSet[0] == coordSet[coordSet.size() - 1])
01595                 coordSet.erase(coordSet.end() - 1);
01596 
01597         return;
01598 }
01599 
01600 // Return a linear ring that is the convex hull of a given list of coords
01601 TePolygon TeConvexHull(std::vector<TeCoord2D>& coordSet)
01602 {
01603         // sorting the coords
01604         sort(coordSet.begin(), coordSet.end(), xOrder<TeCoord2D>());
01605 
01606         register unsigned int i = 0;
01607         register unsigned int n = coordSet.size();
01608 
01609         TeLine2D upperHull;
01610         TeLine2D lowerHull;
01611 
01612         lowerHull.add(coordSet[0]);
01613         lowerHull.add(coordSet[1]);
01614 
01615         unsigned int count = 2;
01616 
01617         bool aux = false;
01618         
01619         for(i = 2; i < n; ++i)
01620         {
01621                 lowerHull.add(coordSet[i]);
01622 
01623                 ++count;
01624 
01625                 while(count > 2 && TeINTERSECTOR2::TeCCW(lowerHull[count - 3], lowerHull[count - 2], lowerHull[count - 1], aux) <= TeNOTURN)
01626                 {
01627                         lowerHull.erase(count - 2);
01628                         --count;
01629                 }
01630         }
01631 
01632         upperHull.add(coordSet[n - 1]);
01633         upperHull.add(coordSet[n - 2]);
01634 
01635         count = 2;
01636 
01637         for(i = n - 2;  i > 0;  --i)
01638         {
01639                 upperHull.add(coordSet[i - 1]);
01640                 ++count;
01641 
01642                 while(count > 2 && TeINTERSECTOR2::TeCCW(upperHull[count - 3], upperHull[count - 2], upperHull[count - 1], aux) <= TeNOTURN)
01643                 {
01644                         upperHull.erase(count - 2);
01645                         --count;
01646                 }
01647         }
01648 
01649         
01650         upperHull.erase(0);
01651         upperHull.erase(upperHull.size() - 1);
01652         
01653         lowerHull.copyElements(upperHull);
01654         lowerHull.add(lowerHull[0]);
01655 
01656         TeLinearRing aux_ring(lowerHull);
01657         TePolygon p;
01658         p.add(aux_ring);
01659         return p;
01660 }
01661 
01662 TePolygon TeConvexHull(const TePolygon& p)
01663 {
01664         vector<TeCoord2D> coords;
01665         back_insert_iterator<vector<TeCoord2D> > it(coords);
01666         // Copy the first ring of each polygon without the last point (that is equals to the first).
01667         
01668         copy(p[0].begin(), p[0].end() - 1, it);
01669 
01670         return TeConvexHull(coords);
01671 }
01672 
01673 TePolygon TeConvexHull(const TePolygonSet& ps)
01674 {
01675         vector<TeCoord2D> coords;
01676         back_insert_iterator<vector<TeCoord2D> > it(coords);
01677         // Copy the first ring of each polygon without the last point (that is equals to the first).
01678         
01679         TePolygonSet::iterator it_ps = ps.begin();
01680         while(it_ps != ps.end())
01681         {
01682                 TeLinearRing r = (*it_ps)[0];
01683                 copy(r.begin(), r.end() - 1, it);
01684                 ++it_ps;
01685         }
01686 
01687         return TeConvexHull(coords);
01688 }
01689 
01690 TePolygon TeConvexHull(const TePointSet& ps)
01691 {
01692         vector<TeCoord2D> coords;
01693         // Copy the first ring of each polygon without the last point (that is equals to the first).
01694         
01695         TePointSet::iterator itr = ps.begin();
01696         
01697         while(itr != ps.end())
01698         {
01699                 coords.push_back(itr->location());
01700 
01701                 ++itr;
01702         }
01703 
01704         return TeConvexHull(coords);
01705 }
01706 
01707 //---------- Utilities Functions ----------//
01708 
01709 
01710 
01711 //---------- Validation Functions ----------//
01712 
01713 bool TeIsConvex(const TeLinearRing& ring)
01714 {
01715         bool aux = false;
01716 
01717         short orientation = TeINTERSECTOR2::TeCCW(*(ring.end() - 2), ring[0], ring[1], aux);
01718 
01719         const unsigned int nStep = ring.size() - 1;
01720         
01721         for(unsigned int i = 1; i <  nStep; ++i)
01722         {
01723                 short this_orientation = TeINTERSECTOR2::TeCCW(ring[i-1], ring[i], ring[i+1], aux);
01724                 
01725                 if(this_orientation == TeNOTURN)
01726                         continue;
01727 
01728                 if((orientation != TeNOTURN) && (orientation != this_orientation))
01729                         return false;
01730 
01731                 orientation = this_orientation;         
01732         }
01733 
01734         return true;
01735 }
01736 
01737 short TeOrientation(const TeLinearRing& r)
01738 {
01739         double area = Te2Area(r);
01740 
01741         if(area >  0.0)
01742                 return TeCOUNTERCLOCKWISE; 
01743 
01744         if(area < 0.0)
01745                 return TeCLOCKWISE;  
01746 
01747         return TeNOTURN;
01748 }
01749 
01750 void TeGetMiddlePoint(const TeCoord2D &first, const TeCoord2D &last, TeCoord2D &middle)
01751 {
01752         double  lenght,parts,curlenght,incx,incy,
01753                         deltax,deltay,dx,dy;
01754         short   i,nparts;
01755         
01756         lenght = TeDistance(first,last);
01757         if(lenght == 0.)
01758         {
01759                 middle = first;
01760                 return;
01761         }
01762 
01763         nparts = 2;     
01764         parts = lenght/2.;
01765 // verify segment orientation
01766         if(first.x() < last.x())
01767                 incx = 1.;
01768         else
01769                 incx = -1.;
01770 
01771         if(first.y() < last.y())
01772                 incy = 1.;
01773         else
01774                 incy = -1.;
01775 
01776         curlenght = 0.;
01777         deltax = fabs(first.x()-last.x());
01778         deltay = fabs(first.y()-last.y());
01779         for(i=0;i<(nparts-1);i++)
01780         {
01781                 curlenght = curlenght + parts;
01782                 // vertical segment
01783                 if(first.x() == last.x())
01784                 {
01785                         middle = TeCoord2D(first.x(),first.y()+(curlenght*incy));
01786                         continue;
01787                 }
01788                                 
01789                 // horizontal segment
01790                 if(first.y() == last.y())
01791                 {
01792                         middle = TeCoord2D(first.x()+(curlenght*incx),first.y());
01793                         continue;
01794                 }
01795                 
01796                 // inclined segment
01797                 
01798                 // calculating X coordinate
01799                 dx = curlenght*deltax/lenght;
01800                 
01801                 // calculating Y coordinate
01802                 dy = curlenght*deltay/lenght;
01803                 middle = TeCoord2D(first.x()+(dx*incx),first.y()+(dy*incy));
01804         }
01805 }
01806 
01807 //---------- Metric Functions ----------//
01808 
01809 double TeDistance(const TeCoord2D& c1, const TeCoord2D& c2)
01810 {
01811         return sqrt(((c2.x() - c1.x()) * (c2.x() - c1.x())) + ((c2.y()-c1.y()) * (c2.y() - c1.y())));
01812 }
01813 
01814 double TeLength(const TeLine2D& l)
01815 {
01816         double len = 0.0;
01817 
01818         unsigned int nStep = l.size() - 1;
01819 
01820         for(unsigned int i = 0 ; i < nStep; ++i)
01821                 len += TeDistance(l[i], l[i+1]);
01822         
01823         return len;
01824 }
01825 
01826 double TePerpendicularDistance(const TeCoord2D& first, const TeCoord2D& last, const TeCoord2D& pin, TeCoord2D &pinter)
01827 {
01828         double  d12,xmin,ymin;
01829 
01830         double xi = first.x();
01831         double xf = last.x();
01832         double yi = first.y();
01833         double yf = last.y();
01834         double x = pin.x();
01835         double y = pin.y();
01836                 
01837         double dx = xf - xi;
01838         double dy = yf - yi;
01839         double a2 = (y - yi) * dx - (x - xi)*dy;
01840         
01841     if(dx==0. && dy==0.)
01842         {
01843                 d12= sqrt(((x - xi) * (x - xi)) + ((y - yi) * (y - yi)));
01844                 d12 *= d12;
01845         }
01846         else
01847                 d12= a2 * a2 / (dx * dx + dy * dy);
01848 
01849         if (dx == 0.)
01850         {
01851                 xmin = xi;
01852                 ymin = y;
01853         }
01854         else if (dy == 0.)
01855         {
01856                 xmin = x;
01857                 ymin = yi;
01858         }
01859         else
01860         {
01861                 double alfa = dy / dx;
01862                 xmin = (x + alfa * (y - yi) + alfa * alfa * xi) / (1. + alfa * alfa);
01863                 ymin = (x - xmin) / alfa + y;   
01864         }
01865         
01866         pinter = TeCoord2D(xmin, ymin);         
01867         return (sqrt(d12));
01868 }
01869 
01870 double TeMinimumDistance (const TeCoord2D& first, const TeCoord2D& last, const TeCoord2D& pin, TeCoord2D& pout, double /*tol*/)
01871 {
01872         TeCoord2D       pinter;
01873         TeBox           sbox(MIN(first.x(),last.x()),
01874                                          MIN(first.y(),last.y()),
01875                                          MAX(first.x(),last.x()),
01876                                          MAX(first.y(),last.y()));
01877 
01878         double d = TePerpendicularDistance (first, last, pin, pinter);
01879         double dmin = TeMAXFLOAT;
01880 
01881         // Perpendicular minimum distance point was found.
01882         if (TeIntersects (pinter, sbox))
01883         {
01884                 dmin = d;
01885                 pout = pinter;
01886         }
01887         else  
01888         {
01889                 // Perpendicular minimum distance point could not be found. 
01890                 // The segment vertices distances will analyzed
01891                 double d1 = TeDistance (first, pin);
01892                 double d2 = TeDistance (last, pin);
01893                 if (d1 <= d2) 
01894                 {
01895                         dmin = d1;
01896                         pout = first;
01897                 }
01898                 else if (d2 < dmin) 
01899                 {
01900                         dmin = d2;
01901                         pout = last;
01902                 }
01903         }
01904 
01905         return dmin;
01906 }
01907 
01908 
01909 //---------- Relation Functions ----------//
01910 
01911 short TeRelation(const TeCoord2D& c, const TeLine2D& l)
01912 {
01913         if(TeEquals(c, l[0]) || TeEquals(c, l[l.size() - 1]))
01914         {
01915                 // Ring doesn't have bundaries, only interiors.
01916                 if(l.isRing())
01917                         return TeINSIDE;
01918 
01919                 return TeBOUNDARY;
01920         }
01921 
01922         if(TeIsOnLine(c, l))
01923                 return TeINSIDE;
01924 
01925         return TeOUTSIDE;
01926 }
01927 
01928 short TeRelation(const TeCoord2D& c, const TeLinearRing& r)
01929 {
01930         if(TeDisjoint(c, r.box()))
01931                 return TeOUTSIDE;
01932 
01933         if(TeIsOnLine(c, r))
01934                 return TeBOUNDARY;
01935 
01936         if(TePointInPoly(c, r))
01937                 return TeINSIDE;
01938         else
01939                 return TeOUTSIDE;
01940 }
01941 
01942 short TeRelation(const TeCoord2D& c, const TePolygon& pol)
01943 {
01944         short rel = TeRelation(c, pol[0]);
01945         
01946         if(rel != TeINSIDE)
01947                 return rel;
01948         else    // If point is inside exterior ring
01949         {
01950                 unsigned int size = pol.size();
01951 
01952                 for(unsigned int i = 1; i < size; ++i)
01953                 {
01954                         rel = TeRelation(c, pol[i]);
01955                 
01956                         switch(rel)
01957                         {
01958                                 // If point is inside a hole so it is on polygon's outside.
01959                                 case TeINSIDE    :      return TeOUTSIDE;
01960 
01961                                 // If point is on boundary so it is on polygon's boundary.
01962                                 case TeBOUNDARY  :  return TeBOUNDARY;
01963                         }
01964                 }
01965         }
01966 
01967         // If the point is inside exterior ring and is not on one of the holes so it is in polygon's interior.
01968         return TeINSIDE;
01969 }
01970 
01971 short TeRelation(const TePoint& p, const TePolygon& pol)
01972 { 
01973         return (TeRelation(p.location(), pol)); 
01974 }
01975 
01976 short TeRelation(const TeCoord2D& c, const TePolygonSet& pSet)
01977 {
01978         if(TeDisjoint(c, pSet.box()))
01979                 return TeOUTSIDE;
01980 
01981         unsigned int size = pSet.size();
01982 
01983         for(unsigned int i = 0; i < size; ++i)
01984         {
01985                 short rel = TeRelation(c, pSet[i]);
01986                 
01987                 if(rel & TeINSIDE)
01988                         return TeINSIDE;
01989                 
01990                 if(rel & TeBOUNDARY)
01991                         return TeBOUNDARY;
01992         }
01993 
01994         return TeOUTSIDE;
01995 }
01996 
01997 short TeRelation(const TeLine2D& lRed, const TeLine2D& lBlue, const short& relation)
01998 {
01999         TeINTERSECTOR2::TeVectorBoundaryIP report;
02000 
02001         if(TeINTERSECTOR2::TeSafeIntersections(lRed, lBlue, report))
02002         {
02003                 short rel = Relation(lRed, lBlue, report, relation);            
02004 
02005                 // Stop to check, because touches can't occur anymore
02006                 if((relation == TeTOUCHES || relation == TeCROSSES) && rel != relation)
02007                         return TeUNDEFINEDREL;
02008 
02009                 if(rel != TeUNDEFINEDREL)
02010                         return rel;
02011 
02012                 TeINTERSECTOR2::TeVectorBoundaryIP::iterator it = report.begin();
02013                 TeINTERSECTOR2::TeVectorBoundaryIP::iterator it_end = report.end();
02014                 
02015                 for(unsigned int i = 0; i < report.size(); ++i)
02016                 {
02017                         swap(report[i].redPartNum_, report[i].bluePartNum_);
02018                         swap(report[i].redSegNum_, report[i].blueSegNum_);
02019                 }
02020 
02021                 rel = Relation(lBlue, lRed, report, relation);
02022 
02023                 if(rel != TeUNDEFINEDREL)
02024                         return ConverseRelation(rel);
02025                 else
02026                         return TeOVERLAPS;
02027         }
02028         else
02029                 return TeDISJOINT;
02030 }
02031 
02032 short TeRelation(const TeLine2D& line, const TePolygon& pol)
02033 {
02034         short rel = TopologicRelation(line, pol[0]);
02035 
02036         if(rel & TeTOUCHES || rel & TeCROSSES || rel & TeDISJOINT)
02037                 return rel;
02038 
02039         // If relation is WITHIN or COVERED BY we need to test inner rings.
02040         register unsigned int i = 1;
02041         register unsigned int nRings = pol.size();
02042 
02043         for(; i < nRings; ++i)
02044         {
02045                 short rel_aux = TopologicRelation(line, pol[i]);
02046 
02047                 switch(rel_aux)
02048                 {
02049                         case TeCROSSES   : return TeCROSSES;
02050 
02051                         case TeCOVEREDBY : return TeTOUCHES;
02052 
02053                         case TeTOUCHES   : rel = TeCOVEREDBY;
02054                                                break;   // Needs to check other holes.
02055 
02056                         case TeWITHIN    : return TeDISJOINT;
02057 
02058                         case TeDISJOINT  : break;       // Keeps rel and check other inner rings
02059                 }
02060         }
02061 
02062         return rel;
02063 }
02064 
02065 short TeRelation(const TePolygon& pRed, const TePolygon& pBlue)
02066 {
02067 
02068         short rel = TopologicRelation(pRed[0], pBlue[0]);
02069 
02070         if(rel & TeTOUCHES || rel & TeOVERLAPS || rel & TeDISJOINT)
02071                 return rel;
02072 
02073         
02074         short rel_external_ring = TeUNDEFINEDREL;
02075 
02076         bool converse = false;
02077 
02078         vector<TeLinearRing> innerRingsToTest;
02079 
02080         switch(rel)
02081         {
02082                 case TeWITHIN           : 
02083                 case TeCOVEREDBY        :
02084                                   // if pBlue has inner rings.
02085                                           if(pBlue.size() > 1)
02086                                                           {
02087                                                                   rel_external_ring = LookAtInnerRings(pRed[0], pBlue, innerRingsToTest, rel);  
02088                                                           }
02089                                                           else  // else if it hasn't
02090                                                           {
02091                                                                   return rel;
02092                                                           }
02093                                                           break;
02094 
02095                 case TeCONTAINS         :
02096                 case TeCOVERS           : 
02097                                                           // if pRed has inner rings.
02098                                           if(pRed.size() > 1)
02099                                                           {
02100                                                                   rel_external_ring = LookAtInnerRings(pBlue[0], pRed, innerRingsToTest, rel);                                                        
02101                                                           }
02102                                                           else  // else if it hasn't
02103                                                           {
02104                                                                   return rel;
02105                                                           }
02106 
02107                                                           converse = true;
02108                                                           break;
02109 
02110                 case TeEQUALS           :
02111                                           if(pRed.size() != pBlue.size())
02112                                                                   return TeOVERLAPS;
02113 
02114                                                           if(pRed.size() == 1 && pBlue.size() == 1)
02115                                                                   return rel;
02116 
02117                                                           for(unsigned int k = 1; k < pBlue.size(); k++)
02118                                                                   innerRingsToTest.push_back(pBlue[k]);
02119 
02120                                                           rel_external_ring = TeUNDEFINEDREL;
02121         }
02122         
02123         if(rel_external_ring != TeUNDEFINEDREL) 
02124                 return rel_external_ring;       
02125 
02126         // If we are here, so we need to test 
02127         if(converse)    // COVERS or CONTAINS
02128         {
02129                 if(pBlue.size() == 1 && innerRingsToTest.size() == 0)
02130                 {
02131                         TeSpatialRelation spatialRel = (TeSpatialRelation)rel;
02132                         if (spatialRel == TeCOVEREDBY)
02133                                 return TeCOVERS;
02134                         else
02135                                 return rel;
02136                         //return ((TeSpatialRelation)rel == TeCOVEREDBY) ? TeCOVERS : rel;      // entrou apenas no touches do lookat inner rings 
02137 
02138                 }
02139                 // The result may be: overlap or equals.
02140                 short rel_aux = TestInnerRings(pBlue, innerRingsToTest);
02141 
02142                 if(rel_aux & TeOVERLAPS)
02143                         return TeOVERLAPS;
02144 
02145                 if(rel_aux & TeCOVERS || rel_aux & TeEQUALS)
02146                         return TeCOVERS;
02147 
02148                 if(rel_aux & TeCONTAINS)
02149                         return TeCONTAINS;
02150         }
02151         else    // EQUALS, COVERED BY or WITHIN
02152         {
02153                 if(pRed.size() == 1 && innerRingsToTest.size() == 0)
02154                         return rel;     // entrou apenas no touches do lookat inner rings pois se desse covered by ou within teria inner rings
02155 
02156                 short rel_aux = TestInnerRings(pRed, innerRingsToTest);
02157 
02158                 if(rel_aux & TeOVERLAPS)
02159                         return TeOVERLAPS;
02160 
02161                 if((rel_aux == TeEQUALS) && (rel == TeEQUALS))
02162                         return TeEQUALS;
02163 
02164                 if((rel_aux & TeCOVERS) || (rel_aux & TeEQUALS))
02165                         return TeCOVEREDBY;     
02166 
02167                 if(rel_aux & TeCONTAINS)
02168                 {
02169                         if((rel == TeEQUALS) || (rel == TeCOVEREDBY))
02170                                 return TeCOVEREDBY;
02171 
02172                         return TeWITHIN;
02173                 }
02174         }
02175 
02176         return TeUNDEFINEDREL;
02177 }
02178 
02179 
02180 //---------- Generate Geometry Functions ----------//
02181 
02182 TePolygon TeMakePolygon(const TeBox& b)
02183 {
02184         TeLine2D l;
02185         
02186         l.add(b.lowerLeft());
02187         l.add(TeCoord2D(b.x2(), b.y1()));
02188         l.add(b.upperRight());
02189         l.add(TeCoord2D(b.x1(), b.y2()));
02190         l.add(b.lowerLeft());
02191         l.setBox(b);
02192 
02193         TePolygon p;
02194         p.add(TeLinearRing(l));
02195         p.setBox(b);
02196 
02197         return p;
02198 }
02199 
02200 TeLinearRing TeSimpleClosedPath(const TePointSet& pSet)
02201 {
02202         TeLine2D l;
02203 
02204         for(register unsigned int i = 0; i < pSet.size(); ++i)
02205                 l.add(pSet[i].location());
02206 
02207         ThetaOrder tr(pSet[0].location());
02208 
02209         sort(l.begin(), l.end(), tr);
02210 
02211         l.add(l[0]);
02212 
02213         return TeLinearRing(l);
02214 }
02215 
02216 
02217 //---------- Nearest ----------//
02218 
02219 bool TeNearest ( TeCoord2D& pt, TeNodeSet& ns , int& k, const double& tol)
02220 {
02221         double d,dmin = TeMAXFLOAT;
02222         bool flag = false;
02223 
02224         k = -1;
02225         for (unsigned int i=0; i < ns.size() ; i++)
02226         {
02227                 d = TeDistance (pt, ns[i].location());
02228                 if ( d <= tol && d < dmin)
02229                 {
02230                         dmin = d;
02231                         k = i;
02232                         flag = true;
02233                 }
02234         }
02235         return flag;
02236 }
02237 
02238 bool TeNearest ( TeCoord2D& pt, TePointSet& ps , int& k, const double& tol)
02239 {
02240         double d,dmin = TeMAXFLOAT;
02241         bool flag = false;
02242 
02243         k = -1;
02244         for (unsigned int i=0; i < ps.size() ; i++)
02245         {
02246                 d = TeDistance (pt, ps[i].location());
02247                 if ( d <= tol && d < dmin)
02248                 {
02249                         dmin = d;
02250                         k = i;
02251                         flag = true;
02252                 }
02253         }
02254         return flag;
02255 }
02256 
02257 bool TeNearest ( TeCoord2D& pt, TeTextSet& ts , int& k, const double& tol)
02258 {
02259         double d,dmin = TeMAXFLOAT;
02260         bool flag = false;
02261 
02262         k = -1;
02263         for (unsigned int i=0; i < ts.size() ; i++)
02264         {
02265                 d = TeDistance (pt, ts[i].location());
02266                 if ( d <= tol && d < dmin)
02267                 {
02268                         dmin = d;
02269                         k = i;
02270                         flag = true;
02271                 }
02272         }
02273         return flag;
02274 }
02275 
02276 bool TeNearest(TeCoord2D& pt, TeLineSet& ls , int& k, TeCoord2D& pi, const double& tol)
02277 {
02278         double d,dmin = TeMAXFLOAT;
02279         bool flag = false;
02280 
02281         k = -1;
02282         for (unsigned int i=0 ; i<ls.size() ; i++)
02283         {
02284                 TeLine2D line = ls[i];
02285                 TeBox lb = line.box();
02286                 TeBox box(lb.x1()-tol,lb.y1()-tol,lb.x2()+tol,lb.y2()+tol);
02287                 if (TeIntersects(pt, box))
02288                 {
02289                         for (unsigned int j=0 ; j<line.size()-1 ; j++)
02290                         {
02291                                 TeCoord2D       pinter;
02292                                 TeBox           sbox(MIN(line[j].x(),line[j+1].x()),
02293                                                                 MIN(line[j].y(),line[j+1].y()),
02294                                                                 MAX(line[j].x(),line[j+1].x()),
02295                                                                 MAX(line[j].y(),line[j+1].y()));
02296                                 d = TePerpendicularDistance (line[j],line[j+1],pt, pinter);
02297                                 if((d <= tol) && (d < dmin) && TeIntersects(pinter, sbox))
02298                                 {
02299                                         dmin = d;
02300                                         k = i;
02301                                         pi = pinter;
02302                                         flag = true;
02303                                 }
02304                         }
02305                 }
02306         }
02307         return flag;
02308 }
02309 
02310 
02311 bool TeNearest (TeCoord2D& pt,TeLineSet& ls, int& lindex, TeCoord2D& pout, double& dmin, const double& tol)
02312 {
02313         bool flag = false;
02314         TeCoord2D       pinter;
02315 
02316         dmin = TeMAXFLOAT;
02317         lindex = -1;
02318 
02319         for (unsigned int i = 0 ; i < ls.size(); i++)
02320         {
02321                 TeLine2D line = ls[i];
02322 
02323                 for (unsigned int j = 0 ; j < line.size() - 1 ; j++)
02324                 {
02325                         double d = TeMinimumDistance (line[j], line[j + 1], pt, pinter, tol);
02326                         if (d < dmin)
02327                         {
02328                                 lindex = i;
02329                                 pout = pinter;
02330                                 dmin = d;
02331                                 flag = true;
02332                         }
02333                 }
02334         }
02335         return flag;
02336 }
02337 
02338 bool TeNearest(TeCoord2D& pt, TePolygonSet& ps , int& k, const double& /*tol*/)
02339 {
02340         bool flag = false;
02341 
02342         k = -1;
02343         
02344         TePoint ptaux(pt);
02345 
02346         for (unsigned int i=0; i < ps.size() ; i++)
02347         {
02348                 if (TeIntersects(ptaux,ps[i]))
02349                 {
02350                         k = i;
02351                         flag = true;
02352                 }
02353         }
02354         return flag;
02355 }
02356 
02357 bool TeNearestByPoints ( TeCoord2D& pt, TeLineSet& ls , int& k, double& dist, const double& tol)
02358 {
02359         double d,dmin = TeMAXFLOAT;
02360         bool flag = false;
02361 
02362         k = -1;
02363         for (unsigned int i=0 ; i<ls.size() ; i++)
02364         {
02365                 TeLine2D line = ls[i];
02366                 TeBox lb = line.box();
02367                 TeBox box(lb.x1()-tol,lb.y1()-tol,lb.x2()+tol,lb.y2()+tol);
02368                 if (TeIntersects (pt,box))
02369                 {
02370                         for (unsigned int j=0 ; j<line.size()-1 ; j++)
02371                         {
02372                                 d = TeDistance (line[j],pt);
02373                                 if ( d <= tol && d < dmin )
02374                                 {
02375                                         dmin = d;
02376                                         dist = dmin;
02377                                         k = i;
02378                                         flag = true;
02379                                 }
02380                         }
02381                 }
02382         }
02383         return flag;
02384 }
02385 
02386 
02387 //---------- TIN ----------//
02388 
02389 bool TeFindTriangleCenter(const TeCoord2D& vert0, const TeCoord2D& vert1, const TeCoord2D& vert2, TeCoord2D& pc )
02390 {
02391         if ( vert0 == vert1 || vert0 == vert2 )
02392                 return false; // pontos sao iguais-> retorna
02393 
02394         //      calcula o coeficiente angular perpendicular a reta 1
02395         bool perpvert1 = false, // perpendicular vertical ao segmento 1 
02396                  perpvert2 = false;     // perpendicular vertical ao segmento 2 
02397         double  m1 = 10., m2 =10.;      // normais aos segmentos 1 e 2
02398         double prcsion = 1.0e-10;       // Precision to be used for equal comparison
02399         double oldPrcsion = TePrecision::instance().precision();
02400         TePrecision::instance().setPrecision(prcsion);
02401 
02402         if ( TeCoord2D( 0., vert0.y() ) == TeCoord2D( 0., vert1.y() ) )
02403                 perpvert1 = true;
02404         else 
02405                 m1 = -(vert1.x() - vert0.x()) / (vert1.y() - vert0.y());
02406 
02407 //      calcula o coeficiente angular da perpendicular a reta 2
02408         if ( TeCoord2D( 0., vert1.y() ) == TeCoord2D( 0., vert2.y() ) )
02409                 perpvert2 = true;
02410         else
02411                 m2 = -(vert2.x() - vert1.x()) / (vert2.y() - vert1.y());
02412 
02413         TePrecision::instance().setPrecision(oldPrcsion);
02414 //      Caso as retas sejam coincidentes, uma circunferencia 
02415 //       nao eh definida
02416         if (fabs( m1 - m2 ) > prcsion)
02417         {
02418 
02419 //      passou pelos testes: os pontos definem uma circunferencia
02420 //      calculo do ponto medio do segmento ponto0-ponto1 (segmento 1)
02421                 TeCoord2D ptm1 = vert0;
02422                 ptm1 += vert1;
02423                 ptm1.scale ( 0.5, 0.5);
02424 
02425 //      calculo do ponto medio do segmento ponto1-ponto2 (segmento 2)
02426                 TeCoord2D ptm2 = vert1;
02427                 ptm2 += vert2;
02428                 ptm2.scale ( 0.5, 0.5);
02429 
02430 //      calculo das coordenadas do centro: ponto de interseccao das mediatrizes
02431 //       dos segmentos ponto0-ponto1 e ponto1-ponto2
02432                 if (perpvert1 == true)
02433                 {
02434                         pc.x( ptm1.x() );
02435                         pc.y( ptm2.y() + m2 * ( pc.x() - ptm2.x() ) );
02436                 }
02437                 else if (perpvert2 == true)
02438                 {
02439                         pc.x( ptm2.x() );
02440                         pc.y( ptm1.y() + m1 * ( pc.x() - ptm1.x() ) );
02441                 }
02442                 else
02443                 {
02444                         pc.x( (m1*ptm1.x() - m2*ptm2.x() - ptm1.y() + ptm2.y())/(m1-m2) );
02445                         pc.y( ptm1.y() + m1 * ( pc.x() - ptm1.x() ) );
02446                 }
02447                 return true;
02448         }
02449         return false;
02450 }
02451 
02452 bool TeLineSimplify(TeLine2D& ptlist, double snap, double maxdist)
02453 {
02454 //      If snap is zero, don't worry
02455         if (snap == 0.0)
02456                 return true;
02457 //      If line is too short do nothing
02458         int npts = ptlist.size();
02459         if ( npts <= 3 )
02460                 return true;
02461         int npte = npts;
02462 
02463         double snap2 = maxdist*maxdist;
02464         TeLine2D vxy;
02465         vxy.copyElements(ptlist);
02466 
02467 //      Check for islands before defining number of points to be used
02468         int npt;
02469         if ( ptlist.last() == vxy.first() )
02470                 npt = npte - 1;
02471         else
02472                 npt = npte;
02473         ptlist.clear();
02474 
02475 //      initialize variables
02476         int i     = 0;
02477         int numa  = 0;
02478         int numpf = npt - 1;
02479 
02480 //      define anchor
02481         TeCoord2D axy = vxy[numa];
02482 
02483 //      define floating point
02484         TeCoord2D pfxy = vxy[numpf];
02485 
02486         while (numa < (npt-1))
02487         {
02488                 bool retv (false);
02489                 double aa1 = 0.;
02490                 double a = 0.;
02491                 double b = 0.;
02492 //              Compute coeficients of straight line y=ax+b
02493                 if (pfxy.x() == axy.x())
02494                         retv = true;
02495                 else
02496                 {
02497                         a = (pfxy.y() - axy.y())/(pfxy.x() - axy.x());
02498                         b = pfxy.y() - a * pfxy.x();
02499                         aa1     = sqrt(a * a + 1.);
02500                 }
02501 
02502                 double d    = 0;
02503                 double dmax = 0;
02504                 int numdmax = numpf;
02505 
02506                 int k;
02507                 for (k = numa + 1; k <= numpf; k++)
02508                 {
02509 //                      Distance between point and line
02510                         if (retv)
02511                                 d = fabs(axy.x() - vxy[k].x());
02512                         else
02513                                 d = fabs(vxy[k].y() - a*vxy[k].x() - b)/aa1;
02514 
02515                         if (d > dmax)
02516                         {
02517                                 dmax    = d;
02518                                 numdmax = k;
02519                         }
02520                 }
02521 
02522                 if (dmax <= snap)
02523                 {
02524 //                      Store selected point
02525                         if (i > (npt-1))
02526                                 return false;
02527                         vxy[i++] = axy;
02528                         
02529                         double axbx = pfxy.x()-axy.x();
02530                         double ayby = pfxy.y()-axy.y();
02531                         double dist2 = axbx*axbx + ayby*ayby;
02532                         if (dist2 > snap2)
02533                         {
02534                                 for (k = numpf; k > numa+1; k--)
02535                                 {
02536                                         axbx = vxy[k].x()-axy.x();
02537                                         ayby = vxy[k].y()-axy.y();
02538                                         dist2 = axbx*axbx + ayby*ayby;
02539                                         if (dist2 < snap2)
02540                                                 break;
02541                                 }
02542 //                              Shift anchor
02543                                 numa = k;
02544                                 axy = vxy[k];
02545                         }
02546                         else
02547                         {
02548 //                              Shift anchor
02549                                 numa = numpf;
02550                                 axy = vxy[numpf];
02551                         }
02552                         numpf = npt - 1;
02553                 }
02554                 else
02555                 {
02556 //                      Shift floating point
02557                         numpf = numdmax;
02558                 }
02559 
02560                 pfxy = vxy[numpf];
02561         }
02562 
02563 //      Store results
02564         vxy[i] = vxy[numa];
02565         npts = i+1;
02566 
02567         if ( vxy[i] == vxy[i-1] )
02568                 npts = i;
02569 
02570         for (i = 0; i < npts; i++)
02571                 ptlist.add( vxy[i] );
02572 
02573 //      Case islands
02574         if (vxy[0] == vxy[npte-1])
02575                 ptlist.add( vxy[0] );
02576 
02577         return true;
02578 }
02579 
02580 bool TeSegmentsIntersectPoint(const TeCoord2D& fr0, const TeCoord2D& to0, const TeCoord2D& fr1, const TeCoord2D& to1, TeCoord2D& pi)
02581 {
02582 //      Adapted from TWO-DIMENSIONAL CLIPPING: A VECTOR-BASED APPROACH
02583 //      Hans J.W. Spoelder, Fons H. Ullings in:
02584 //      Graphics Gems I, pp.701, 
02585 
02586         double  a, b, c,
02587                 px, py, lx, ly, lpx, lpy,
02588                 s;
02589 
02590         px  = to0.x() - fr0.x();
02591         py  = to0.y() - fr0.y();
02592         lx  = to1.x() - fr1.x();
02593         ly  = to1.y() - fr1.y();
02594         lpx = fr0.x() - fr1.x();
02595         lpy = fr0.y() - fr1.y();
02596 
02597         a = py * lx - px * ly;
02598         b = lpx * ly - lpy * lx;
02599         c = lpx * py - lpy * px;
02600 
02601         if (a == 0) // Linhas paralelas
02602                 return false;
02603         else
02604         {
02605                 if (a > 0)
02606                 {
02607                         if ((b < 0) || (b > a) || (c < 0) || (c > a))
02608                                 return false;
02609                 }
02610                 else
02611                 {
02612                         if ((b > 0) || (b < a) || (c > 0) || (c < a))
02613                                 return false;
02614                 }
02615                 s = b/a;
02616                 pi.x(fr0.x() + (px*s));
02617                 pi.y(fr0.y() + (py*s));
02618         }
02619         return true;
02620 }
02621 
02622 //---------- Curve ----------//
02623 
02624 /*! \fn void TeSwap(TePoint &p1, TePoint &p2)
02625     \brief Swaps to points.
02626         \param p1 The first point.
02627         \param p2 The second point.
02628 */
02629 void TeSwap(TePoint& p1, TePoint& p2)
02630 {
02631         TePoint temp;
02632 
02633         temp = p1;
02634         p1 = p2;
02635         p2 = temp;
02636 
02637         return;
02638 }
02639 
02640 bool TeGetCenter(TePoint p1, TePoint p2, TePoint p3, TePoint& center)
02641 {
02642         double x, y;
02643         double ma=0., mb= 0.;
02644         bool result = true;
02645 
02646         //we don't want infinite slopes, or 0 slope for line 1, since we'll divide by "ma" below
02647         if ((p1.location().x()==p2.location().x()) || (p1.location().y()==p2.location().y())) 
02648                 TeSwap(p2,p3);
02649           
02650         if (p2.location().x()==p3.location().x()) 
02651                 TeSwap(p1,p2);
02652 
02653         if (p1.location().x()!=p2.location().x())
02654                 ma=(p2.location().y()-p1.location().y())/(p2.location().x()-p1.location().x());
02655         else 
02656                 result=false;
02657           
02658         if (p2.location().x()!=p3.location().x()) 
02659                 mb=(p3.location().y()-p2.location().y())/(p3.location().x()-p2.location().x());
02660         else 
02661           result=false;
02662           
02663         if ((ma==0) && (mb==0)) 
02664                 result=false;
02665           
02666         if (result) 
02667         {
02668                 x=(ma*mb*(p1.location().y()-p3.location().y())+mb*(p1.location().x()+p2.location().x())-ma*(p2.location().x()+p3.location().x()))/(2*(mb-ma));
02669                 y=-(x-(p1.location().x()+p2.location().x())/2)/ma + (p1.location().y()+p2.location().y())/2;
02670                 
02671                 double w= x;  //TeRound(x);
02672                 double z= y;  //TeRound(y);     
02673                 TeCoord2D coord(w,z);
02674                 center.add(coord);
02675         }
02676   return result;
02677 }
02678 
02679 double TeGetRadius(TePoint& p1, TePoint& p2, TePoint& p3)
02680 {
02681         double s,a,b,c, result;
02682         a=sqrt(pow(p1.location().x()-p2.location().x(),2)+pow(p1.location().y()-p2.location().y(),2));  //sqr: square of the param
02683         b=sqrt(pow(p2.location().x()-p3.location().x(),2)+pow(p2.location().y()-p3.location().y(),2));
02684         c=sqrt(pow(p3.location().x()-p1.location().x(),2)+pow(p3.location().y()-p1.location().y(),2));
02685         s=(a+b+c)/2;
02686         result=(a*b*c)/(4*sqrt(s*(s-a)*(s-b)*(s-c)));
02687         return result;
02688 }
02689 
02690 bool TeGenerateArc(TePoint& p1, TePoint& p2, TePoint& p3, TeLine2D& arcOut, const short& NPoints)
02691 {       
02692         TePoint center;
02693         double radius;
02694 
02695         if(!TeGetCenter(p1, p2, p3, center))
02696                 return false;
02697 
02698         radius = TeGetRadius(p1, p2, p3);
02699 
02700         //calculate the distance between the points p1 and p3
02701         double length = TeDistance(p1.location(),p3.location());
02702 
02703         double val = length/(2*radius);
02704         if(val>1)
02705                 return false;
02706 
02707         //calculate the angle (in radians) between the segments (p1 - p3) in the circle center 
02708         //asin : arco seno
02709         //http://mathforum.org/dr.math/faq/faq.circle.segment.html#7
02710         double thetaR = 2 * asin(val);  
02711         
02712         //calculate the variation of the angle in radians for each point
02713         double deltaR = thetaR/(NPoints+1); 
02714 
02715         //verify if is counterclockwise or clockwise
02716         TeLine2D line;
02717         line.add(p1.location());
02718         line.add(p2.location());
02719         line.add(p3.location());
02720         line.add(p1.location());
02721         TeLinearRing ring(line);
02722         
02723         short orient = TeOrientation(ring);
02724 
02725         //calculate the coseno e seno of the angle (beta) between the circle center (horizontal segment) and the first point  
02726         //http://mathforum.org/library/drmath/view/55327.html
02727         double cosBeta = (p1.location().x()-center.location().x())/radius; 
02728         double sinBeta = (p1.location().y()-center.location().y())/radius;
02729 
02730         //rela�es trigonom�ricas
02731         //sin(x+y) = sin(x)cos(y) + cos(x)sin(y),
02732     //cos(x+y) = cos(x)cos(y) - sin(x)sin(y),
02733         //sin(x-y) = sin(x)cos(y) - cos(x)sin(y),
02734         //cos(x-y) = cos(x)cos(y) + sin(x)sin(y),
02735 
02736         arcOut.add(p1.location());
02737         double angle = deltaR;
02738         for (int i=0; i<(NPoints+1); i++)
02739         {
02740                 double x = 0.,y = 0.;
02741                 if(orient==TeCOUNTERCLOCKWISE)
02742                 {
02743                         //c = h + r*cos(B+A),
02744                         //d = k + r*sin(B+A),
02745                         x = center.location().x() + radius * ((cosBeta*cos(angle))-(sinBeta*sin(angle))); //cos(beta+angle) 
02746                         y = center.location().y() + radius * ((sinBeta*cos(angle))+(cosBeta*sin(angle))); //sin(beta+angle)
02747                 }
02748                 else if (orient==TeCLOCKWISE)
02749                 {
02750                         //c = h + r*cos(B-A),
02751                         //d = k + r*sin(B-A),
02752                         x = center.location().x() + radius * ((cosBeta*cos(angle))+(sinBeta*sin(angle))); //cos(beta-angle)
02753                         y = center.location().y() + radius * ((sinBeta*cos(angle))-(cosBeta*sin(angle))); //sin(beta-angle)
02754                 }
02755 
02756                 TeCoord2D coord(x,y);
02757                 arcOut.add(coord);
02758                 angle += deltaR;
02759         }
02760         arcOut.add(p3.location());
02761         return true;
02762 }
02763 
02764 bool TeGenerateCircle(const TePoint& center, const double& radius, TeLine2D& circle, const short& NPoints)
02765 {
02766         //angle (in radians) of the circumference (2*Pi)
02767         double thetaR = 2 * 3.14159;    
02768         
02769         //calculate the variation of the angle in radians for each point
02770         double deltaR = thetaR/(NPoints+1); 
02771 
02772         //calculate a point P1 of the  circumference
02773         TePoint p1(center.location().x()+radius, center.location().y());
02774         
02775         //calculate the coseno e seno of the angle (beta) between the center and the point P1  
02776         //http://mathforum.org/library/drmath/view/55327.html
02777         double cosBeta = 1;
02778         double sinBeta = 0;
02779 
02780         //rela�es trigonom�ricas
02781         //sin(x+y) = sin(x)cos(y) + cos(x)sin(y),
02782     //cos(x+y) = cos(x)cos(y) - sin(x)sin(y),
02783         //sin(x-y) = sin(x)cos(y) - cos(x)sin(y),
02784         //cos(x-y) = cos(x)cos(y) + sin(x)sin(y),
02785 
02786         circle.add(p1.location());
02787         double angle = deltaR;
02788         for (int i=0; i<(NPoints+1); i++)
02789         {
02790                 double x,y;
02791                 
02792                 //TeCOUNTERCLOCKWISE
02793                 //c = h + r*cos(B+A),
02794                 //d = k + r*sin(B+A),
02795                 
02796                 x = center.location().x() + radius * ((cosBeta*cos(angle))-(sinBeta*sin(angle))); //cos(beta+angle) 
02797                 y = center.location().y() + radius * ((sinBeta*cos(angle))+(cosBeta*sin(angle))); //sin(beta+angle)
02798                 
02799                 TeCoord2D coord(x,y);
02800                 circle.add(coord);
02801                 angle += deltaR;
02802         }
02803         circle.add(p1.location());
02804         return true;
02805 }
02806 
02807 double TeGetPrecision(TeProjection* proj)
02808 {
02809         if(!proj)
02810                 return 0.000000001;
02811 
02812         if(proj->units() == "Meters")
02813         {
02814                 return 0.001;
02815         }
02816         
02817         return 0.000000001;     // Lat/Long e NoProjection
02818 }
02819 
02820 //------------------------- Edition ---------------------------------------------//
02821 
02822 bool TeAdjustSegment(TeCoord2D P0, TeCoord2D P1, double d0, TeCoord2D &P0out, TeCoord2D &P1out)
02823 {
02824         double          vL_norm1;
02825         double          vL_norm2;
02826 
02827         try
02828         {
02829                 if( P0 == P1 )  return false;
02830                 
02831                 TeCoord2D vL1( (P1.x() - P0.x()), (P1.y() - P0.y()) );
02832                 TeCoord2D vL2( -1 * (P1.x() - P0.x()), -1 * (P1.y() - P0.y()) );
02833                 vL_norm1 = sqrt( vL1.x() * vL1.x() + vL1.y() * vL1.y() );
02834                 vL_norm2 = sqrt( vL2.x() * vL2.x() + vL2.y() * vL2.y() );
02835 
02836 
02837                 TeCoord2D uL1( ( vL1.x() / vL_norm1 ), ( vL1.y() / vL_norm1 ) );
02838                 TeCoord2D uL2( ( vL2.x() / vL_norm2 ), ( vL2.y() / vL_norm2 ) );
02839                 TeCoord2D pFim1 (P0.x() + uL1.x() * d0, P0.y() + uL1.y() * d0);
02840                 TeCoord2D pFim2 (P0.x() + uL2.x() * d0, P0.y() + uL2.y() * d0);
02841 
02842                 if ( TeDistance(pFim1, P1) <= TeDistance(pFim2, P1) )
02843                         {
02844                                 P0out = P0;
02845                                 P1out = pFim1; 
02846                         }
02847                 else
02848                         {
02849                                 P0out = P0;
02850                                 P1out = pFim2;
02851                         }
02852         }
02853         catch(...)
02854         { 
02855                 return (false); 
02856         }
02857         return (true);
02858 }
02859 
02860 bool TeFindCentroid(const TeLine2D &line, TeCoord2D &p)
02861 {
02862 
02863         double          iDistance;
02864         float           fMiddle=0.;
02865         float           fSize=0.;
02866         int                     iCont=0;
02867         TeLine2D        lneResult;
02868 
02869 
02870         iDistance=TeLength(line);
02871         if(iDistance<=0)
02872                 {
02873                         p=line[0];
02874                         return false;
02875                 }
02876 
02877         fMiddle=(float)(((float) iDistance)/2.);
02878 
02879         while(fSize<fMiddle)
02880                 {
02881                         lneResult.add(line[iCont]);
02882                         iCont++;
02883                         if(lneResult.size()>1)
02884                                 fSize=(float)TeLength(lneResult);
02885                 }
02886 
02887         if(fSize>fMiddle)
02888                 {
02889                         double                  dDistance=0;
02890                         TeCoord2D               coorP1,coorP2;
02891 
02892                         dDistance=TeDistance(lneResult[lneResult.size()-2],lneResult[lneResult.size()-1]);
02893 
02894                         dDistance-=(fSize-fMiddle);
02895 
02896                         TeAdjustSegment(lneResult[lneResult.size()-2],lneResult[lneResult.size()-1],dDistance,coorP1,coorP2);
02897                         p=coorP2;
02898                         
02899                 }
02900         else
02901                 p=lneResult[lneResult.size()-1];
02902                 
02903         return true;
02904 }
02905 
02906 

Generated on Sun Jul 29 04:01:21 2012 for TerraLib - Development Source by  doxygen 1.5.3