Suppose we have a singly connected but not necessarily convex polygon. Something like shape = CountryData["Chad", "Coordinates"].

Is there a simple way to implement an approximate dilation for this shape, and obtain the result as vector data (lists of coordinates) just like the input?

Here's what dilation does to images:

img = ImagePad[ColorNegate@Image@Graphics[Polygon[shape]], 30];
ImageCompose[Dilation[img, DiskMatrix[30]], {img, .5}]

Mathematica graphics

What I need is the outline of the gray area, but as vector (not bitmap) data.

One way is to rasterize, dilate the image, then vectorize the outline again. This seems complicated, especially since I need to preserve the original coordinate system.

Is there a better way?

The result will be used for visualization purposes, so it need not be perfect. Approximations are okay.

  • 2
    $\begingroup$ Something along the lines of ImplicitRegion[RegionDistance[polygon, {x, y}] <= r, {x, y}]? $\endgroup$
    – user484
    Commented Jun 30, 2015 at 15:55
  • $\begingroup$ @Rahul Sounds like a great idea! The problem is that actually plotting or discretizing region specifications fails very often. It seems that for Chad it does work well, and what's better, it even gives me the (approximately) equidistant points along the perimeter. I'm going to try it for my actual use case and hope for the best ... RegionBoundary@DiscretizeRegion[ImplicitRegion[RegionDistance[reg, {x, y}] <= 0.05, {x, y}], MaxCellMeasure -> 0.0001]. Why don't you post an answer? $\endgroup$
    – Szabolcs
    Commented Jun 30, 2015 at 16:39
  • $\begingroup$ @Rahul Unfortunately for my actual use case it just gives up :( I'll post a better example tomorrow, no internet connection at home and I need to leave :( $\endgroup$
    – Szabolcs
    Commented Jun 30, 2015 at 17:32
  • $\begingroup$ I didn't post an answer because I don't have access to Mathematica right now, so I had no idea if my suggestion would actually work! $\endgroup$
    – user484
    Commented Jun 30, 2015 at 19:30
  • $\begingroup$ @Rahul Thanks again, I managed to come up with a robust solution by making some minor modifications to your line. I'll post later tonight when I get the time. $\endgroup$
    – Szabolcs
    Commented Jul 1, 2015 at 16:07

3 Answers 3


From 2016 and Version 11.0 we can use ImageMesh.

img = ImagePad[ColorNegate@Image@Graphics[Polygon[shape]], 30];
imgD = Dilation[img, DiskMatrix[30]];
mesh0 = ImageMesh@img; meshD = ImageMesh@imgD;
Arrow[Flatten[pts0 = MeshPrimitives[mesh0, 1][[All, 1]], 1]], Red, 
Arrow@Flatten[ptsD = MeshPrimitives[meshD, 1][[All, 1]], 1]}]

enter image description here

shape = First @ CountryData["Chad", "Coordinates"];
poly = Polygon @ shape;
srd = SignedRegionDistance @ poly;

ranges = Flatten /@ Transpose[{{x, y}, 
     CoordinateBounds[ScalingTransform[1.4 {1, 1}, Mean @ shape] @ shape]}];

ContourPlot[srd[{x, y}], ranges[[1]], ranges[[2]], 
 Contours -> Thread[{{-1, -.5, -.25, .25, .5, 1}, 
    ColorData["Rainbow"] /@ Subdivide[5]}],
 ContourShading -> False, 
 Frame -> False, ImageSize -> 500, 
 Prolog -> {EdgeForm[Black], FaceForm[LightBlue], poly}, 
 PlotLegends -> Placed[LineLegend[Automatic, 
     LegendLabel -> SignedRegionDistance], Top]]

enter image description here


For visualization purposes only I propose a simple and robust approach using a thick boundary line:

shape = CountryData["Chad", "Coordinates"];
r = 2;

xmin = Min[shape[[1, ;; , 1]]] - r;
xmax = Max[shape[[1, ;; , 1]]] + r;
ymin = Min[shape[[1, ;; , 2]]] - r;
ymax = Max[shape[[1, ;; , 2]]] + r;

   EdgeForm[{JoinForm["Round"], Thickness[2 r/(xmax - xmin)], Blue}], 
  {Red, Polygon[shape]},
  Circle[shape[[1, 1]], r]
  }, PlotRange -> {{xmin, xmax}, {ymin, ymax}}, Axes -> True]

There are two drawbacks:

  • The dilated polygon is not given by an explicit set of points
  • We should specify the plot range to obtain the thickness in terms of original coordinates. The circle is drawn to check the thickness.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.