Skip to content

Commit 937ca24

Browse files
authored
Fix rasterization with degenerate segments (#207)
* Fix rasterization with degenerate segments * Change javadoc source version to 1.6
1 parent 47142f9 commit 937ca24

File tree

5 files changed

+77
-58
lines changed

5 files changed

+77
-58
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
bin/
22
results/
33
javadoc/
4+
depfiles/
5+
DepFiles/
46
esri-geometry-api.jar
57
.project
68
.classpath

build.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@
8686
</target>
8787

8888
<target name="javadoc" depends="jar">
89-
<javadoc access="public" author="true" classpathref="project.classpath" destdir="${dir.javadoc}" doctitle="Esri-geometry-api" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="com.esri.core.geometry.*" source="1.5" sourcepath="${dir.src.main.java}" splitindex="true" use="true" version="true">
89+
<javadoc access="public" author="true" classpathref="project.classpath" destdir="${dir.javadoc}" doctitle="Esri-geometry-api" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="com.esri.core.geometry.*" source="1.6" sourcepath="${dir.src.main.java}" splitindex="true" use="true" version="true">
9090
<link href="http://help.arcgis.com/EN/sdk/10.0/Java_AO_ADF/api/arcobjects" />
9191
<link href="http://docs.oracle.com/javase/6/docs/api/" />
9292
</javadoc>
9393
</target>
9494

9595
<target name="javadoc1">
96-
<javadoc access="public" author="true" classpathref="project.classpath" destdir="${dir.javadoc}" doctitle="Esri-geometry-api" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="com.esri.core.geometry.*" source="1.5" sourcepath="${dir.src.main.java}" splitindex="true" use="true" version="true">
96+
<javadoc access="public" author="true" classpathref="project.classpath" destdir="${dir.javadoc}" doctitle="Esri-geometry-api" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="com.esri.core.geometry.*" source="1.6" sourcepath="${dir.src.main.java}" splitindex="true" use="true" version="true">
9797
<link href="http://help.arcgis.com/EN/sdk/10.0/Java_AO_ADF/api/arcobjects" />
9898
<link href="http://docs.oracle.com/javase/6/docs/api/" />
9999
</javadoc>

src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,6 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer,
141141

142142
SegmentIteratorImpl segIter = polyPath.querySegmentIterator();
143143
double strokeHalfWidth = m_transform.transform(tol) + 1.5;
144-
double shortSegment = 0.25;
145-
Point2D vec = new Point2D();
146-
Point2D vecA = new Point2D();
147-
Point2D vecB = new Point2D();
148144

149145
Point2D ptStart = new Point2D();
150146
Point2D ptEnd = new Point2D();
@@ -153,6 +149,7 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer,
153149
double[] helper_xy_10_elm = new double[10];
154150
Envelope2D segEnv = new Envelope2D();
155151
Point2D ptOld = new Point2D();
152+
double extraWidth = 0;
156153
while (segIter.nextPath()) {
157154
boolean hasFan = false;
158155
boolean first = true;
@@ -170,10 +167,11 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer,
170167
if (hasFan) {
171168
rasterizer.startAddingEdges();
172169
rasterizer.addSegmentStroke(prev_start.x, prev_start.y,
173-
prev_end.x, prev_end.y, strokeHalfWidth, false,
170+
prev_end.x, prev_end.y, strokeHalfWidth + extraWidth, false,
174171
helper_xy_10_elm);
175172
rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD);
176173
hasFan = false;
174+
extraWidth = 0.0;
177175
}
178176

179177
first = true;
@@ -195,19 +193,26 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer,
195193

196194
rasterizer.startAddingEdges();
197195
hasFan = !rasterizer.addSegmentStroke(prev_start.x,
198-
prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth,
196+
prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth + extraWidth,
199197
true, helper_xy_10_elm);
200198
rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD);
201-
if (!hasFan)
199+
if (!hasFan) {
202200
ptOld.setCoords(prev_end);
201+
extraWidth = 0.0;
202+
}
203+
else {
204+
//track length of skipped segment to add it to the stroke width for the next edge.
205+
extraWidth = Math.max(extraWidth, Point2D.distance(prev_start, prev_end));
206+
}
203207
}
204208

