use of org.geotoolkit.geometry.jts.coordinatesequence.LiteCoordinateSequence in project geotoolkit by Geomatys.
the class GridCoverageFeatureSetTest method coverageRecord2DTest.
/**
* Test coverage 2D mapped as a feature.
*
* @throws DataStoreException
*/
@Test
public void coverageRecord2DTest() throws DataStoreException {
// create coverage
final BufferedImage image = BufferedImages.createImage(2, 2, 2, DataBuffer.TYPE_INT);
final WritableRaster raster = image.getRaster();
raster.setPixel(0, 0, new int[] { 10, 2 });
raster.setPixel(1, 0, new int[] { 30, 4 });
raster.setPixel(0, 1, new int[] { 50, 6 });
raster.setPixel(1, 1, new int[] { 70, 8 });
SampleDimension.Builder sdb = new SampleDimension.Builder();
sdb.setName("values");
sdb.addQuantitative("valuesCat", NumberRange.create(0, true, 1000, true), (MathTransform1D) MathTransforms.linear(10, -5), null);
final SampleDimension sdim1 = sdb.build();
sdb.clear();
sdb.setName("quality");
sdb.addQuantitative("qualityCat", NumberRange.create(0, true, 100, true), (MathTransform1D) MathTransforms.linear(1, 0), null);
final SampleDimension sdim2 = sdb.build();
final GridCoverageBuilder gcb = new GridCoverageBuilder();
gcb.setValues(image);
gcb.setDomain(new GridGeometry(null, PixelInCell.CELL_CENTER, new AffineTransform2D(2, 0, 0, 2, 31, 11), CommonCRS.WGS84.normalizedGeographic()));
gcb.setRanges(sdim1, sdim2);
final GridCoverage coverage = gcb.build();
// test mapped feature type
final FeatureType coverageType = GridCoverageFeatureSet.createCoverageType(coverage);
final FeatureAssociationRole role = (FeatureAssociationRole) coverageType.getProperty(TypeConventions.RANGE_ELEMENTS_PROPERTY.toString());
final FeatureType recordType = role.getValueType();
assertEquals("Coverage", coverageType.getName().toString());
assertTrue(TypeConventions.COVERAGE_TYPE.isAssignableFrom(coverageType));
assertEquals("Record", recordType.getName().tip().toString());
assertTrue(TypeConventions.COVERAGE_RECORD_TYPE.isAssignableFrom(recordType));
// convert coverage to feature
final Feature feature = coverageType.newInstance();
feature.setProperty(GridCoverageFeatureSet.coverageRecords(coverage, role));
// check records
final Collection col = (Collection) feature.getPropertyValue(TypeConventions.RANGE_ELEMENTS_PROPERTY.toString());
assertEquals(4, col.size());
final Iterator<Feature> ite = col.iterator();
final Feature r1 = ite.next();
final Feature r2 = ite.next();
final Feature r3 = ite.next();
final Feature r4 = ite.next();
assertFalse(ite.hasNext());
assertEquals(10.0 * 10 - 5, r1.getPropertyValue("values"));
assertEquals(2.0, r1.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 10, 32, 10, 32, 12, 30, 12, 30, 10 })), r1.getProperty("geometry").getValue());
assertEquals(30.0 * 10 - 5, r2.getPropertyValue("values"));
assertEquals(4.0, r2.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 10, 34, 10, 34, 12, 32, 12, 32, 10 })), r2.getProperty("geometry").getValue());
assertEquals(50.0 * 10 - 5, r3.getPropertyValue("values"));
assertEquals(6.0, r3.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 12, 32, 12, 32, 14, 30, 14, 30, 12 })), r3.getProperty("geometry").getValue());
assertEquals(70.0 * 10 - 5, r4.getPropertyValue("values"));
assertEquals(8.0, r4.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 12, 34, 12, 34, 14, 32, 14, 32, 12 })), r4.getProperty("geometry").getValue());
}
use of org.geotoolkit.geometry.jts.coordinatesequence.LiteCoordinateSequence in project geotoolkit by Geomatys.
the class GeometryClipTransformer method transform.
@Override
protected MultiPoint transform(final MultiPoint geom) throws TransformException {
final int nbGeom = geom.getNumGeometries();
if (nbGeom == 1) {
// nothing to decimate
return geom;
} else {
final LiteCoordinateSequence cs = new LiteCoordinateSequence(nbGeom, 2);
for (int i = 0; i < nbGeom; i++) {
final Coordinate coord = geom.getGeometryN(i).getCoordinate();
cs.setX(i, coord.x);
cs.setY(i, coord.y);
}
return gf.createMultiPoint(transform(cs, 1));
}
}
use of org.geotoolkit.geometry.jts.coordinatesequence.LiteCoordinateSequence in project geotoolkit by Geomatys.
the class GeometryClipTransformer method transform.
@Override
public CoordinateSequence transform(final CoordinateSequence cs, final int minpoints) {
double[] result = null;
final int size = cs.size();
if (size <= 2) {
// nothing to decimate
return cs;
}
// reset values
index = 0;
xmin = (float) clip.getMinX();
xmax = (float) clip.getMaxX();
ymin = (float) clip.getMinY();
ymax = (float) clip.getMaxY();
/*
* It appears that the polyline is neither completely inside nor completely
* outside <code>clip</code>. It is therefore necessary to perform a more
* powerful (and more costly) check.
*/
borderLength = 0;
intersectLength = 0;
final boolean isClosed = cs.getCoordinate(0).equals2D(cs.getCoordinate(size));
/*
* Obtains the first coordinate of the polyline. This first coordinate will be memorised
* in the variables <code>first[X/Y]</code> so it can be reused to eventually close the
* polyline. We must check whether this first coordinate is inside or outside the region
* of interest. This check serves to initialise the variable <code>inside</code>, which
* will serve for the rest of this method.
*/
if (next(cs)) {
final float firstX = line.x2;
final float firstY = line.y2;
boolean hasJoined = false;
boolean inside = (firstX >= xmin && firstX <= xmax) && (firstY >= ymin && firstY <= ymax);
float initialX1 = Float.NaN;
float initialY1 = Float.NaN;
double initialClockwise = Double.NaN;
float x0 = Float.NaN;
float y0 = Float.NaN;
double clockwise = 0;
int lower = 0, upper = 0;
while (true) {
/*
* Extracts the next coordinates. The point <code>line.p2</code>
* will contain the point that we have just extracted, whilst
* point <code>line.p1</code> will be the coordinate we had during the
* previous pass through this loop. If all the coordinates have been
* iterated, we will reuse the first point to reclose the polyline.
*/
if (!next(cs)) {
if (isClosed && (line.x2 != firstX || line.y2 != firstY)) {
assert !hasJoined;
line.x2 = firstX;
line.y2 = firstY;
hasJoined = true;
} else
// The only exit point for this loop.
break;
}
// Point at 'polyline[upper]' is equals to line.P2
upper++;
/*
* Checks whether the segment (x1,y1)-(x2,y2) goes clockwise around the rectangle.
* The segments inside the rectangle will not be taken into account. In the
* example below, the segment goes anti-clockwise.
*
* +--------+
* | |
* | | //(x2,y2)
* +--------+ //
* //(x1,y1)
*/
int outcode1 = 0;
int outcode2 = 0;
boolean out1, out2;
final float x1 = line.x1;
final float y1 = line.y1;
final float x2 = line.x2;
final float y2 = line.y2;
final float dx = x2 - x1;
final float dy = y2 - y1;
if (out1 = y1 > ymax)
outcode1 |= Rectangle2D.OUT_BOTTOM;
if (out2 = y2 > ymax)
outcode2 |= Rectangle2D.OUT_BOTTOM;
if (out1 && out2)
clockwise += dx;
else if (out1)
clockwise += dx / dy * (ymax - y1);
else if (out2)
clockwise += dx / dy * (y2 - ymax);
if (out1 = y1 < ymin)
outcode1 |= Rectangle2D.OUT_TOP;
if (out2 = y2 < ymin)
outcode2 |= Rectangle2D.OUT_TOP;
if (out1 && out2)
clockwise -= dx;
else if (out1)
clockwise -= dx / dy * (ymin - y1);
else if (out2)
clockwise -= dx / dy * (y2 - ymin);
if (out1 = x1 > xmax)
outcode1 |= Rectangle2D.OUT_RIGHT;
if (out2 = x2 > xmax)
outcode2 |= Rectangle2D.OUT_RIGHT;
if (out1 && out2)
clockwise -= dy;
else if (out1)
clockwise -= dy / dx * (xmax - x1);
else if (out2)
clockwise -= dy / dx * (x2 - xmax);
if (out1 = x1 < xmin)
outcode1 |= Rectangle2D.OUT_LEFT;
if (out2 = x2 < xmin)
outcode2 |= Rectangle2D.OUT_LEFT;
if (out1 && out2)
clockwise += dy;
else if (out1)
clockwise += dy / dx * (xmin - x1);
else if (out2)
clockwise += dy / dx * (x2 - xmin);
/*
* Now checks whether the points (x1,y1) and (x2,y2) are both outside
* the clip. If both are outside it does not mean that there are no
* intersections between the line P1-P2 and the clip. It is necessary to
* check (we will do this later). A first stage has already been done
* with the condition <code>(outcode1 & outcode2)==0</code>, which allowed
* us to check that the two points are not from the same side of the rectangle.
*/
final boolean lineInsideAndOutside = (inside != (outcode2 == 0));
final boolean lineCompletlyOutside = !lineInsideAndOutside && (outcode1 != 0 && outcode2 != 0 && (outcode1 & outcode2) == 0);
/*
* Adds the intersection points to the border, if it has been determined
* that the intersection points should be added. This situation occurs
* in the following three cases:
*
* 1) We have just entered the clip. The code below will construct all
* the border that precedes the entrance. We complete this border with the
* intersection point between the clip and the polyline.
* 2) We have just left the clip. The code below will memorise the data
* needed to render the polyline that is found entirely inside the clip.
* We complete these data with the intersection point between the clip and
* the polyline. Later in the loop, a border will be added after this
* intersection point, followed by another intersection point (stage 1).
* 3) It is possible that we have gone through the whole clip without
* stopping inside. Code below will try to detect this particular situation.
*/
intersectLength = 0;
if (lineInsideAndOutside || lineCompletlyOutside) {
final float cxmin = Math.max(xmin, Math.min(x1, x2));
final float cxmax = Math.min(xmax, Math.max(x1, x2));
final float cymin = Math.max(ymin, Math.min(y1, y2));
final float cymax = Math.min(ymax, Math.max(y1, y2));
if (ymax >= cymin && ymax <= cymax) {
final float v = dx / dy * (ymax - y1) + x1;
if (v >= cxmin && v <= cxmax)
addIntersect(v, ymax);
}
if (ymin >= cymin && ymin <= cymax) {
final float v = dx / dy * (ymin - y1) + x1;
if (v >= cxmin && v <= cxmax)
addIntersect(v, ymin);
}
if (xmax >= cxmin && xmax <= cxmax) {
final float v = dy / dx * (xmax - x1) + y1;
if (v >= cymin && v <= cymax)
addIntersect(xmax, v);
}
if (xmin >= cxmin && xmin <= cxmax) {
final float v = dy / dx * (xmin - x1) + y1;
if (v >= cymin && v <= cymax)
addIntersect(xmin, v);
}
/*
* Classifies intersection points using a 'classement � bulles'.
* This method is in theory extremely counter-productive when there is
* a lot of data to classify. But in our case, there will never normally
* be more than 2 points to classify, which makes this technique very
* advantageous.
*/
boolean modified;
do {
modified = false;
for (int i = 2; i < intersectLength; i += 2) {
if ((intersect[i - 2] - x1) * dx + (intersect[i - 1] - y1) * dy > (intersect[i + 0] - x1) * dx + (intersect[i + 1] - y1) * dy) {
final float x = intersect[i - 2];
final float y = intersect[i - 1];
intersect[i - 2] = intersect[i + 0];
intersect[i - 1] = intersect[i + 1];
intersect[i + 0] = x;
intersect[i + 1] = y;
modified = true;
}
}
} while (modified);
}
if (lineInsideAndOutside) {
/*
* An intersection has been found. We might have just entered the area of
* interest or just left it. The variable <code>inside</code> will indicate
* whether we have just entered or left the <code>clip</code> area.
*/
inside = !inside;
if (inside) {
/*
* If we have just entered the area of interest 'clip', checks whether
* it should add points to surround the clip border. These points will
* be effectively memorised later, when we leave the clip.
*/
float xn, yn;
if (intersectLength >= 2) {
xn = intersect[0];
yn = intersect[1];
} else {
xn = x1;
yn = y1;
}
if (Float.isNaN(x0) || Float.isNaN(y0)) {
initialClockwise = clockwise;
initialX1 = xn;
initialY1 = yn;
} else {
buildBorder(clockwise, x0, y0, xn, yn);
}
x0 = Float.NaN;
y0 = Float.NaN;
clockwise = 0;
} else {
/*
* If we have just left the area of interest, we will create a new
* "sub-polyline" that will contain only the data that appears in the
* region (the data will not be copied; only a reference game will be
* carried out). The coordinates (x0,y0) will be those of the first
* point outside the clip. Point index range from 'lower' inclusive
* (i.e. the 'line.P2' point at the time we entered in the area) to
* 'upper' exclusive (i.e. the 'line.P2' point right now).
*/
if (intersectLength >= 2) {
x0 = intersect[intersectLength - 2];
y0 = intersect[intersectLength - 1];
} else {
x0 = x2;
y0 = y2;
}
assert upper <= cs.size() : upper;
result = attach(result, cs, lower, upper);
}
lower = upper;
/*
* Adds the intersection points to the border.
* The method {@link #addBorder} will ensure that we do
* not repeat the same points twice.
*/
for (int i = 0; i < intersectLength; ) {
addBorder(intersect[i++], intersect[i++]);
}
} else if (lineCompletlyOutside) {
/*
* We now know that the points (x1,y1) and (x2,y2) are both
* outside the clip. But that doesn't mean that there was no
* intersection between the line P1-P2 and the clip. If there
* are at least two intersection points, the line goes through
* the clip and we must add it to the border.
*/
if (intersectLength >= 4) {
/*
* First of all, we recalculate <code>clockwise</code>
* (see above) but only counting the component due at the
* end of the line (i.e. "if (out2) ...").
*/
double clockwise2 = 0;
if ((outcode1 & Rectangle2D.OUT_BOTTOM) == 0 && (outcode2 & Rectangle2D.OUT_BOTTOM) != 0) {
clockwise2 += dx / dy * (y2 - ymax);
}
if ((outcode1 & Rectangle2D.OUT_TOP) == 0 && (outcode2 & Rectangle2D.OUT_TOP) != 0) {
clockwise2 -= dx / dy * (y2 - ymin);
}
if ((outcode1 & Rectangle2D.OUT_RIGHT) == 0 && (outcode2 & Rectangle2D.OUT_RIGHT) != 0) {
clockwise2 -= dy / dx * (x2 - xmax);
}
if ((outcode1 & Rectangle2D.OUT_LEFT) == 0 && (outcode2 & Rectangle2D.OUT_LEFT) != 0) {
clockwise2 += dy / dx * (x2 - xmin);
}
clockwise -= clockwise2;
if (Float.isNaN(x0) || Float.isNaN(y0)) {
initialClockwise = clockwise;
initialX1 = line.x1;
initialY1 = line.y1;
} else {
buildBorder(clockwise, x0, y0, intersect[0], intersect[1]);
}
x0 = intersect[intersectLength - 2];
y0 = intersect[intersectLength - 1];
clockwise = clockwise2;
/*
* Adds the intersection points to the border.
* The method {@link #addBorder} ensures that we do not
* repeat the same points twice.
*/
for (int i = 0; i < intersectLength; ) {
addBorder(intersect[i++], intersect[i++]);
}
}
}
}
/*
* At the end of the loop, adds the remaining points
* if they were inside the clip.
*/
if (inside) {
if (!hasJoined) {
upper++;
}
assert upper <= cs.size() : upper;
result = attach(result, cs, lower, upper);
}
if (isClosed) {
if (!Float.isNaN(x0) && !Float.isNaN(y0)) {
buildBorder(clockwise + initialClockwise, x0, y0, initialX1, initialY1);
}
}
if (result != null) {
result = attach(result, cs, 0, 0);
} else if (borderLength != 0) {
/*
* If no polyline has been created, but we have nevertheless
* detected intersections (i.e. if the zoom doesn't contain
* any point of the polyline but intercepts one of the polyline's
* lines) then we will add the intersection points and their borders.
*/
final float[] tmp;
if (border.length == borderLength) {
tmp = border;
} else {
tmp = new float[borderLength];
System.arraycopy(border, 0, tmp, 0, borderLength);
}
return new LiteCoordinateSequence(tmp);
} else {
/*
* If absolutely no point of the polyline is found inside the zoom
* then the zoom is either completely inside or completely outside
* the polyline. If it is completely inside, we will memorize a
* rectangle that will cover the whole zoom.
*/
final CoordinateSequence clipcs = new LiteCoordinateSequence(new float[] { xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin });
final LineString clipls = gf.createLineString(clipcs);
if (clipls.intersects(currentGeometry)) {
return clipcs;
}
}
}
if (result == null || result.length == 0) {
// todo should we do this ?
return null;
}
// todo should use the factory.
return new LiteCoordinateSequence(result);
}
use of org.geotoolkit.geometry.jts.coordinatesequence.LiteCoordinateSequence in project geotoolkit by Geomatys.
the class GeometryScaleTransformer method transform.
@Override
protected MultiPoint transform(final MultiPoint geom) throws TransformException {
final int nbGeom = geom.getNumGeometries();
if (nbGeom == 1) {
// nothing to decimate
return geom;
} else {
final LiteCoordinateSequence cs = new LiteCoordinateSequence(nbGeom, 2);
for (int i = 0; i < nbGeom; i++) {
final Coordinate coord = geom.getGeometryN(i).getCoordinate();
cs.setX(i, coord.x);
cs.setY(i, coord.y);
}
return gf.createMultiPoint(transform(cs, 1));
}
}
use of org.geotoolkit.geometry.jts.coordinatesequence.LiteCoordinateSequence in project geotoolkit by Geomatys.
the class GridCoverageFeatureSetTest method coverageRecord3DTest.
/**
* Test coverage 3D mapped as a feature.
*
* @throws DataStoreException
*/
@Ignore
@Test
public void coverageRecord3DTest() throws DataStoreException, IOException, TransformException, FactoryException {
// create CRS
final CoordinateReferenceSystem crs3d = new DefaultCompoundCRS(Collections.singletonMap("name", "crs3d"), CommonCRS.WGS84.normalizedGeographic(), CommonCRS.Vertical.DEPTH.crs());
// create sample dimensions
SampleDimension.Builder sdb = new SampleDimension.Builder();
sdb.setName("values");
sdb.addQuantitative("valuesCat", NumberRange.create(0, true, 1000, true), (MathTransform1D) MathTransforms.linear(10, -5), null);
final SampleDimension sdim1 = sdb.build();
sdb.clear();
sdb.setName("quality");
sdb.addQuantitative("qualityCat", NumberRange.create(0, true, 100, true), (MathTransform1D) MathTransforms.linear(1, 0), null);
final SampleDimension sdim2 = sdb.build();
final int width = 2, height = 2, depth = 2, nbSamples = 2;
// Cube geometry
final GridExtent cubeGrid = new GridExtent(new DimensionNameType[] { DimensionNameType.COLUMN, DimensionNameType.ROW, DimensionNameType.VERTICAL }, new long[3], new long[] { width, height, depth }, false);
final MathTransform cubeGrid2Crs = MathTransforms.linear(Matrices.create(4, 4, new double[] { 2, 0, 0, 31, 0, 2, 0, 11, 0, 0, 1, 100, 0, 0, 0, 1 }));
final GridGeometry domain = new GridGeometry(cubeGrid, PixelInCell.CELL_CENTER, cubeGrid2Crs, crs3d);
final int[] values = { // z = 0
10, 2, 30, 4, 50, 6, 70, 8, // z = 1
20, 3, 40, 5, 60, 7, 80, 9 };
final GridCoverage coverage3D = new BufferedGridCoverage(domain, Arrays.asList(sdim1, sdim2), new DataBufferInt(values, values.length));
// test mapped feature type
final FeatureType coverageType = GridCoverageFeatureSet.createCoverageType(coverage3D);
final FeatureAssociationRole role = (FeatureAssociationRole) coverageType.getProperty(TypeConventions.RANGE_ELEMENTS_PROPERTY.toString());
final FeatureType recordType = role.getValueType();
assertEquals("Coverage3D", coverageType.getName().toString());
assertTrue(TypeConventions.COVERAGE_TYPE.isAssignableFrom(coverageType));
assertEquals("Coverage3DRecord", recordType.getName().toString());
assertTrue(TypeConventions.COVERAGE_RECORD_TYPE.isAssignableFrom(recordType));
// convert coverage to feature
final Feature feature = coverageType.newInstance();
feature.setProperty(GridCoverageFeatureSet.coverageRecords(coverage3D, role));
// check records
final Collection col = (Collection) feature.getPropertyValue(TypeConventions.RANGE_ELEMENTS_PROPERTY.toString());
assertEquals(4 * 2, col.size());
final Iterator<Feature> ite = col.iterator();
final Feature r1 = ite.next();
final Feature r2 = ite.next();
final Feature r3 = ite.next();
final Feature r4 = ite.next();
final Feature r5 = ite.next();
final Feature r6 = ite.next();
final Feature r7 = ite.next();
final Feature r8 = ite.next();
assertFalse(ite.hasNext());
assertEquals(10.0 * 10 - 5, r1.getPropertyValue("values"));
assertEquals(2.0, r1.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 12, 32, 12, 32, 14, 30, 14, 30, 12 })), r1.getProperty("geometry").getValue());
assertEquals(30.0 * 10 - 5, r2.getPropertyValue("values"));
assertEquals(4.0, r2.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 12, 34, 12, 34, 14, 32, 14, 32, 12 })), r2.getProperty("geometry").getValue());
assertEquals(50.0 * 10 - 5, r3.getPropertyValue("values"));
assertEquals(6.0, r3.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 14, 32, 14, 32, 16, 30, 16, 30, 14 })), r3.getProperty("geometry").getValue());
assertEquals(70.0 * 10 - 5, r4.getPropertyValue("values"));
assertEquals(8.0, r4.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 14, 34, 14, 34, 16, 32, 16, 32, 14 })), r4.getProperty("geometry").getValue());
assertEquals(20.0 * 10 - 5, r5.getPropertyValue("values"));
assertEquals(3.0, r5.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 12, 32, 12, 32, 14, 30, 14, 30, 12 })), r5.getProperty("geometry").getValue());
assertEquals(40.0 * 10 - 5, r6.getPropertyValue("values"));
assertEquals(5.0, r6.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 12, 34, 12, 34, 14, 32, 14, 32, 12 })), r6.getProperty("geometry").getValue());
assertEquals(60.0 * 10 - 5, r7.getPropertyValue("values"));
assertEquals(7.0, r7.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 30, 14, 32, 14, 32, 16, 30, 16, 30, 14 })), r7.getProperty("geometry").getValue());
assertEquals(80.0 * 10 - 5, r8.getPropertyValue("values"));
assertEquals(9.0, r8.getPropertyValue("quality"));
assertEquals(GF.createPolygon(new LiteCoordinateSequence(new double[] { 32, 14, 34, 14, 34, 16, 32, 16, 32, 14 })), r8.getProperty("geometry").getValue());
}
Aggregations