in src/simulator/image_to_box2d.cpp [63:128]
void fillConvexPoly(const std::vector<Vector>& v, const T color,
Array2d<T>* array) {
struct Edge {
Vector start, end;
};
std::vector<Edge> leftEdges, rightEdges;
for (size_t i = 0; i < v.size(); ++i) {
size_t prev = i == 0 ? v.size() - 1 : i - 1;
if (std::abs(v[i].y - v[prev].y) < 1e-3) {
continue;
}
if (v[prev].y < v[i].y) {
Edge edge{v[prev], v[i]};
rightEdges.push_back(edge);
} else {
Edge edge{v[i], v[prev]};
leftEdges.push_back(edge);
}
}
const auto width = array->width;
const auto height = array->height;
if (leftEdges.empty() || rightEdges.empty()) return;
std::sort(leftEdges.begin(), leftEdges.end(),
[](const Edge& lhs, const Edge& rhs) {
return lhs.start.y < rhs.start.y;
});
std::sort(rightEdges.begin(), rightEdges.end(),
[](const Edge& lhs, const Edge& rhs) {
return lhs.start.y < rhs.start.y;
});
int leftActive = 0, rightActive = 0;
auto cmpY = [](const Vector& lhs, const Vector& rhs) {
return lhs.y < rhs.y;
};
const float polygonMinY = std::min_element(v.begin(), v.end(), cmpY)->y;
const float polygonMaxY = std::max_element(v.begin(), v.end(), cmpY)->y;
const int drawStartY = std::max<int>(0, std::lrint(polygonMinY));
const int drawEndY = std::min<int>(height, std::lrint(polygonMaxY));
auto getX = [](const Edge& edge, float y) {
const float alpha = (y - edge.start.y) / (edge.end.y - edge.start.y);
return alpha * (edge.end.x - edge.start.x) + edge.start.x;
};
for (int y = drawStartY; y < drawEndY; ++y) {
while (leftActive + 1 < leftEdges.size() &&
leftEdges[leftActive].end.y < y + 0.5)
++leftActive;
while (rightActive + 1 < rightEdges.size() &&
rightEdges[rightActive].end.y < y + 0.5)
++rightActive;
const float leftX = getX(leftEdges[leftActive], y + 0.5);
const float rightX = getX(rightEdges[rightActive], y + 0.5);
const int leftXInt = std::max<int>(0, std::lrint(leftX));
const int rightXInt = std::min<int>(width, std::lrint(rightX));
if (leftXInt < rightXInt) {
auto start = array->data + y * width;
std::fill(&start[leftXInt], &start[rightXInt], color);
}
}
}