FloatShapeInterval OffsetPolygonEdge::clippedEdgeXRange(float y1, float y2) const { if (!overlapsYRange(y1, y2) || (y1 == maxY() && minY() <= y1) || (y2 == minY() && maxY() >= y2)) return FloatShapeInterval(); if (isWithinYRange(y1, y2)) return FloatShapeInterval(minX(), maxX()); // Clip the edge line segment to the vertical range y1,y2 and then return // the clipped line segment's horizontal range. FloatPoint minYVertex; FloatPoint maxYVertex; if (vertex1().y() < vertex2().y()) { minYVertex = vertex1(); maxYVertex = vertex2(); } else { minYVertex = vertex2(); maxYVertex = vertex1(); } float xForY1 = (minYVertex.y() < y1) ? xIntercept(y1) : minYVertex.x(); float xForY2 = (maxYVertex.y() > y2) ? xIntercept(y2) : maxYVertex.x(); return FloatShapeInterval(std::min(xForY1, xForY2), std::max(xForY1, xForY2)); }
static FloatShapeInterval clippedCircleXRange(const FloatPoint& center, float radius, float y1, float y2) { if (y1 > center.y() + radius || y2 < center.y() - radius) return FloatShapeInterval(); if (center.y() >= y1 && center.y() <= y2) return FloatShapeInterval(center.x() - radius, center.x() + radius); // Clip the circle to the vertical range y1,y2 and return the extent of the clipped circle's // projection on the X axis float xi = circleXIntercept((y2 < center.y() ? y2 : y1) - center.y(), radius); return FloatShapeInterval(center.x() - xi, center.x() + xi); }
static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, float y1, float y2, FloatShapeIntervals& result) { Vector<const FloatPolygonEdge*> edges; if (!polygon.overlappingEdges(y1, y2, edges)) return; EdgeIntersection intersection; for (unsigned i = 0; i < edges.size(); ++i) { const FloatPolygonEdge *edge = edges[i]; float x1; float x2; if (edge->minY() < y1) { computeXIntersection(edge, y1, intersection); x1 = intersection.point.x(); } else x1 = (edge->vertex1().y() < edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x(); if (edge->maxY() > y2) { computeXIntersection(edge, y2, intersection); x2 = intersection.point.x(); } else x2 = (edge->vertex1().y() > edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x(); if (x1 > x2) std::swap(x1, x2); if (x2 > x1) result.append(FloatShapeInterval(x1, x2)); } sortAndMergeShapeIntervals(result); }
static inline bool appendIntervalX(float x, bool inside, FloatShapeIntervals& result) { if (!inside) result.append(FloatShapeInterval(x, x)); else result.last().setX2(x); return !inside; }