OsmAnd
jni/osmand/multipolygons.h
Go to the documentation of this file.
00001 
00002 #include <android/log.h>
00003 #include <stdio.h>
00004 #include <map>
00005 #include <set>
00006 #include <hash_map>
00007 
00008 
00009 #include "renderRules.h"
00010 #include "common.h"
00011 #include "mapObjects.h"
00012 
00013 #define INT_MAX         0x7fffffff      /* max value for an int */
00014 #define INT_MIN         (-0x7fffffff-1) /* min value for an int */
00015 
00016 char textMsg[1024] ;
00017 struct tagValueType {
00018         int type;
00019         std::string tag;
00020         std::string value;
00021 
00022         tagValueType(tag_value t, int type) : type(type) {
00023                 tag = t.first;
00024                 value = t.second;
00025         }
00026 
00027 };
00028 bool operator==(const tagValueType& __x, const tagValueType& __y) {
00029         return __x.type == __y.type;
00030 }
00031 bool operator<(const tagValueType& __x, const tagValueType& __y) {
00032         return __x.type < __y.type;
00033 }
00035 bool isClockwiseWay(std::vector<int_pair>& c) ;
00036 bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
00037                 int bottomY, int topY, std::vector<int_pair>& coordinates);
00038 
00039 void processMultipolygonLine(std::vector<std::vector<int_pair> >& completedRings, std::vector<std::vector<int_pair> >& incompletedRings,
00040                         std::vector<std::string> &completedRingsNames, std::vector<std::string> &incompletedRingsNames, std::vector<int_pair> & coordinates, std::string name);
00041 
00042 void unifyIncompletedRings(std::vector<std::vector<int_pair> >& incompletedRings, std::vector<std::vector<int_pair> >& completedRings, std::vector<std::string> &completedRingNames,
00043                         std::vector<std::string> &incompletedRingNames, int leftX, int rightX, int bottomY, int topY, long dbId, int zoom);
00044 
00045 MultiPolygonObject* processMultiPolygon(int leftX, int rightX, int bottomY, int topY,
00046                 std::vector<std::vector<int_pair > >& completedRings, std::vector<std::vector<int_pair> >& incompletedRings,
00047                 std::vector<std::string>& completedRingNames, std::vector<std::string>& incompletedRingNames,
00048                 const tagValueType&  type, std::vector<MapDataObject* > & directList, std::vector<MapDataObject*>& inverselist,
00049                 int zoom) {
00050         MultiPolygonObject* pl = new MultiPolygonObject();
00051         // delete direction last bit (to not show point)
00052         pl->tag = type.tag;
00053         pl->value = type.value;
00054         pl->layer = getNegativeWayLayer(type.type);
00055         long long dbId = 0;
00056         for (int km = 0; km < 2; km++) {
00057                 std::vector<MapDataObject* >::iterator o = (km == 0 ? directList.begin() : inverselist.begin());
00058                 std::vector<MapDataObject* >::iterator oEnd = (km == 0 ? directList.end() : inverselist.end());
00059                 for (; o != oEnd; o++) {
00060                         int len = (*o)->points.size();
00061                         if (len < 2) {
00062                                 continue;
00063                         }
00064                         dbId = (*o)->id >> 1;
00065                         std::vector<int_pair> coordinates;
00066                         int_pair p = (*o)->points.at(km == 0 ? 0 : len - 1);
00067                         int px = p.first;
00068                         int py = p.second;
00069                         int x = p.first;
00070                         int y = p.second;
00071                         bool pinside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
00072                         if (pinside) {
00073                                 coordinates.push_back(int_pair(x, y));
00074                         }
00075                         for (int i = 1; i < len; i++) {
00076                                 int_pair cp = (*o)->points.at(km == 0 ? i : len - i - 1);
00077                                 x = cp.first;
00078                                 y = cp.second;
00079                                 bool inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
00080                                 bool lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY,
00081                                                 coordinates);
00082                                 if (lineEnded) {
00083                                         processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames,
00084                                                         coordinates, (*o)->name);
00085                                         // create new line if it goes outside
00086                                         coordinates.clear();
00087                                 }
00088                                 px = x;
00089                                 py = y;
00090                                 pinside = inside;
00091                         }
00092                         processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames,
00093                                         coordinates, (*o)->name);
00094                 }
00095         }
00096         if (completedRings.size() == 0 && incompletedRings.size() == 0) {
00097                 return NULL;
00098         }
00099         if (incompletedRings.size() > 0) {
00100                 unifyIncompletedRings(incompletedRings, completedRings, completedRingNames, incompletedRingNames, leftX, rightX,
00101                                 bottomY, topY, dbId, zoom);
00102         } else {
00103                 // due to self intersection small objects (for low zooms check only coastline)
00104                 if (zoom >= 13 || ("natural" == type.tag && "coastline" == type.value)) {
00105                         bool clockwiseFound = false;
00106                         std::vector<std::vector<int_pair> > ::iterator c = completedRings.begin();
00107                         for (; c != completedRings.end(); c++) {
00108                                 if (isClockwiseWay(*c)) {
00109                                         clockwiseFound = true;
00110                                         break;
00111                                 }
00112                         }
00113                         if (!clockwiseFound) {
00114                                 // add whole bound
00115                                 std::vector<int_pair> whole;
00116                                 whole.push_back(int_pair(leftX, topY));
00117                                 whole.push_back(int_pair(rightX, topY));
00118                                 whole.push_back(int_pair(leftX, bottomY));
00119                                 whole.push_back(int_pair(rightX, bottomY));
00120                                 completedRings.push_back(whole);
00121                                 __android_log_print(ANDROID_LOG_INFO, "net.osmand", "!!! Isolated island !!!");
00122                         }
00123 
00124                 }
00125         }
00126 
00127         pl->names = completedRingNames;
00128         pl->points = completedRings;
00129         return pl;
00130 }
00131 
00132 static std::vector<MapDataObject*> EMPTY_LIST;
00133 void proccessMultiPolygons(std::map<tagValueType, std::vector<MapDataObject*> >& multyPolygons, int leftX,
00134                 int rightX, int bottomY, int topY, int zoom, std::vector<BaseMapDataObject*>& listPolygons) {
00135         std::vector<std::vector<int_pair> > completedRings;
00136         std::vector<std::vector<int_pair> > incompletedRings;
00137         std::vector<std::string> completedRingNames;
00138         std::vector<std::string> incompletedRingNames;
00139         std::map<tagValueType, std::vector<MapDataObject*> >::iterator val = multyPolygons.begin();
00140         for (; val != multyPolygons.end(); val++) {
00141                 std::vector<MapDataObject*>* directList;
00142                 std::vector<MapDataObject*>* inverselist;
00143                 if (((val->first.type >> 15) & 1) == 1) {
00144                         tagValueType directType = val->first;
00145                         directType.type = val->first.type & ((1 << 15) - 1);
00146                         if (multyPolygons.find(directType) == multyPolygons.end()) {
00147                                 inverselist = &val->second;
00148                                 directList = &EMPTY_LIST;
00149                         } else {
00150                                 // continue on inner boundaries
00151                                 continue;
00152                         }
00153                 } else {
00154                         tagValueType inverseType = val->first;
00155                         inverseType.type = val->first.type | (1 << 15);
00156                         directList = &val->second;
00157                         inverselist = &multyPolygons[inverseType];
00158                 }
00159                 completedRings.clear();
00160                 incompletedRings.clear();
00161                 completedRingNames.clear();
00162                 incompletedRingNames.clear();
00163 
00164                 sprintf(textMsg, "Process multipolygon %s %s direct list %d rev %d", val->first.tag.c_str(), val->first.value.c_str(), directList->size(), inverselist->size());
00165                 __android_log_print(ANDROID_LOG_INFO, "net.osmand", textMsg);
00166                 MultiPolygonObject* pl = processMultiPolygon(leftX, rightX, bottomY, topY, completedRings, incompletedRings,
00167                                 completedRingNames, incompletedRingNames, val->first, *directList, *inverselist, zoom);
00168                 if (pl != NULL) {
00169                         listPolygons.push_back(pl);
00170                 } else {
00171                         __android_log_print(ANDROID_LOG_INFO, "net.osmand", "Multipolygon skipped");
00172                 }
00173         }
00174 }
00175 
00176 // Copied from MapAlgorithms
00177 int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) {
00178         // prev node above line
00179         // x,y node below line
00180         if (prevY > y) {
00181                 int tx = prevX;
00182                 int ty = prevY;
00183                 x = prevX;
00184                 y = prevY;
00185                 prevX = tx;
00186                 prevY = ty;
00187         }
00188         if (y == middleY || prevY == middleY) {
00189                 middleY -= 1;
00190         }
00191         if (prevY > middleY || y < middleY) {
00192                 return INT_MIN;
00193         } else {
00194                 if (y == prevY) {
00195                         // the node on the boundary !!!
00196                         return x;
00197                 }
00198                 // that tested on all cases (left/right)
00199                 double rx = x + ((double) middleY - y) * ((double) x - prevX) / (((double) y - prevY));
00200                 return (int) rx;
00201         }
00202 }
00203 
00204 // Copied from MapAlgorithms
00205 bool isClockwiseWay(std::vector<int_pair>& c) {
00206         if (c.size() == 0) {
00207                 return true;
00208         }
00209 
00210         // calculate middle Y
00211         long middleY = 0;
00212         for (size_t i = 0; i < c.size(); i++) {
00213                 middleY += c.at(i).second;
00214         }
00215         middleY /= (long) c.size();
00216 
00217         double clockwiseSum = 0;
00218 
00219         bool firstDirectionUp = false;
00220         int previousX = INT_MIN;
00221         int firstX = INT_MIN;
00222 
00223         int prevX = c.at(0).first;
00224         int prevY = c.at(0).second;
00225 
00226         for (size_t i = 1; i < c.size(); i++) {
00227                 int x = c.at(i).first;
00228                 int y = c.at(i).second;
00229                 int rX = ray_intersect_x(prevX, prevY, x, y, (int) middleY);
00230                 if (rX != INT_MIN) {
00231                         bool skipSameSide = (y <= middleY) == (prevY <= middleY);
00232                         if (skipSameSide) {
00233                                 continue;
00234                         }
00235                         bool directionUp = prevY >= middleY;
00236                         if (firstX == INT_MIN) {
00237                                 firstDirectionUp = directionUp;
00238                                 firstX = rX;
00239                         } else {
00240                                 bool clockwise = (!directionUp) == (previousX < rX);
00241                                 if (clockwise) {
00242                                         clockwiseSum += abs(previousX - rX);
00243                                 } else {
00244                                         clockwiseSum -= abs(previousX - rX);
00245                                 }
00246                         }
00247                         previousX = rX;
00248                         prevX = x;
00249                         prevY = y;
00250                 }
00251         }
00252 
00253         if (firstX != INT_MIN) {
00254                 bool clockwise = (!firstDirectionUp) == (previousX < firstX);
00255                 if (clockwise) {
00256                         clockwiseSum += abs(previousX - firstX);
00257                 } else {
00258                         clockwiseSum -= abs(previousX - firstX);
00259                 }
00260         }
00261 
00262         return clockwiseSum >= 0;
00263 }
00264 
00265 
00266 
00267 void processMultipolygonLine(std::vector<std::vector<int_pair> >& completedRings, std::vector<std::vector<int_pair> >& incompletedRings,
00268                         std::vector<std::string> &completedRingsNames,
00269                 std::vector<std::string> &incompletedRingsNames, std::vector<int_pair> & coordinates, std::string name) {
00270         if (coordinates.size() > 0) {
00271                 if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
00272                         completedRings.push_back(coordinates);
00273                         completedRingsNames.push_back(name);
00274                 } else {
00275                         bool add = true;
00276                         for (size_t k = 0; k < incompletedRings.size();) {
00277                                 bool remove = false;
00278                                 std::vector<int_pair> i = incompletedRings.at(k);
00279                                 std::string oldName = incompletedRingsNames.at(k);
00280                                 if (coordinates.at(0) == i.at(i.size() - 1)) {
00281                                         std::vector<int_pair>::iterator tit =  coordinates.begin();
00282                                         i.insert(i.end(), ++tit, coordinates.end());
00283                                         remove = true;
00284                                         coordinates = i;
00285                                 } else if (coordinates.at(coordinates.size() - 1) == i.at(0)) {
00286                                         std::vector<int_pair>::iterator tit =  i.begin();
00287                                         coordinates.insert(coordinates.end(), ++tit, i.end());
00288                                         remove = true;
00289                                 }
00290                                 if (remove) {
00291                                         std::vector<std::vector<int_pair> >::iterator ti = incompletedRings.begin();
00292                                         ti += k;
00293                                         incompletedRings.erase(ti);
00294                                         std::vector<std::string> :: iterator tis = incompletedRingsNames.begin();
00295                                         tis += k;
00296                                         incompletedRingsNames.erase(tis);
00297                                 } else {
00298                                         k++;
00299                                 }
00300                                 if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
00301                                         completedRings.push_back(coordinates);
00302                                         if (oldName.length() > 0) {
00303                                                 completedRingsNames.push_back(oldName);
00304                                         } else {
00305                                                 completedRingsNames.push_back(name);
00306                                         }
00307                                         add = false;
00308                                         break;
00309                                 }
00310                         }
00311                         if (add) {
00312                                 incompletedRings.push_back(coordinates);
00313                                 incompletedRingsNames.push_back(name);
00314                         }
00315                 }
00316         }
00317 }
00318 
00319 int safelyAddDelta(int number, int delta) {
00320         int res = number + delta;
00321         if (delta > 0 && res < number) {
00322                 return INT_MAX;
00323         } else if (delta < 0 && res > number) {
00324                 return INT_MIN;
00325         }
00326         return res;
00327 }
00328 
00329 void unifyIncompletedRings(std::vector<std::vector<int_pair> >& incompletedRings, std::vector<std::vector<int_pair> >& completedRings,
00330                 std::vector<std::string> &completedRingNames, std::vector<std::string> & incompletedRingsNames,
00331                 int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
00332         std::set<int> nonvisitedRings;
00333         std::vector<std::vector<int_pair> >::iterator ir = incompletedRings.begin();
00334         std::vector<std::string>::iterator irs = incompletedRingsNames.begin();
00335         int j = 0;
00336         for (j = 0; ir != incompletedRings.end(); ir++, irs++, j++) {
00337                 int x = ir->at(0).first;
00338                 int y = ir->at(0).second;
00339                 int sx = ir->at(ir->size() - 1).first;
00340                 int sy = ir->at(ir->size() - 1).second;
00341                 bool st = y == topY || x == rightX || y == bottomY || x == leftX;
00342                 bool end = sy == topY || sx == rightX || sy == bottomY || sx == leftX;
00343                 // something goes wrong
00344                 // These exceptions are used to check logic about processing multipolygons
00345                 // However this situation could happen because of broken multipolygons (so it should data causes app error)
00346                 // that's why these exceptions could be replaced with return; statement.
00347                 if (!end || !st) {
00348                         // TODO message
00349 //                              float dx = (float) MapUtils.get31LongitudeX(x);
00350 //                              float dsx = (float) MapUtils.get31LongitudeX(sx);
00351 //                              float dy = (float) MapUtils.get31LatitudeY(y);
00352 //                              float dsy = (float) MapUtils.get31LatitudeY(sy);
00353 //                              String str;
00354 //                              if (!end) {
00355 //                                      str = " Start point (to close) not found : end_x = {0}, end_y = {1}, start_x = {2}, start_y = {3} : bounds {4} {5} - {6} {7}"; //$NON-NLS-1$
00356 //                                      System.err
00357 //                                                      .println(MessageFormat.format(dbId + str, dx, dy, dsx, dsy, leftX + "", topY + "", rightX + "", bottomY + "")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
00358 //                              }
00359 //                              if (!st) {
00360 //                                      str = " End not found : end_x = {0}, end_y = {1}, start_x = {2}, start_y = {3} : bounds {4} {5} - {6} {7}"; //$NON-NLS-1$
00361 //                                      System.err
00362 //                                                      .println(MessageFormat.format(dbId + str, dx, dy, dsx, dsy, leftX + "", topY + "", rightX + "", bottomY + "")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
00363 //                              }
00364                         __android_log_print(ANDROID_LOG_INFO, "net.osmand", "Error processing multipolygon");
00365                 } else {
00366                         nonvisitedRings.insert(j);
00367                 }
00368         }
00369         ir = incompletedRings.begin();
00370         irs = incompletedRingsNames.begin();
00371         for (j = 0; ir != incompletedRings.end(); ir++, irs++, j++) {
00372                 if (nonvisitedRings.find(j) == nonvisitedRings.end()) {
00373                         continue;
00374                 }
00375                 int x = ir->at(ir->size() - 1).first;
00376                 int y = ir->at(ir->size() - 1).second;
00377                 // 31 - (zoom + 8)
00378                 const int EVAL_DELTA = 6 << (23 - zoom);
00379                 const int UNDEFINED_MIN_DIFF = -1 - EVAL_DELTA;
00380                 while (true) {
00381                         int st = 0; // st already checked to be one of the four
00382                         if (y == topY) {
00383                                 st = 0;
00384                         } else if (x == rightX) {
00385                                 st = 1;
00386                         } else if (y == bottomY) {
00387                                 st = 2;
00388                         } else if (x == leftX) {
00389                                 st = 3;
00390                         }
00391                         int nextRingIndex = -1;
00392                         // BEGIN go clockwise around rectangle
00393                         for (int h = st; h < st + 4; h++) {
00394 
00395                                 // BEGIN find closest nonvisited start (including current)
00396                                 int mindiff = UNDEFINED_MIN_DIFF;
00397                                 std::vector<std::vector<int_pair> >::iterator cni = incompletedRings.begin();
00398                                 int cnik = 0;
00399                                 for (;cni != incompletedRings.end(); cni++, cnik ++) {
00400                                         if (nonvisitedRings.find(cnik) == nonvisitedRings.end()) {
00401                                                 continue;
00402                                         }
00403                                         int csx = cni->at(0).first;
00404                                         int csy = cni->at(0).second;
00405                                         if (h % 4 == 0) {
00406                                                 // top
00407                                                 if (csy == topY && csx >= safelyAddDelta(x, -EVAL_DELTA)) {
00408                                                         if (mindiff == UNDEFINED_MIN_DIFF || (csx - x) <= mindiff) {
00409                                                                 mindiff = (csx - x);
00410                                                                 nextRingIndex = cnik;
00411                                                         }
00412                                                 }
00413                                         } else if (h % 4 == 1) {
00414                                                 // right
00415                                                 if (csx == rightX && csy >= safelyAddDelta(y, -EVAL_DELTA)) {
00416                                                         if (mindiff == UNDEFINED_MIN_DIFF || (csy - y) <= mindiff) {
00417                                                                 mindiff = (csy - y);
00418                                                                 nextRingIndex = cnik;
00419                                                         }
00420                                                 }
00421                                         } else if (h % 4 == 2) {
00422                                                 // bottom
00423                                                 if (csy == bottomY && csx <= safelyAddDelta(x, EVAL_DELTA)) {
00424                                                         if (mindiff == UNDEFINED_MIN_DIFF || (x - csx) <= mindiff) {
00425                                                                 mindiff = (x - csx);
00426                                                                 nextRingIndex = cnik;
00427                                                         }
00428                                                 }
00429                                         } else if (h % 4 == 3) {
00430                                                 // left
00431                                                 if (csx == leftX && csy <= safelyAddDelta(y, EVAL_DELTA)) {
00432                                                         if (mindiff == UNDEFINED_MIN_DIFF || (y - csy) <= mindiff) {
00433                                                                 mindiff = (y - csy);
00434                                                                 nextRingIndex = cnik;
00435                                                         }
00436                                                 }
00437                                         }
00438                                 } // END find closest start (including current)
00439 
00440                                 // we found start point
00441                                 if (mindiff != UNDEFINED_MIN_DIFF) {
00442                                         break;
00443                                 } else {
00444                                         if (h % 4 == 0) {
00445                                                 // top
00446                                                 y = topY;
00447                                                 x = rightX;
00448                                         } else if (h % 4 == 1) {
00449                                                 // right
00450                                                 y = bottomY;
00451                                                 x = rightX;
00452                                         } else if (h % 4 == 2) {
00453                                                 // bottom
00454                                                 y = bottomY;
00455                                                 x = leftX;
00456                                         } else if (h % 4 == 3) {
00457                                                 y = topY;
00458                                                 x = leftX;
00459                                         }
00460                                         ir->push_back(int_pair(x, y));
00461                                 }
00462 
00463                         } // END go clockwise around rectangle
00464                         if (nextRingIndex == -1) {
00465                                 // it is impossible (current start should always be found)
00466                         } else if (nextRingIndex == j) {
00467                                 ir->push_back(ir->at(0));
00468                                 nonvisitedRings.erase(j);
00469                                 break;
00470                         } else {
00471                                 std::vector<int_pair> p = incompletedRings.at(nextRingIndex);
00472                                 ir->insert(ir->end(), p.begin(), p.end());
00473                                 nonvisitedRings.erase(nextRingIndex);
00474                                 // get last point and start again going clockwise
00475                                 x = ir->at(ir->size() - 1).first;
00476                                 y = ir->at(ir->size() - 1).second;
00477                         }
00478                 }
00479 
00480                 completedRings.push_back(*ir);
00481                 completedRingNames.push_back(*irs);
00482         }
00483 
00484 }
00485 
00486 
00487 
00491 bool calculateIntersection(int x, int y, int px, int py, int leftX, int rightX, int bottomY, int topY, int_pair& b) {
00492         // firstly try to search if the line goes in
00493         if (py < topY && y >= topY) {
00494                 int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
00495                 if (leftX <= tx && tx <= rightX) {
00496                         b.first = tx;
00497                         b.second = topY;
00498                         return true;
00499                 }
00500         }
00501         if (py > bottomY && y <= bottomY) {
00502                 int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
00503                 if (leftX <= tx && tx <= rightX) {
00504                         b.first = tx;
00505                         b.second = bottomY;
00506                         return true;
00507                 }
00508         }
00509         if (px < leftX && x >= leftX) {
00510                 int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
00511                 if (ty >= topY && ty <= bottomY) {
00512                         b.first = leftX;
00513                         b.second = ty;
00514                         return true;
00515                 }
00516 
00517         }
00518         if (px > rightX && x <= rightX) {
00519                 int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
00520                 if (ty >= topY && ty <= bottomY) {
00521                         b.first = rightX;
00522                         b.second = ty;
00523                         return true;
00524                 }
00525 
00526         }
00527 
00528         // try to search if point goes out
00529         if (py > topY && y <= topY) {
00530                 int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
00531                 if (leftX <= tx && tx <= rightX) {
00532                         b.first = tx;
00533                         b.second = topY;
00534                         return true;
00535                 }
00536         }
00537         if (py < bottomY && y >= bottomY) {
00538                 int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
00539                 if (leftX <= tx && tx <= rightX) {
00540                         b.first = tx;
00541                         b.second = bottomY;
00542                         return true;
00543                 }
00544         }
00545         if (px > leftX && x <= leftX) {
00546                 int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
00547                 if (ty >= topY && ty <= bottomY) {
00548                         b.first = leftX;
00549                         b.second = ty;
00550                         return true;
00551                 }
00552 
00553         }
00554         if (px < rightX && x >= rightX) {
00555                 int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
00556                 if (ty >= topY && ty <= bottomY) {
00557                         b.first = rightX;
00558                         b.second = ty;
00559                         return true;
00560                 }
00561 
00562         }
00563 
00564         if (px == rightX || px == leftX || py == topY || py == bottomY) {
00565                 b.first = px;
00566                 b.second = py;
00567 //              return true;
00568                 // Is it right? to not return anything?
00569         }
00570         return false;
00571 }
00572 
00573 bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
00574                 int bottomY, int topY, std::vector<int_pair>& coordinates) {
00575         bool lineEnded = false;
00576         int_pair b(x, y);
00577         if (pinside) {
00578                 if (!inside) {
00579                         bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
00580                         if (!is) {
00581                                 b.first = px;
00582                                 b.second = py;
00583                         }
00584                         coordinates.push_back(b);
00585                         lineEnded = true;
00586                 } else {
00587                         coordinates.push_back(b);
00588                 }
00589         } else {
00590                 bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
00591                 if (inside) {
00592                         // assert is != -1;
00593                         coordinates.push_back(b);
00594                         int_pair n(x, y);
00595                         coordinates.push_back(n);
00596                 } else if (is) {
00597                         coordinates.push_back(b);
00598                         calculateIntersection(x, y, b.first, b.second, leftX, rightX, bottomY, topY, b);
00599                         coordinates.push_back(b);
00600                         lineEnded = true;
00601                 }
00602         }
00603 
00604         return lineEnded;
00605 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines