01: package com.vividsolutions.jts.noding;
02:
03: import java.util.*;
04: import com.vividsolutions.jts.geom.*;
05: import com.vividsolutions.jts.algorithm.*;
06: import com.vividsolutions.jts.util.*;
07:
08: /**
09: * Wraps a {@link Noder} and transforms its input
10: * into the integer domain.
11: * This is intended for use with Snap-Rounding noders,
12: * which typically are only intended to work in the integer domain.
13: * Offsets can be provided to increase the number of digits of available precision.
14: *
15: * @version 1.7
16: */
17: public class ScaledNoder implements Noder {
18: private Noder noder;
19: private double scaleFactor;
20: private double offsetX;
21: private double offsetY;
22: private boolean isScaled = false;
23:
24: public ScaledNoder(Noder noder, double scaleFactor) {
25: this (noder, scaleFactor, 0, 0);
26: }
27:
28: public ScaledNoder(Noder noder, double scaleFactor, double offsetX,
29: double offsetY) {
30: this .noder = noder;
31: this .scaleFactor = scaleFactor;
32: // no need to scale if input precision is already integral
33: isScaled = !isIntegerPrecision();
34: }
35:
36: public boolean isIntegerPrecision() {
37: return scaleFactor == 1.0;
38: }
39:
40: public Collection getNodedSubstrings() {
41: Collection splitSS = noder.getNodedSubstrings();
42: if (isScaled)
43: rescale(splitSS);
44: return splitSS;
45: }
46:
47: public void computeNodes(Collection inputSegStrings) {
48: Collection intSegStrings = inputSegStrings;
49: if (isScaled)
50: intSegStrings = scale(inputSegStrings);
51: noder.computeNodes(intSegStrings);
52: }
53:
54: private Collection scale(Collection segStrings) {
55: return CollectionUtil.transform(segStrings,
56: new CollectionUtil.Function() {
57: public Object execute(Object obj) {
58: SegmentString ss = (SegmentString) obj;
59: return new SegmentString(scale(ss
60: .getCoordinates()), ss.getData());
61: }
62: });
63: }
64:
65: private Coordinate[] scale(Coordinate[] pts) {
66: Coordinate[] roundPts = new Coordinate[pts.length];
67: for (int i = 0; i < pts.length; i++) {
68: roundPts[i] = new Coordinate(Math
69: .round((pts[i].x - offsetX) * scaleFactor), Math
70: .round((pts[i].y - offsetY) * scaleFactor));
71: }
72: Coordinate[] roundPtsNoDup = CoordinateArrays
73: .removeRepeatedPoints(roundPts);
74: return roundPtsNoDup;
75: }
76:
77: //private double scale(double val) { return (double) Math.round(val * scaleFactor); }
78:
79: private void rescale(Collection segStrings) {
80: CollectionUtil.apply(segStrings, new CollectionUtil.Function() {
81: public Object execute(Object obj) {
82: SegmentString ss = (SegmentString) obj;
83: rescale(ss.getCoordinates());
84: return null;
85: }
86: });
87: }
88:
89: private void rescale(Coordinate[] pts) {
90: for (int i = 0; i < pts.length; i++) {
91: pts[i].x = pts[i].x / scaleFactor + offsetX;
92: pts[i].y = pts[i].y / scaleFactor + offsetY;
93: }
94: }
95:
96: //private double rescale(double val) { return val / scaleFactor; }
97: }
|