blob: 192cf95a7f9d30e49737488f78844650bdf2d497 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.asterix.runtime.evaluators.common;
import org.apache.asterix.dataflow.data.nontagged.Coordinate;
import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
import org.apache.asterix.dataflow.data.nontagged.serde.APolygonSerializerDeserializer;
import org.apache.asterix.om.base.ARectangle;
import org.apache.hyracks.api.exceptions.HyracksDataException;
public class SpatialUtils {
private double xAxis;
private double yAxis;
private double minProjection;
private double maxProjection;
private static final double doubleEpsilon = computeDoubleEpsilon();
private static final double pi = 3.14159265;
public SpatialUtils() {
}
private static double computeDoubleEpsilon() {
double doubleEpsilon = 1.0;
do {
doubleEpsilon /= 2.0;
} while (1.0 + (doubleEpsilon / 2.0) != 1.0);
return doubleEpsilon;
}
public static double doubleEpsilon() {
return doubleEpsilon;
}
public double getMinProjection() {
return minProjection;
}
public void setMinProjection(double minProjection) {
this.minProjection = minProjection;
}
public double getMaxProjection() {
return maxProjection;
}
public void setMaxProjection(double maxProjection) {
this.maxProjection = maxProjection;
}
public double getXAxis() {
return xAxis;
}
public void setXAxis(double xAxis) {
this.xAxis = xAxis;
}
public double getYAxis() {
return yAxis;
}
public void setYAxis(double yAxis) {
this.yAxis = yAxis;
}
public final static double pi() {
return pi;
}
public final static double dotProduct(double x1, double y1, double x2, double y2) {
return x1 * x2 + y1 * y2;
}
public final static double crossProduct(double x1, double y1, double x2, double y2) {
return x1 * y2 - y1 * x2;
}
// Warning: The caller is responsible of taking the absolute value
public final static double polygonArea(byte[] bytes, int offset, int numOfPoints) throws HyracksDataException {
double area = 0.0;
for (int i = 0; i < numOfPoints; i++) {
double x1 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.X));
double y1 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.Y));
double x2;
double y2;
if (i + 1 == numOfPoints) {
x2 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.X));
y2 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.Y));
} else {
x2 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(i + 1, Coordinate.X));
y2 = ADoubleSerializerDeserializer.getDouble(bytes,
offset + 1 + APolygonSerializerDeserializer.getCoordinateOffset(i + 1, Coordinate.Y));
}
area += (x1 * y2) - (x2 * y1);
}
return area * 0.5;
}
public void projectPolygon(DoubleArray trianglesX, DoubleArray trianglesY, int triangleId, double xAxis,
double yAxis) throws HyracksDataException {
double temp, min, max;
min = max = getTriangleXCoordinate(trianglesX, triangleId, 0) * xAxis
+ getTriangleYCoordinate(trianglesY, triangleId, 0) * yAxis;
for (int i = 1; i < 3; i++) {
temp = getTriangleXCoordinate(trianglesX, triangleId, i) * xAxis
+ getTriangleYCoordinate(trianglesY, triangleId, i) * yAxis;
if (temp > max) {
max = temp;
} else if (temp < min) {
min = temp;
}
}
setMinProjection(min);
setMaxProjection(max);
}
public void findNormals(DoubleArray trianglesX, DoubleArray trianglesY, int triangleId, int side)
throws HyracksDataException {
double x, y;
if (side == 0) {
x = getTriangleYCoordinate(trianglesY, triangleId, 2)
- getTriangleYCoordinate(trianglesY, triangleId, side);
y = getTriangleXCoordinate(trianglesX, triangleId, side)
- getTriangleXCoordinate(trianglesX, triangleId, 2);
} else {
x = getTriangleYCoordinate(trianglesY, triangleId, side - 1)
- getTriangleYCoordinate(trianglesY, triangleId, side);
y = getTriangleXCoordinate(trianglesX, triangleId, side)
- getTriangleXCoordinate(trianglesX, triangleId, side - 1);
}
double temp = Math.sqrt(dotProduct(x, y, x, y));
x /= temp;
y /= temp;
setXAxis(x);
setYAxis(y);
}
public static double getTriangleXCoordinate(DoubleArray trianglesX, int triangleId, int point) {
return trianglesX.get(triangleId * 3 + point);
}
public static double getTriangleYCoordinate(DoubleArray trianglesY, int triangleId, int point) {
return trianglesY.get(triangleId * 3 + point);
}
public static void setTriangleXCoordinate(DoubleArray trianglesX, int triangleId, int point, double value) {
trianglesX.get()[triangleId * 3 + point] = value;
}
public static void setTriangleYCoordinate(DoubleArray trianglesY, int triangleId, int point, double value) {
trianglesY.get()[triangleId * 3 + point] = value;
}
public static boolean intersects(ARectangle rect1, ARectangle rect2) {
// If one rectangle is on left side of other
if ((rect1.getP1().getX() > rect2.getP2().getX()) || (rect2.getP1().getX() > rect1.getP2().getX())) {
return false;
}
// If one rectangle is above other
if ((rect1.getP1().getY() > rect2.getP2().getY()) || (rect2.getP1().getY() > rect1.getP2().getY())) {
return false;
}
return true;
}
}