Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, const Polygons &clip, bool safety_offset_) { // transform input polygons into polylines Polylines polylines; polylines.reserve(subject.size()); for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon) polylines.push_back(*polygon); // implicit call to split_at_first_point() // perform clipping Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_); /* If the split_at_first_point() call above happens to split the polygon inside the clipping area we would get two consecutive polylines instead of a single one, so we go through them in order to recombine continuous polylines. */ for (size_t i = 0; i < retval.size(); ++i) { for (size_t j = i+1; j < retval.size(); ++j) { if (retval[i].points.back().coincides_with(retval[j].points.front())) { /* If last point of i coincides with first point of j, append points of j to i and delete j */ retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.front().coincides_with(retval[j].points.back())) { /* If first point of i coincides with last point of j, prepend points of j to i and delete j */ retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.front().coincides_with(retval[j].points.front())) { /* Since Clipper does not preserve orientation of polylines, also check the case when first point of i coincides with first point of j. */ retval[j].reverse(); retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.back().coincides_with(retval[j].points.back())) { /* Since Clipper does not preserve orientation of polylines, also check the case when last point of i coincides with last point of j. */ retval[j].reverse(); retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); retval.erase(retval.begin() + j); --j; } } } return retval; }
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, bool safety_offset_) { // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) polylines.push_back(*line); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); // convert Polylines to Lines Lines retval; for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) retval.push_back(*polyline); return retval; }
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, bool safety_offset_) { // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); for (const Line &line : subject) polylines.emplace_back(Polyline(line.a, line.b)); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); // convert Polylines to Lines Lines retval; for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) retval.emplace_back(polyline->operator Line()); return retval; }