package com.nutiteq.components;
import javax.microedition.lcdui.Graphics;
import net.sourceforge.jmicropolygon.PolygonGraphics;
import com.nutiteq.maps.GeoMap;
import com.nutiteq.utils.Utils;
/**
* A generic polygon object. At the moment only available in blue.
*/
public class Polygon implements OnMapElement {
private final WgsPoint[] coordinates;
private final MapPos[] mapPositions;
private final boolean serverSideRender;
private Point boundingBoxMin;
private Point boundingBoxMax;
private PolyStyle style;
private final Label label;
public Polygon(final WgsPoint[] coordinates) {
this(coordinates, PolyStyle.DEFAULT_STYLE, false);
}
public Polygon(final WgsPoint[] coordinates, final PolyStyle style) {
this(coordinates, style, false);
}
public Polygon(final WgsPoint[] coordinates, final PolyStyle style, final Label label) {
this(coordinates, style, label, false);
}
public Polygon(final WgsPoint[] coordinates, final boolean serverSideRender) {
this(coordinates, PolyStyle.DEFAULT_STYLE, serverSideRender);
}
public Polygon(final WgsPoint[] coordinates, final PolyStyle style, final boolean serverSideRender) {
this(coordinates, style, null, serverSideRender);
}
public Polygon(final WgsPoint[] coordinates, final PolyStyle style, final Label label,
final boolean serverSideRender) {
this.coordinates = coordinates;
this.style = style;
this.label = label;
mapPositions = new MapPos[coordinates.length];
this.serverSideRender = serverSideRender;
}
protected Polygon(final MapPos[] positions) {
coordinates = null;
style = null;
label = null;
mapPositions = positions;
serverSideRender = false;
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for (int i = 0; i < mapPositions.length; i++) {
final MapPos pos = mapPositions[i];
minX = Math.min(minX, pos.getX());
minY = Math.min(minY, pos.getY());
maxX = Math.max(maxX, pos.getX());
maxY = Math.max(maxY, pos.getY());
}
boundingBoxMin = new Point(minX, minY);
boundingBoxMax = new Point(maxX, maxY);
}
public boolean isVisible(final int viewX, final int viewY, final int viewWidth,
final int viewHeight, final int zoom) {
final MapPos start = mapPositions[0];
for (int i = 1; i < mapPositions.length; i++) {
final MapPos end = mapPositions[i];
if (Utils.rectanglesIntersect(start.getX(), start.getY(), end.getX() - start.getX(), end
.getY()
- start.getY(), viewX, viewY, viewWidth, viewHeight)) {
return true;
}
}
return false;
}
public void paint(final Graphics g, final MapPos middlePoint, final int displayCenterX,
final int displayCenterY, final Rectangle changedMapArea) {
if (serverSideRender) {
return;
}
//TODO jaanus : check toScreenArea. looks like height or screen y is incorrect
final Rectangle changedAreaOnScreen = Utils.areaToScreen(changedMapArea, middlePoint.getX()
- displayCenterX, middlePoint.getY() - displayCenterY, displayCenterX * 2,
displayCenterY * 2);
//Set current color
g.setColor(style.getColor());
int left;
int top;
int dx;
int dy;
//Try to draw filled polygon
//TODO jaanus : shares some logic with line?
final int[] xPoints = new int[mapPositions.length];
final int[] yPoints = new int[mapPositions.length];
int minScreenY = Integer.MAX_VALUE;
for (int i = 0; i < xPoints.length; i++) {
left = mapPositions[i].getX() - middlePoint.getX() + displayCenterX;
top = mapPositions[i].getY() - middlePoint.getY() + displayCenterY;
if (i < mapPositions.length - 1) {
dx = mapPositions[i + 1].getX() - mapPositions[i].getX();
dy = mapPositions[i + 1].getY() - mapPositions[i].getY();
} else {
dx = mapPositions[0].getX() - mapPositions[i].getX();
dy = mapPositions[0].getY() - mapPositions[i].getY();
}
//Draw border lines
g.drawLine(left, top, left + dx, top + dy);
xPoints[i] = left + dx;
yPoints[i] = top + dy;
minScreenY = Math.min(minScreenY, yPoints[i]);
}
//Hash the area
PolygonGraphics.hashPolygon(g, xPoints, yPoints, displayCenterX * 2, displayCenterY * 2,
minScreenY, changedAreaOnScreen);
}
public void calculatePosition(final GeoMap displayedMap, final int zoomLevel) {
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for (int i = 0; i < coordinates.length; i++) {
mapPositions[i] = displayedMap.wgsToMapPos(coordinates[i].toInternalWgs(), zoomLevel);
final MapPos pos = mapPositions[i];
minX = Math.min(minX, pos.getX());
minY = Math.min(minY, pos.getY());
maxX = Math.max(maxX, pos.getX());
maxY = Math.max(maxY, pos.getY());
}
boundingBoxMin = new Point(minX, minY);
boundingBoxMax = new Point(maxX, maxY);
}
public boolean isCentered(final MapPos cursorPoint) {
if (!viewWithinBoundingBox(cursorPoint.getX(), cursorPoint.getY(), 1, 1)) {
return false;
}
final MapPos[] copy = new MapPos[mapPositions.length];
System.arraycopy(mapPositions, 0, copy, 0, mapPositions.length);
return PolygonGraphics.cursorOnPolygon(copy, cursorPoint.getX(), cursorPoint.getY());
}
public int distanceInPixels(final MapPos cursorOnMap) {
//TODO jaanus : check this
return 0;
}
public Label getLabel() {
return label;
}
public WgsPoint[] getPoints() {
return coordinates;
}
private boolean viewWithinBoundingBox(final int viewX, final int viewY, final int viewW,
final int viewH) {
return Utils.rectanglesIntersect(boundingBoxMin.getX(), boundingBoxMin.getY(), boundingBoxMax
.getX()
- boundingBoxMin.getX(), boundingBoxMax.getY() - boundingBoxMin.getY(), viewX, viewY,
viewW, viewH);
}
public void setStyle(final PolyStyle style) {
this.style = style;
}
}