
com.querydsl.sql.spatial.SQLServerGeometryWriter Maven / Gradle / Ivy
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.querydsl.sql.spatial;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import org.geolatte.geom.*;
import com.google.common.collect.Lists;
class SQLServerGeometryWriter {
private static final int POINT = 1;
private static final int LINE_STRING = 2;
private static final int POLYGON = 3;
private static final int MULTI_POINT = 4;
private static final int MULTI_LINESTRING = 5;
private static final int MULTI_POLYGON = 6;
private static final int GEOMETRY_COLLECTION = 7;
private static class Figure {
int attributes;
int pointOffset;
}
private static class Shape {
int parentOffset;
int figureOffset;
int type;
}
private List points = Lists.newArrayList();
private List figures = Lists.newArrayList();
private List shapes = Lists.newArrayList();
private int calculateCapacity(Geometry geometry) {
int numPoints = points.size();
int prefixSize = 6;
if (geometry instanceof Point) {
int capacity = prefixSize + 16 * numPoints;
if (geometry.is3D()) {
capacity += 8 * numPoints;
}
if (geometry.isMeasured()) {
capacity += 8 * numPoints;
}
return capacity;
}
int pointSize = 16 + (geometry.is3D() ? 8 : 0) + (geometry.isMeasured() ? 8 : 0);
int size = prefixSize + 3 * 4; // prefix + 3 ints for points, shapes and
// figures
size += numPoints * pointSize;
size += figures.size() * 5;
size += shapes.size() * 9;
return size;
}
public byte[] write(Geometry geometry) throws IOException {
visit(geometry, -1);
int bytes = calculateCapacity(geometry);
boolean singlePoint = geometry instanceof Point;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(geometry.getSRID());
buffer.put((byte) 1);
buffer.put((byte) ((geometry.is3D() ? 1 : 0)
+ (geometry.isMeasured() ? 2 : 0)
+ 4 // is valid
+ (singlePoint ? 8 : 0)
+ 0)); // TODO
if (!singlePoint) {
buffer.putInt(points.size());
}
for (Point point : points) {
buffer.putDouble(point.getX());
buffer.putDouble(point.getY());
}
if (geometry.is3D()) {
for (Point point : points) {
buffer.putDouble(point.getZ());
}
}
if (geometry.isMeasured()) {
for (Point point : points) {
buffer.putDouble(point.getM());
}
}
if (!singlePoint) {
buffer.putInt(figures.size());
for (Figure figure : figures) {
buffer.put((byte) figure.attributes);
buffer.putInt(figure.pointOffset);
}
buffer.putInt(shapes.size());
for (Shape shape : shapes) {
buffer.putInt(shape.parentOffset);
buffer.putInt(shape.figureOffset);
buffer.put((byte) shape.type);
}
}
return buffer.array();
}
private void visit(Geometry geometry, int parent) {
switch (geometry.getGeometryType()) {
case POINT: visit((Point) geometry, parent); break;
case POLYGON: visit((Polygon) geometry, parent); break;
case LINE_STRING: visit((LineString) geometry, parent); break;
case MULTI_POINT: visit((MultiPoint) geometry, parent); break;
case MULTI_LINE_STRING: visit((MultiLineString) geometry, parent); break;
case MULTI_POLYGON: visit((MultiPolygon) geometry, parent); break;
case GEOMETRY_COLLECTION: visit((GeometryCollection) geometry, parent); break;
default: throw new IllegalArgumentException(geometry.toString());
}
}
public void visit(Point point, int parent) {
Shape shape = new Shape();
shape.type = POINT;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
Figure figure = new Figure();
figure.attributes = 1;
figure.pointOffset = points.size();
figures.add(figure);
points.add(point);
}
public void visit(LineString lineString, int parent) {
Shape shape = new Shape();
shape.type = LINE_STRING;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
Figure figure = new Figure();
figure.attributes = 1;
figure.pointOffset = points.size();
figures.add(figure);
for (Point point : lineString.getPoints()) {
points.add(point);
}
}
public void visit(Polygon polygon, int parent) {
Shape shape = new Shape();
shape.type = POLYGON;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
// exterior
Figure figure = new Figure();
figure.attributes = 2;
figure.pointOffset = points.size();
figures.add(figure);
for (Point point : polygon.getExteriorRing().getPoints()) {
points.add(point);
}
// interior
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
figure = new Figure();
figure.attributes = 0;
figure.pointOffset = points.size();
figures.add(figure);
for (Point point : polygon.getInteriorRingN(i).getPoints()) {
points.add(point);
}
}
}
public void visit(MultiPoint collection, int parent) {
Shape shape = new Shape();
shape.type = MULTI_POINT;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
parent = shapes.size() - 1;
for (int i = 0; i < collection.getNumGeometries(); i++) {
visit(collection.getGeometryN(i), parent);
}
}
public void visit(MultiLineString collection, int parent) {
Shape shape = new Shape();
shape.type = MULTI_LINESTRING;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
parent = shapes.size() - 1;
for (int i = 0; i < collection.getNumGeometries(); i++) {
visit(collection.getGeometryN(i), parent);
}
}
public void visit(MultiPolygon collection, int parent) {
Shape shape = new Shape();
shape.type = MULTI_POLYGON;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
parent = shapes.size() - 1;
for (int i = 0; i < collection.getNumGeometries(); i++) {
visit(collection.getGeometryN(i), parent);
}
}
public void visit(GeometryCollection collection, int parent) {
Shape shape = new Shape();
shape.type = GEOMETRY_COLLECTION;
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
parent = shapes.size() - 1;
for (int i = 0; i < collection.getNumGeometries(); i++) {
visit(collection.getGeometryN(i), parent);
}
}
public void visit(PolyHedralSurface surface, int parent) {
Shape shape = new Shape();
shape.type = -1; // TODO
shape.figureOffset = figures.size();
shape.parentOffset = parent;
shapes.add(shape);
parent = shapes.size() - 1;
for (int i = 0; i < surface.getNumPatches(); i++) {
visit(surface.getPatchN(i), parent);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy