Message |
Dan and Steve,
If you're going to make a TIN or a grid, then you might as well generate the "solid contours" directly from that and be done with it.
The challenge, then, is to generate solid contours from a collection of contour lines directly, using vector operations only.
I twice attempted that in ArcView 3, as recently as six years ago, but was forced to abandon the project due to unavoidable bugs in ArcView's geometry calculations. The algorithm works fine--it doesn't even require closed contours--but when errors occur in splitting polygons with polylines, you're screwed.
OK, let's trust ArcGIS 9. Let me share an algorithm with you.
The input is a polygonal region and a set of polylines, each attributed with a number (its "height"). In preliminary steps, union any polylines of the same height together, so that to each height corresponds one unique (possibly disconnected) polyline. Sort these polylines into ascending order by height.
Let's consider the properties that make this a collection of contour lines and not just a bunch of lines scribbled on a map:
1) No two distinct polylines cross each other (intersect transversally).
2) Each polyline must dissect the region into two or more connected polygonal pieces. Each connected component of such a dissection intersects either polylines of lesser height or polylines of greater height, but not both.
(Property 1 is violated by overhangs, which cannot be unambiguously represented by contours.)
(Property 2 does not necessarily hold in some extreme cases: a perfectly level ridge or perfectly level valley, whose heights coincide with a contour value, will violate this property. Such contours are extremely rare, however, and if we consider them to be infinitesimally skinny loops, then property 2 always holds. Thus, as part of preprocessing, you can check for polylines that violate property 2 and replace them with very tiny buffers of those polylines.)
The algorithm exploits these properties. Initially, endow the input region with two null attributes: its lower height and upper height.
Let's see what happens when we start splitting the region with the polylines. (If there are no polylines, just output the entire region and its attributes.) Take the first (lowest) polyline and split the region with it, producing a collection of non-intersecting polygons. Each polygon in this collection inherits the lower height and upper height attributes of its parent (region) polygon. Momentarily retain the elevation, 'h', of this splitting polyline.
Remove the first polyline from the list and proceed to the next polyline. Let its height be 'k'. We are going to compare it to each of the regional components produced in the previous step. There are two possibilities:
(1) They do not intersect. In this case, set the upper height of the component to 'h' and output the polygon and its height attributes.
(2) Otherwise, they do intersect. Set the component's lower height to 'h' and *recursively apply the algorithm* to this component as the starting region, using a clone of the list of remaining polylines (including the one of height 'k').
If you are convinced that step (1) is correct, then the entire algorithm must be correct, because step (2) just applies the algorithm to an identical situation. But it should be obvious that step (1) does the right thing.
Notice that converting polylines to polygons is never done: the basic operations are splitting a polygon by a (potentially closed) polyline and testing whether a polyline intersects the interior of a polygon.
Notice, also, the following properties of the output:
a) Two regional components either do not intersect or else they intersect along a boundary that coincides with one of the original contours.
b) The union of the regional components coincides with the original region.
c) Every regional component has a lower and upper height, either of which may be null. A null lower height means this component is at elevations lower than all contours; a null upper height means it is at elevations higher than all contours.
d) When the original contours were obtained at regular intervals, then the difference between the upper and lower height must equal that interval. (This is implied by the procedure of step (2) in the algorithm.) |