Example #1
0
/*!
  \brief Add linestring to a ring (private)

  \param[in,out] papoRing list of rings
  \param poLine pointer to linestring to be added to a ring 

  \return TRUE on success
  \return FALSE on failure
*/
bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineString *poLine, bool bNewRing)
{
    OGRPoint *poFirst, *poLast;
    OGRPoint *poFirstNew, *poLastNew;

    OGRPoint  pt;
    PointList poList;

    /* OGRLineString -> PointList */
    for (int i = 0; i < poLine->getNumPoints(); i++) {
        poLine->getPoint(i, &pt);
        poList.push_back(pt);
    }

    /* create new ring */
    if (bNewRing) {
        papoRing->push_back(new PointList(poList));
        return TRUE;
    }
    
    poFirstNew = &(poList.front());
    poLastNew  = &(poList.back());
    for (PointListArray::const_iterator i = papoRing->begin(), e = papoRing->end();
         i != e; ++i) {
        PointList *ring = (*i);
        poFirst = &(ring->front());
        poLast  = &(ring->back());
        if (!poFirst || !poLast || poLine->getNumPoints() < 2)
            return FALSE;

        if (poFirstNew->Equals(poLast)) {
            /* forward, skip first point */
            ring->insert(ring->end(), poList.begin()+1, poList.end());
            return TRUE;
        }
        
        if (poFirstNew->Equals(poFirst)) {
            /* backward, skip last point */
            ring->insert(ring->begin(), poList.rbegin(), poList.rend()-1);
            return TRUE;
        }
        
        if (poLastNew->Equals(poLast)) {
            /* backward, skip first point */
            ring->insert(ring->end(), poList.rbegin()+1, poList.rend());
            return TRUE;
        }
        
        if (poLastNew->Equals(poFirst)) {
            /* forward, skip last point */
            ring->insert(ring->begin(), poList.begin(), poList.end()-1);
            return TRUE;
        }
    }

    return FALSE;
}
Example #2
0
PointList buildPolygon(Site_2 site, std::vector<PointList>& polylines)
{
    // A list for the resulting points.
    PointList points;
    // We build this list from the polylines collected before.
    // One of the problems solved here is that we actually don't know
    // whether the polylines we get are in order or reversed because of the
    // way we obtained them via Hyperbola_2.generate_points which makes no
    // guarantees about the order of produces points. So we check at each
    // step whether a consecutive polyline has to be added in-order or
    // reversed by inspecting the first and last points respectively. A
    // special case is the first polyline, where we don't have a previous
    // polyline to perform this check for, which is why we make a more
    // extensive checking when adding the second polyline which also takes
    // care about the first.
    std::cerr << "# polylines: " << polylines.size() << std::endl;
    // the first polyline will just be added as it is
    if (polylines.size() > 0) {
      PointList seg = polylines.front();
      points.insert(points.end(), seg.begin(), seg.end());
    }
    // handle consecutive polylines
    if (polylines.size() > 1) {
      // check wheter we can use the second segment this way or whether we
      // have to reverse the first polyline. Use distance comparism to pick
      // the best fit (so that we don't need exact equivalence of endpoints)
      PointList seg = polylines.at(1);
      double d1 = CGAL::squared_distance(points.front(), seg.front());
      double d2 = CGAL::squared_distance(points.front(), seg.back());
      double d3 = CGAL::squared_distance(points.back(), seg.front());
      double d4 = CGAL::squared_distance(points.back(), seg.back());
      // if the first point of the first polyline fits both endpoints of the
      // second polyline better thant the last point of the first polyline,
      // then we reverse the order of the first polyline.
      if ((d1 < d3 && d1 < d4) || (d2 < d3 && d2 < d4)) {
        std::reverse(points.begin(), points.end());
      }
      // for each consecutive polyline
      for (int i = 1; i < polylines.size(); i++) {
        // check which endpoint of this polyline is nearest to the last
        // point in our list of points.
        Point_2 lastPoint = points.back();
        PointList seg = polylines.at(i);
        double d1 = CGAL::squared_distance(lastPoint, seg.front());
        double d2 = CGAL::squared_distance(lastPoint, seg.back());
        if (d1 <= d2) {
          // first point fits better, take polyline in default order
          points.insert(points.end(), ++seg.begin(), seg.end());
        } else {
          // last point fits better, take polyline in reverse order
          points.insert(points.end(), ++seg.rbegin(), seg.rend());
        }
      }
    }
    std::cerr << "# points: " << points.size() << std::endl;

    // close polygon if necessary
    if (points.size() > 0){
      Point_2 start = points.front();
      Point_2 end = points.back();
      if (start != end) {
        points.push_back(start);
      }
    }

    if (points.size() > 0 && points.size() < 4) {
      std::cerr << "invalid polygon: >0 but <4 points" << std::endl;
      points.clear();
    }

    return points;
}