205209
if (hasFan) {
206210
rasterizer.startAddingEdges();
207211
hasFan = !rasterizer.addSegmentStroke(prev_start.x,
208-
prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth,
212+
prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth + extraWidth,
209213
false, helper_xy_10_elm);
210214
rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD);
215+
extraWidth = 0.0;
211216
}
212217
}
213218
}
@@ -308,12 +313,10 @@ void init(MultiVertexGeometryImpl geom, double toleranceXY,
308313
m_transform = new Transformation2D();
309314
m_transform.initializeFromRect(worldEnv, pixEnv);// geom to pixels
310315

311-
Transformation2D identityTransform = new Transformation2D();
312-
313316
switch (geom.getType().value()) {
314317
case Geometry.GeometryType.MultiPoint:
315318
callback.setColor(m_rasterizer, 2);
316-
fillPoints(m_rasterizer, (MultiPointImpl) geom, m_stroke_half_width);
319+
fillPoints(m_rasterizer, (MultiPointImpl) geom, m_stroke_half_width);
317320
break;
318321
case Geometry.GeometryType.Polyline:
319322
callback.setColor(m_rasterizer, 2);
@@ -545,7 +548,6 @@ public boolean dbgSaveToBitmap(String fileName) {
545548
// int32_t* rgb4 = (int32_t*)malloc(biSizeImage);
546549
for (int y = 0; y < height; y++) {
547550
int scanlineIn = y * ((width * 2 + 31) / 32);
548-
int scanlineOut = offset + width * y;
549551

550552
for (int x = 0; x < width; x++) {
551553
int res = (m_bitmap[scanlineIn + (x >> 4)] >> ((x & 15) * 2)) & 3;

src/main/java/com/esri/core/geometry/SimpleRasterizer.java

+45-44
Original file line numberDiff line numberDiff line change
@@ -305,50 +305,51 @@ public final void fillEnvelope(Envelope2D envIn) {
305305
}
306306
}
307307

308-
final boolean addSegmentStroke(double x1, double y1, double x2, double y2, double half_width, boolean skip_short, double[] helper_xy_10_elm)
309-
{
310-
double vec_x = x2 - x1;
311-
double vec_y = y2 - y1;
312-
double len = Math.sqrt(vec_x * vec_x + vec_y * vec_y);
313-
if (skip_short && len < 0.5)
314-
return false;
315-
316-
boolean bshort = len < 0.00001;
317-
if (bshort)
318-
{
319-
len = 0.00001;
320-
vec_x = len;
321-
vec_y = 0.0;
322-
}
323-
324-
double f = half_width / len;
325-
vec_x *= f; vec_y *= f;
326-
double vecA_x = -vec_y;
327-
double vecA_y = vec_x;
328-
double vecB_x = vec_y;
329-
double vecB_y = -vec_x;
330-
//extend by half width
331-
x1 -= vec_x;
332-
y1 -= vec_y;
333-
x2 += vec_x;
334-
y2 += vec_y;
335-
//create rotated rectangle
336-
double[] fan = helper_xy_10_elm;
337-
assert(fan.length == 10);
338-
fan[0] = x1 + vecA_x;
339-
fan[1] = y1 + vecA_y;//fan[0].add(pt_start, vecA);
340-
fan[2] = x1 + vecB_x;
341-
fan[3] = y1 + vecB_y;//fan[1].add(pt_start, vecB);
342-
fan[4] = x2 + vecB_x;
343-
fan[5] = y2 + vecB_y;//fan[2].add(pt_end, vecB)
344-
fan[6] = x2 + vecA_x;
345-
fan[7] = y2 + vecA_y;//fan[3].add(pt_end, vecA)
346-
fan[8] = fan[0];
347-
fan[9] = fan[1];
348-
addRing(fan);
349-
return true;
350-
}
351-
308+
final boolean addSegmentStroke(double x1, double y1, double x2, double y2, double half_width, boolean skip_short,
309+
double[] helper_xy_10_elm) {
310+
double vec_x = x2 - x1;
311+
double vec_y = y2 - y1;
312+
double sqr_len = vec_x * vec_x + vec_y * vec_y;
313+
if (skip_short && sqr_len < (0.5 * 0.5)) {
314+
return false;
315+
}
316+
317+
boolean veryShort = !skip_short && (sqr_len < (0.00001 * 0.00001));
318+
if (veryShort) {
319+
vec_x = half_width + 0.00001;
320+
vec_y = 0.0;
321+
} else {
322+
double f = half_width / Math.sqrt(sqr_len);
323+
vec_x *= f;
324+
vec_y *= f;
325+
}
326+
327+
double vecA_x = -vec_y;
328+
double vecA_y = vec_x;
329+
double vecB_x = vec_y;
330+
double vecB_y = -vec_x;
331+
// extend by half width
332+
x1 -= vec_x;
333+
y1 -= vec_y;
334+
x2 += vec_x;
335+
y2 += vec_y;
336+
// create rotated rectangle
337+
double[] fan = helper_xy_10_elm;
338+
assert (fan.length == 10);
339+
fan[0] = x1 + vecA_x;
340+
fan[1] = y1 + vecA_y;// fan[0].add(pt_start, vecA);
341+
fan[2] = x1 + vecB_x;
342+
fan[3] = y1 + vecB_y;// fan[1].add(pt_start, vecB);
343+
fan[4] = x2 + vecB_x;
344+
fan[5] = y2 + vecB_y;// fan[2].add(pt_end, vecB)
345+
fan[6] = x2 + vecA_x;
346+
fan[7] = y2 + vecA_y;// fan[3].add(pt_end, vecA)
347+
fan[8] = fan[0];
348+
fan[9] = fan[1];
349+
addRing(fan);
350+
return true;
351+
}
352+
352353
public final ScanCallback getScanCallback() { return callback_; }
353354

354355
public long estimateMemorySize()

src/test/java/com/esri/core/geometry/TestOGCContains.java

+14
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ public void testGeometryCollection() {
5555
"GEOMETRYCOLLECTION (MULTIPOINT (0 0, 2 1))");
5656
}
5757

58+
@Test
59+
public void testAcceleratedPiP() {
60+
String wkt = "MULTIPOLYGON (((-109.642707 30.5236901, -109.607932 30.5367411, -109.5820257 30.574184, -109.5728286 30.5874766, -109.568679 30.5934741, -109.5538097 30.5918356, -109.553714 30.5918251, -109.553289 30.596034, -109.550951 30.6191889, -109.5474935 30.6221179, -109.541059 30.6275689, -109.5373751 30.6326491, -109.522538 30.6531099, -109.514671 30.6611981, -109.456764 30.6548095, -109.4556456 30.6546861, -109.4536755 30.6544688, -109.4526481 30.6543554, -109.446824 30.6537129, -109.437751 30.6702901, -109.433968 30.6709781, -109.43338 30.6774591, -109.416243 30.7164651, -109.401643 30.7230741, -109.377583 30.7145241, -109.3487939 30.7073896, -109.348594 30.7073401, -109.3483718 30.7073797, -109.3477608 30.7074887, -109.3461903 30.7078834, -109.3451022 30.7081569, -109.3431732 30.7086416, -109.3423301 30.708844, -109.3419714 30.7089301, -109.3416347 30.709011, -109.3325693 30.7111874, -109.3323814 30.7112325, -109.332233 30.7112681, -109.332191 30.7112686, -109.3247809 30.7113581, -109.322215 30.7159391, -109.327776 30.7234381, -109.350134 30.7646001, -109.364505 30.8382481, -109.410211 30.8749199, -109.400048 30.8733419, -109.3847799 30.9652412, -109.3841625 30.9689575, -109.375268 31.0224939, -109.390544 31.0227899, -109.399749 31.0363341, -109.395787 31.0468411, -109.388174 31.0810249, -109.3912446 31.0891966, -109.3913452 31.0894644, -109.392735 31.0931629, -109.4000839 31.0979214, -109.402803 31.0996821, -109.4110458 31.1034586, -109.419153 31.1071729, -109.449782 31.1279489, -109.469654 31.1159979, -109.4734874 31.1131178, -109.473753 31.1129183, -109.4739754 31.1127512, -109.491296 31.0997381, -109.507789 31.0721811, -109.512776 31.0537519, -109.5271478 31.0606861, -109.5313703 31.0627234, -109.540698 31.0672239, -109.5805468 31.0674089, -109.5807399 31.0674209, -109.595423 31.0674779, -109.60347 31.0690241, -109.6048011 31.068808, -109.6050803 31.0687627, -109.6192237 31.0664664, -109.635432 31.0638349, -109.6520068 31.0955326, -109.6522294 31.0959584, -109.652373 31.0962329, -109.657709 31.0959719, -109.718258 31.0930099, -109.821036 31.0915909, -109.8183088 31.0793374, -109.8165128 31.0712679, -109.8140062 31.0600052, -109.8138512 31.0593089, -109.812707 31.0541679, -109.8188146 31.0531909, -109.8215447 31.0527542, -109.8436765 31.0492138, -109.8514316 31.0479733, -109.8620535 31.0462742, -109.8655958 31.0457076, -109.868388 31.0452609, -109.8795483 31.0359656, -109.909274 31.0112075, -109.9210382 31.0014092, -109.9216329 31.0009139, -109.920594 30.994183, -109.9195356 30.9873254, -109.9192113 30.9852243, -109.9186281 30.9814453, -109.917814 30.9761709, -109.933894 30.9748879, -109.94094 30.9768059, -109.944854 30.9719821, -109.950803 30.9702809, -109.954025 30.9652409, -109.9584129 30.9636033, -109.958471 30.9635809, -109.9590542 30.9644372, -109.959896 30.9656733, -109.9604184 30.9664405, -109.9606288 30.9667494, -109.9608462 30.9670686, -109.961225 30.9676249, -109.9611615 30.9702903, -109.9611179 30.9721175, -109.9610885 30.9733488, -109.9610882 30.9733604, -109.9610624 30.9744451, -109.961017 30.9763469, -109.962609 30.9786559, -109.9634437 30.9783167, -110.00172 30.9627641, -110.0021152 30.9627564, -110.0224353 30.9623622, -110.0365868 30.9620877, -110.037493 30.9620701, -110.0374055 30.961663, -110.033653 30.9442059, -110.0215506 30.9492932, -110.0180392 30.9507693, -110.011203 30.9536429, -110.0062891 30.9102124, -110.0058721 30.9065268, -110.004869 30.8976609, -109.996392 30.8957129, -109.985038 30.8870439, -109.969416 30.9006011, -109.967905 30.8687239, -109.903498 30.8447749, -109.882925 30.8458289, -109.865184 30.8206519, -109.86465 30.777698, -109.864515 30.7668429, -109.837007 30.7461781, -109.83453 30.7164469, -109.839017 30.7089009, -109.813394 30.6906529, -109.808694 30.6595701, -109.795334 30.6630041, -109.7943042 30.6427223, -109.7940456 30.6376287, -109.7940391 30.637501, -109.793823 30.6332449, -109.833511 30.6274289, -109.830299 30.6252799, -109.844198 30.6254801, -109.852442 30.6056949, -109.832973 30.6021201, -109.8050409 30.591211, -109.773847 30.5790279, -109.772859 30.5521999, -109.754427 30.5393969, -109.743293 30.5443401, -109.6966136 30.5417334, -109.6648181 30.5399578, -109.6560456 30.5394679, -109.6528439 30.5392912, -109.6504039 30.5391565, -109.6473602 30.5389885, -109.646906 30.5389634, -109.6414545 30.5386625, -109.639708 30.5385661, -109.6397729 30.5382443, -109.642707 30.5236901)))";
61+
String pointWkt = "POINT (-109.65 31.091666666673)";
62+
63+
OGCGeometry polygon = OGCGeometry.fromText(wkt);
64+
OGCGeometry point = OGCGeometry.fromText(pointWkt);
65+
assertTrue(polygon.contains(point));
66+
67+
OperatorContains.local()
68+
.accelerateGeometry(polygon.getEsriGeometry(), null, Geometry.GeometryAccelerationDegree.enumMild);
69+
assertTrue(polygon.contains(point));;
70+
}
71+
5872
private void assertContains(String wkt, String otherWkt) {
5973
OGCGeometry geometry = OGCGeometry.fromText(wkt);
6074
OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt);

0 commit comments

Comments
 (0)