void build(utymap::meshing::Polygon& polygon) { ClipperLib::ClipperOffset offset; ClipperLib::Path path; path.reserve(polygon.points.size() / 2); auto lastPointIndex = polygon.points.size() - 2; double min = std::numeric_limits<double>::max(); for (std::size_t i = 0; i < polygon.points.size(); i += 2) { auto nextIndex = i == lastPointIndex ? 0 : i + 2; utymap::meshing::Vector2 v1(polygon.points[i], polygon.points[i + 1]); utymap::meshing::Vector2 v2(polygon.points[nextIndex], polygon.points[nextIndex + 1]); min = std::min(min, utymap::meshing::Vector2::distance(v1, v2)); path.push_back(ClipperLib::IntPoint(static_cast<ClipperLib::cInt>(v1.x * Scale), static_cast<ClipperLib::cInt>(v1.y * Scale))); } offset.AddPath(path, ClipperLib::JoinType::jtMiter, ClipperLib::EndType::etClosedPolygon); ClipperLib::Paths solution; // NOTE: use minimal side value as reference for offsetting. offset.Execute(solution, -(min / 10) * Scale); // NOTE: this is unexpected result for algorithm below, fallback to flat roof. if (solution.size() != 1 || solution[0].size() != path.size()) { return FlatRoofBuilder::build(polygon); } buildMansardShape(polygon, solution[0], findFirstIndex(solution[0][0], polygon)); }
static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) { ClipperLib::Path result; result.reserve(ring.size()); for (const auto& p : ring) { result.emplace_back(p.x, p.y); } return result; }
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input) { ClipperLib::Path output; output.reserve(input.points.size()); for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit) output.emplace_back((*pit)(0), (*pit)(1)); return output; }