I'm collecting different geometries from drawn parts of a graphic and combining them into a single geometry to show a selection highlighting border around a graphical object. The combined geometry consists of the union of many rectangles (might also be other shapes). Sometimes, the combined rectangles may cause a hole in the resulting geometry, when my graphic drawing goes all around an empty spot where nothing is drawn.
How can I remove that hole? I need only the outermost outline of the geometry, none of the inner empty parts.
This code unions the geometries:
outline = Geometry.Combine(outline, new RectangleGeometry(rect), GeometryCombineMode.Union, null);
CodePudding user response:
You may first create a polygonal approximation of your geometry as PathGeometry, which contains multiple Figures for its inner and outer polygons.
Then select the appropriate Figure that holds the outer polygon for another PathGeometry - which seems to be the last one. Not sure if this is always true. If unsure, you may certainly somehow retrieve their bounding boxes and select the largest one.
var outlinePath = outline.GetOutlinedPathGeometry();
var singleOutline = new PathGeometry();
singleOutline.Figures.Add(outlinePath.Figures.Last());
CodePudding user response:
Based on Clemens' answer I've written this code:
/// <summary>
/// Removes figures from a path geometry that are contained by other figures. These are
/// holes in an outline that shall be removed to simplify the form. Separate figures that
/// do not overlap are kept.
/// </summary>
/// <param name="geometry">The path geometry with multiple figures.</param>
private void RemoveInnerFigures(PathGeometry geometry)
{
var boundsList = new List<Rect>();
var dummyPathGeom = new PathGeometry();
foreach (var figure in geometry.Figures)
{
dummyPathGeom.Figures.Add(figure.Clone());
boundsList.Add(dummyPathGeom.Bounds);
dummyPathGeom.Figures.Clear();
}
for (int i = 0; i < geometry.Figures.Count; i )
{
for (int j = 0; j < geometry.Figures.Count; j )
{
if (i == j) continue;
if (boundsList[j].Contains(boundsList[i]))
{
// Figure i is contained within figure j, remove i
geometry.Figures.RemoveAt(i);
boundsList.RemoveAt(i);
i--;
break;
}
}
}
}
It seems to be important to apply this only once when the geometry is complete. Calling it after adding each bit of the geometry (as shown in the question's code) will cause missing parts. I haven't investigated the reasons for it.
(Please upvote both answers if you find this code helpful.)