blob: 8434cb0dbdef4f4d45cb7cb2881babfe0293c106 [file] [log] [blame]
package org.eclipse.stem.ui.views.geographic.map;
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import org.eclipse.stem.core.common.Identifiable;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
/**
* A sub-class of java.awt.Polygon that has an extra field saving the relative
* value of the polygon. The relative values could be used for intensity values
* of the labels.
*/
public class StemPolygon {
private static final int LATITUDE_DIRECTION = -1;
private static final long serialVersionUID = 1L;
/**
* This value is selected to convert lat/long values to integers with six
* digits of precision extracted from the original double values.
*/
private final static int scalingFactorForData = 1000000;
/**
* This is the {@link Identifiable} instance associated with the polygon.
*/
private transient Identifiable identifiable;
/**
* An array of all points (better used by SWT drawing)
*/
public int[] points = null;
/**
* An array of all points, transformed to scale and offsets
*/
public int[] transformedPoints = null;
private int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
/**
* Empty constructor.
*
*/
public StemPolygon() {
super();
}
/**
* Gets a list of a latLongData arrays, and transforms it into a Polygon.
*
* @param latLongSegment
* @param identifiable
* the {@link Identifiable} associated with the polygon.
*/
public StemPolygon(final Segment latLongSegment, final Identifiable identifiable) {
super();
this.identifiable = identifiable;
final int size = latLongSegment.size();
points = new int[2*size];
for (int i = 0, pointsIndex = 0; i < size; i++, pointsIndex+=2) {
addPoint(latLongSegment.longitude(i), latLongSegment.latitude(i), pointsIndex);
}
// }
} // StemPolygon
// /**
// * Add latLong coordinates to a polygon.
// *
// * @param latLongData
// */
// public void addLatLongData(final LatLong latLongData) {
// final List<Segment> latLongSegmentsList = latLongData.getSegments();
//
// for (final Segment latLongSegment : latLongSegmentsList) {
// if (latLongSegment.isPolygon()) {
// final int size = latLongSegment.size();
// for (int i = 0, pointsIndex = 0; i < size; i++, pointsIndex+=2) {
// addPoint(latLongSegment.longitude(i), latLongSegment
// .latitude(i), pointsIndex);
// }
// }
// } // for
// } // addLatLongData
/**
*
* @param longitude
* longitude value
* @param latitude
* latitude value
* @param pointsIndex
*/
private void addPoint(final double longitude, final double latitude, final int pointsIndex) {
int x = (int)(longitude * scalingFactorForData);
int y = (int)(latitude * scalingFactorForData * LATITUDE_DIRECTION);
points[pointsIndex] = x;
points[pointsIndex+1] = y;
maxX = Math.max(x, maxX);
maxY = Math.max(y, maxY);
minX = Math.min(x, minX);
minY = Math.min(y, minY);
} // addPoint
/**
* @param pointsTransformer the pointsTransformer to set
*/
public void setPointsTransformer(StemPolygonTransform pointsTransformer) {
transformedPoints = new int[getNumberOfPoints()*2];
for (int i=0; i<getNumberOfPoints(); i++) {
int xBefore = points[2*i];
int yBefore = points[2*i+1];
int xAfter = (int) ((xBefore * pointsTransformer.getScale()) + pointsTransformer.getOffsetX());
int yAfter = (int)((yBefore * pointsTransformer.getScale()) + pointsTransformer.getOffsetY());
transformedPoints[2*i] = xAfter;
transformedPoints[2*i+1] = yAfter;
}
}
/**
* method to unscale the value that had been scaled by the above addPoint
* method.
*
* @param longitude
* @return unscaled value
*/
public double unScaleLongitude(final double longitude) {
return longitude / scalingFactorForData;
}
/**
* method to unscale the value that had been scaled by the above addPoint
* method.
*
* @param latitude
* @return unscaled value
*/
public double unScaleLatitude(final double latitude) {
return latitude / scalingFactorForData * LATITUDE_DIRECTION;
}
/**
* Returns the title of the polygon.
*
* @return String
*/
public String getTitle() {
return identifiable.getDublinCore().getTitle();
} // getTitle
/**
* @return the <code>Identifiable</code>
*/
public final Identifiable getIdentifiable() {
return identifiable;
}
/**
* @param identifiable
* the <code>Identifiable</code> to set
*/
public final void setIdentifiable(final Identifiable identifiable) {
this.identifiable = identifiable;
}
/**
* The method returns the smallest {@link Rectangle} that bounds of the polygon.
* @return {@link Rectangle} of the bounds of the polygon
*/
public Rectangle getBounds() {
if (minX == Integer.MAX_VALUE && maxY == Integer.MIN_VALUE) {
return null;
}
Rectangle bounds = new Rectangle(minX, minY, (maxX - minX), (maxY - minY));
return bounds;
}
/**
* Returns whether the point (x,y) is contained inside this polygon.
* @param point the X and Y coordinates
* @return whether the point (x,y) is contained in this polygon
*/
public boolean containsPoint(Point point) {
return containsPoint(point.x, point.y);
}
/**
* Returns whether the point (x,y) is contained inside this polygon.
* @param x The X value of the point
* @param y The Y value of the point
* @return whether the point (x,y) is contained in this polygon
*/
public boolean containsPoint(int x, int y) {
int i, j;
boolean isInside = false;
int numOfPoints = points.length / 2;
for (i = 0, j = (numOfPoints-1)*2; i < points.length-1; ) {
if ((((points[i+1]<=y) && (y<points[j+1])) ||
((points[j+1]<=y) && (y<points[i+1]))) &&
(x < (points[j] - points[i]) * (y - points[i+1]) / (points[j+1] - points[i+1]) + points[i])) {
isInside = !isInside;
}
j = i;
i += 2;
}
return isInside;
}
/**
* Returns the number of lat/long points that this polygon has
* @return the number of lat/long points
*/
public int getNumberOfPoints() {
if (points == null)
return 0;
return points.length / 2;
}
/**
* Returns the non-scaled value of the latitude of the specific point
* @param i Point index
* @return the non-scaled value of the latitude of the specific point
*/
public double getNonScaledLatitude(final int i) {
return (double)points[2*i+1] / (double)scalingFactorForData;
}
/**
* Returns the non-scaled value of the longitude of the specific point
* @param i Point index
* @return the non-scaled value of the longitude of the specific point
*/
public double getNonScaledLongitude(final int i) {
return (double)points[2*i] / scalingFactorForData * LATITUDE_DIRECTION;
}
/**
* Returns the unscaled value of the provided latitude
* @param latValue the scaled latitude value
* @return the unscaled value of the provided latitude
*/
public static double getUnscaledLatitude(final int latValue) {
return (double)latValue / (double)scalingFactorForData;
}
/**
* Returns the unscaled value of the provided longitude
* @param longValue the scaled latitude value
* @return the unscaled value of the provided longitude
*/
public static double getUnscaledLongitude(final int longValue) {
return (double)longValue / scalingFactorForData * LATITUDE_DIRECTION;
}
} // StemPolygon