[jts-devel] Re: decompose rectilinear polygon

2008-12-17 Thread Michael Bedward
Apologies for all the self-replies on the this thread...

I now have code that seems to work - slightly more involved than I
previously described after I realized that many configurations will
not have 3 consecutive convex vertices and that I needed to guard
against colinear point in the polygon's boundary.

In case it's of use to anyone, here is the code.  I'd also still be
keen to hear how this task should really be done !

Michael
package org.emilythecamel.jtsutils;

import com.vividsolutions.jts.algorithm.CGAlgorithms;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * A class to decompose a recti-linear (aka orthogonal) polygon into a set of 
 * non-overlapping rectangular polygons.
 * 
 * @author Michael Bedward
 */
public class OrthoPolygonDecomposer {

private GeometryFactory gf;

/**
 * Constructor
 */
public OrthoPolygonDecomposer() {
gf = new GeometryFactory();
}

/**
 * Decompose an orthogonal (rectilinear) polygon into a series of 
non-overlapping
 * rectangles.
 * @param orthoPoly the input polygon; it must not contain any holes and 
 * is ASSUMED to be orthogonal
 * @return a list of non-overlapping rectangular Polygons
 */
public List decompose(Geometry orthoPoly) {

if (((Polygon) orthoPoly).getNumInteriorRing() > 0) {
throw new IllegalArgumentException("can't deal with holes yet");
}

List rectangles = new ArrayList();
List vertices = new ArrayList();
List orientation;

Geometry edPoly = new EditablePolygon((Geometry) orthoPoly.clone());
Polygon rect;

while (true) {
((EditablePolygon)edPoly).removeColinearOuterVertices();
vertices.addAll(Arrays.asList(edPoly.getCoordinates()));
if (vertices.size() <= 5) {
break;
}

vertices.remove(vertices.size() - 1);
orientation = getVertexOrientation(vertices);

rect = search3(vertices, orientation);
rectangles.add(rect);
Geometry diff = edPoly.difference(rect);

if (diff.getGeometryType().equals("Polygon")) {
edPoly = new EditablePolygon(diff);
} else {
throw new RuntimeException("expected more polygons");
}

vertices.clear();
}

rect = makeRectPoly(vertices.get(0), vertices.get(2));
rectangles.add(rect);

return rectangles;
}

/**
 * Searches for a rectangle by looking for a concave vertex preceded by 3 
or more
 * convex vertices. If this configuration is found a new rectangle is 
constructed
 * having, as its diagonal, the line segment between the 1st and 3rd 
preceding
 * convex vertices;
 * otherwise the search is passed to
 * {...@linkplain #search2(java.util.List, java.util.List) }
 * @param vertices list of unique polygon vertices
 * @param orientation corresponding list of vertex orientations
 * @return a new rectangular polygon or null if one could not be constructed
 */
private Polygon search3(List vertices, List 
orientation) {
int n = vertices.size();
Stack convex = new Stack();

for (int i = 0; i < n; i++) {
switch (orientation.get(i)) {
case CGAlgorithms.LEFT:
if (convex.size() >= 3) {
int h = convex.pop();
convex.pop();
int f = convex.pop();
return makeRectPoly(vertices.get(f), vertices.get(h));
} else {
convex.clear();
}
break;

case CGAlgorithms.RIGHT:
convex.push(i);
break;
}
}

return search2(vertices, orientation);
}

/**
 * Searches for a rectangle by looking for a concave vertex preceded by 2 
or more
 * convex vertices. If this configuration is found, a rectangle is 
constructed
 * that has, as its diagonal, the line segment between the concave vertex 
and the
 * convex vertex two positions before it.
 * @param vertices list of unique polygon vertices
 * @param orientation corresponding list of vertex orientations
 * @return a new rectangular polygon or null if one could not be constructed
 */
private Polygon search2(List vertices, List 
orientation) {
int n = vertices.size();
Stack convex = new Stack();

for (int i = 0; i < n; i++) {
switch (orientation.get(i)) {
case CGAlgorithms.LEFT:

[jts-devel] Re: decompose rectilinear polygon

2008-12-17 Thread Michael Bedward
> 3. Find a concave vertex that is proceeded by 3 or more convex
> vertices;

sorry, that should read "preceded by 3 or more..."
___
jts-devel mailing list
jts-devel@lists.jump-project.org
http://lists.refractions.net/mailman/listinfo/jts-devel


[jts-devel] Re: decompose rectilinear polygon

2008-12-17 Thread Michael Bedward
2008/12/17 Michael Bedward :
> Hi folks,
>
> I need an algorithm to decompose a rectilinear polygon into a set of
> non-overlapping rectangles.

I now have this working.  No doubt there is a much easier and more
elegant solution, but here is my approach:

1. Get polygon vertices

2. Tag each vertex as convex or concave

3. Find a concave vertex that is proceeded by 3 or more convex
vertices; form a rectangle R using the closest 3 vertices; add R to
output list

4. P = difference of R and P

5. If P contains more than 4 unique vertices go to (1); otherwise P is
last rectangle

Michael
___
jts-devel mailing list
jts-devel@lists.jump-project.org
http://lists.refractions.net/mailman/listinfo/jts-devel