Say we have this path:
How do we find the bounds of the box that fits inside?
Yes I know that paths can be arbitrarily complex and must not be closed. Still curious about suggestions for how to solve this problem.
I guess to start I would go with a simple answer. The jut out on the bottom clearly won't affect the size of the largest interior rectangle so we can just assume that you can omit that. Once that is omitted it seems to me to be something like just two RectangleGeometries
that have been combined that have their RadiusX
and RadiusY
properties being non-zero.
An approximation that I made is given by the xaml below:
<Path Fill="Black">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="10,10,100,50" RadiusX="5" RadiusY="5" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="15,15,90,40" RadiusX="5" RadiusY="5"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
To me your question boils down to how to in general find the largest rectangle that will fit inside of the interior RectangleGeometry
without overlapping its border. To do that we have to deal with the RadiusX
and RadiusY
values.
To simplify things for now I will assume that RadiusX
= RadiusY
!= 0 and if you happen to be interested in the case of RadiusX
!= RadiusY
!= 0 then we can cross that bridge when we get to it.
When the x and y radii are equal the curved corner is just traced out using a circle. This circle will shorten the interior space given the way that it works and given that the radius values are small relative to the width and height of your image you are probably looking for the bounding rectangle that fits touches the 45 degree angle of the curved corners.
To accomplish this we just need to figure out the width and height that we are losing for a single corner. Since we are talking a circle and considering the 45 degree angle the losses will be the same in both directions. Using some simple trigonometry I came up with the following loss amount given a radius value of R:
loss for single corner direction = R(1 - sqrt(2)/2)
This was derived by determining the distance from the corner of the non-rounded version to the 45 degree edge of the rounding circle. This length can just be gathered by using the Pythagorean theorem to determine the length of the radius of the circle plus the "missing" portion and then just subtracting out the known radius to determine the length of the hypotenuse for this "missing" portion which is equal to R(1 - sqrt(2)).
Once this distance was gathered I used trigonometry again to gather the size of the legs of the resulting isosceles triangle which came out to R(1 - sqrt(2)/2) which is the equation that I listed earlier.
So finally, assuming that the original rectangle without any rounding would have x = x_o, y = y_o, width = w_o, height = h_o, and R = RadiusX = RadiusY != 0 we would get the following for our inscribed rectangle:
x = x_o + R(1 - sqrt(2)/2)
y = y_o + R(1 - sqrt(2)/2)
width = w_o - 2R(1 - sqrt(2)/2)
height = h_o - 2R(1 - sqrt(2)/2)
I tested this with the following xaml:
<Path Stroke="Black">
<Path.Data>
<RectangleGeometry Rect="10,10,100,50" RadiusX="5" RadiusY="5"/>
</Path.Data>
</Path>
<Path Stroke="Orange">
<Path.Data>
<RectangleGeometry Rect="11.47,11.47,97.07,47.07" RadiusX="0" RadiusY="0"/>
</Path.Data>
</Path>
Now this doesn't take into account the actual strokes of each rectangle geometry which do overlap but the interiors do not overlap which is what I am assuming is what you are looking for.
I know that there are a fair number of assumptions and simplifications flying around here but even with all of those this is a very long post so I am hoping that this is good enough for what you are looking for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With