/**
* Copyright (c) 2009-2011, chunquedong(YangJiandong)
*
* This file is part of ChunMap project
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
*
* History:
* 2010-05-05 Jed Young Creation
*/
package chunmap.model.operate.overlay;
import java.util.ArrayList;
import java.util.List;
import chunmap.model.coord.CoordSeqEditor;
import chunmap.model.elem.PointLineBag;
import chunmap.model.geom.GeometryException;
import chunmap.model.geom.LineString;
import chunmap.model.geom.Ring;
import chunmap.model.geom.Polygon;
import chunmap.model.relate.ComputeIm;
import chunmap.model.relate.ComputeImFactory;
import chunmap.model.relate.IntersectionMatrix;
/**
* @author chunquedong
*
*/
public class FragmentCollection {
private final List<Fragment> fragments1 = new ArrayList<Fragment>();
private final List<Fragment> fragments2 = new ArrayList<Fragment>();
public FragmentCollection(Polygon r1, Polygon r2) {
if (!r1.isValid() || !r2.isValid()) {
throw new GeometryException();
}
PointLineBag bag = getIntersection(r1, r2);
addPolygon(fragments1, r1, r2, bag);
addPolygon(fragments2, r2, r1, bag);
}
private void addPolygon(List<Fragment> fragment1, Polygon pg,
Polygon other, PointLineBag bag) {
fillList(fragment1, bag.breakLine(pg.getShell()), other);
List<Ring> rs = pg.getHoles();
for (Ring r : rs) {
fillList(fragment1, bag.breakLine(r), other);
}
return;
}
private PointLineBag getIntersection(Polygon pg1, Polygon pg2) {
PointLineBag tbag = subGetIntersection(pg1.getShell(), pg2);
List<Ring> rs = pg1.getHoles();
for (Ring r : rs) {
tbag.add(subGetIntersection(r, pg2));
}
return tbag;
}
private PointLineBag subGetIntersection(Ring r1, Polygon pg2) {
PointLineBag tbag = r1.intersection(pg2.getShell());
List<Ring> rs = pg2.getHoles();
for (Ring r : rs) {
tbag.add(r1.intersection(r));
}
return tbag;
}
private void fillList(List<Fragment> fragment1,
List<LineString> lineStrings, Polygon other) {
for (LineString ls : lineStrings) {
Fragment fra = new Fragment();
fra.setLineString(ls);
ComputeIm cim = ComputeImFactory.getInstance().getImComputer(ls,
other);
IntersectionMatrix im = cim.getIM();
boolean isWithin = isWithin(im);
boolean isBorder = isOnBorder(im);
if (isBorder) {
fra.setContainIn(Fragment.Border);
} else if (isWithin) {
fra.setContainIn(Fragment.Inner);
} else {
fra.setContainIn(Fragment.Outer);
}
fragment1.add(fra);
}
}
public boolean isOnBorder(IntersectionMatrix im) {
boolean b1 = (im.get(IntersectionMatrix.Inner,
IntersectionMatrix.Border) != IntersectionMatrix.EmptyDim);
boolean b2 = im.get(IntersectionMatrix.Inner, IntersectionMatrix.Inner) == IntersectionMatrix.EmptyDim;
boolean b3 = im.get(IntersectionMatrix.Inner, IntersectionMatrix.Outer) == IntersectionMatrix.EmptyDim;
if (b1 && b2 && b3)
return true;
return false;
}
public boolean isWithin(IntersectionMatrix im) {
boolean b1 = (im
.get(IntersectionMatrix.Inner, IntersectionMatrix.Outer) == IntersectionMatrix.EmptyDim);
if (b1)
return true;
return false;
}
public List<Polygon> getRing(int a, int b) {
List<Fragment> fragments = new ArrayList<Fragment>();
fillFragmentList(fragments, fragments1, a);
fillFragmentList(fragments, fragments2, b);
fillFragmentList(fragments, fragments1, Fragment.Border);
List<Polygon> result = new ArrayList<Polygon>();
Ring r = join(fragments);
while (r != null) {
assert r.isValid() : "the ring is not simple";
addRing(r, result);
r = join(fragments);
}
clearFlag(fragments);
return result;
}
private void addRing(Ring r, List<Polygon> pgs) {
List<Polygon> newPgs = new ArrayList<Polygon>();
List<Polygon> oldPgs = new ArrayList<Polygon>();
for (int i = 0, n = pgs.size(); i < n; i++) {
Polygon pg = pgs.get(i);
if (r.containLineStringIn(pg.getShell())) {
List<Ring> rr = new ArrayList<Ring>();
rr.add(pg.getShell());
newPgs.add(new Polygon(r, rr));
oldPgs.add(pg);
} else if (pg.getShell().containLineStringIn(r)) {
List<Ring> rr = new ArrayList<Ring>();
rr.add(r);
newPgs.add(new Polygon(pg.getShell(), rr));
oldPgs.add(pg);
}
}
if (newPgs.size() == 0) {
pgs.add(new Polygon(r));
} else {
for (Polygon pg : oldPgs) {
pgs.remove(pg);
}
pgs.addAll(newPgs);
}
}
private void fillFragmentList(List<Fragment> result, List<Fragment> old,
int a) {
for (Fragment fra : old) {
if (fra.isContainIn() == a) {
result.add(fra);
}
}
}
private Ring join(List<Fragment> fragment) {
CoordSeqEditor line = new CoordSeqEditor();
int n = fragment.size();
boolean none = true;
while (true) {
for (int i = 0; i < n; i++) {
if (!fragment.get(i).isFlag()) {
LineString ls = fragment.get(i).getLineString();
if (line.canJoin(ls.getPoints())) {
line.join(ls.getPoints());
fragment.get(i).setFlag(true);
none = false;
}
}
}
if (none) {
break;
}
none = true;
}
if (line.isEmpty()) {
return null;
}
assert line.isClose() : "the ring is not close";
line.deleteOverPoint();
line.close();
return new Ring(line.toCoordinateSeq());
}
private void clearFlag(List<Fragment> fragment) {
for (Fragment fra : fragment) {
fra.setFlag(false);
}
}
@Override
public String toString() {
return "FragmentCollection [fragments1size=" + fragments1.size()
+ ", fragments2size=" + fragments2.size() + "]";
}
}