PDA

View Full Version : Inward/outward QPainterPath/polygon offset



brcain
26th September 2016, 20:40
Hello all,

Does Qt have the ability to generate inward/outward offset paths similar to what is shown in the image?

If not, can anyone offer a lightweight solution?

12125

Thanks,
Ben

brcain
28th September 2016, 15:56
If not available, this would be a useful feature to add to QPainterPath. Note, offsets are not the same thing as scaling because they are done on a edge basis.

I ended up computing the edge/wire offsets by using third party software. The result is shown below (note the slightly less bright dashed line).

12134

d_stranz
28th September 2016, 22:15
Geometrically, this is equivalent to rolling a circle of radius equal to the offset distance along the curve and plotting the trajectory of the center of the circle. The problem is that the elements of a path can be both geometric (lines, arcs, rectangles, etc.) as well as parametric (cubic and quadratic Bezier curve) objects. Paths can also be convex, concave, closed, open, intersecting, connected and disconnected.

So *if* you can compute the bounding exterior contour, then in principle you can compute an outer offset path. Computing an inner offset path would be much harder, I think, given all the possibilities.

To complicate this, QPainterPath does not give you access to the bounding contour. The best you can get is pointAtPercent() and slopeAtPrecent(), and that doesn't really tell you anything about whether the point is on the outer boundary of a closed curve or on an interior element.

brcain
29th September 2016, 00:32
The third party software I ended up using supports polygon and parametric types. It's actually the 2D portions of a full blown CAD engine.

You can get the bounding contour of a QPainterPath with the toFillPolygon() method.

It's easy to compute inward and outward offset shapes as long as they don't produce invalid geometry.



QList<QPointF> points;
QPolygonF polygon = outerArc.toFillPolygon();
foreach(auto point, polygon)
{
points.push_back(point);
}
QList<QPointF> pointsResult;
makeOffsetFace(points, -0.25*mMaxelSize, pointsResult);
QPolygonF polygonOffset;
foreach(auto point, pointsResult)
{
polygonOffset << point;
}
if(!polygonOffset.isEmpty())
{
mOuterFillPath.addPolygon(polygonOffset);
}

d_stranz
29th September 2016, 16:27
You can get the bounding contour of a QPainterPath with the toFillPolygon() method.

Ah, didn't realize that - good to know.

What does "makeOffsetFace" do? If I were to guess, it would calculate the bisecting line between two adjacent polygon edges and move outward or inward along that line for the specified offset to find the new point for the outer or inner polygon, correct? I presume there is also a "handedness" rule that determines outward vs. inward as you move along the polygon in a clockwise or counterclockwise direction.