15

I'm drawing regions (using SqlGeometry/SqlGeography and translating them to the WPF LocationCollection equivalent) on the Bing Maps WPF Control and needed to label them. I got the labels drawn on the regions and attached them to the point found by STCentroid(). Of course as you imagine this is a problem with the 'U' or 'C' shaped regions where the centroid ends up outside the region, which makes the label incorrect.

Is there a way using SqlGeometry/SqlGeography to find the "visual" center or perhaps find the largest circle that can fit in the shape and use that center? I've tried various methods using STPointOnSurface() but it seems that STPointOnSurface() always picks a point on the edge like so DCREHA (the label for the bottom dark green region always ends up on the edges:

enter image description here

Peet Whittaker
  • 750
  • 6
  • 31
Hershizer33
  • 1,206
  • 2
  • 23
  • 46
  • Assuming that there is only one shape, one solution might be to find the open side and then move the label the opposite side until the label is within the shape. You might also do some filtering to remove some area. Or you might try to find the biggest concave area (I don't know if there are algorithms for that). – Phil1970 Sep 08 '16 at 15:48
  • Related: http://stackoverflow.com/q/1203135/3628232 – Peet Whittaker Sep 11 '16 at 13:58
  • So where is the "visual center" of a U shape? – Sergei Patiakin Sep 13 '16 at 12:06
  • 1
    The center of largest circle that fits inside. The example I posted is U-like, so very informally it seems like to me the largest circle that can fit in it would be in the south-west, encompassing Garner and touching the PDNUNN area. – Hershizer33 Sep 13 '16 at 14:31

1 Answers1

10

An almost identical question has already been asked here. In your case, the most relevant answer is probably this one. The hard part of that answer is determining where to draw the line that splits the polygon into two equal areas. Therefore, I propose a slightly modified version below for SQL Server:

  1. Use STCentroid to find the centre of mass
  2. If this is inside the polygon (STWithin), then no need to process further; otherwise:
  3. Determine the centroid of the polygon's bounding box (e.g. use STEnvelope to get the polygon's envelope and pass that as the argument to STCentroid)
  4. If this centroid is within polygon (STWithin), it may be good enough (would need testing); otherwise:
  5. Extend the line that connects the polygon's centroid and the envelope's centroid so that it extends to just beyond the polygon's envelope in each direction (may be easier in C# code, or see here for a PostGIS solution)
  6. Determine the intersection points between the extended line and the polygon (STIntersection)
  7. Find the nearest intersection point to the polygon's centroid point from step 1 (see here). This point is an approximation for the "1st cut point" detailed in the linked answer.
  8. Find the nearest intersection point to the intersection point found above in step 7. This point is an approximation for the "2nd cut point" detailed in the linked answer.
  9. The mid-point of the line that connects the two intersection points will be inside the polygon, and should be a reasonable approximation for the "visual centre" of the polygon.

For instance, given the polygon for the DCREHA example above, the following GIF animates the procedure listed above (judged by eye - actual result will differ):

enter image description here

Community
  • 1
  • 1
Peet Whittaker
  • 750
  • 6
  • 31
  • 1
    I'm gonna accept this as it is very close to what I ended up doing (and would work for anyone with a similar issue) and I appreciated the effort that went into it. I went with casting 8 rays from the centroid (if not inside shape) to the NW, N, NE, E, SE, S, SW, W, took the intersection of those lines with the shape formed by the actual geometry and the viewbox, measured them and placed the label at the midpoint of the longest resulting line. – Hershizer33 Sep 13 '16 at 14:34