package com.nutiteq.components; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import com.nutiteq.log.Log; import com.nutiteq.maps.GeoMap; import com.nutiteq.utils.Utils; /** * Place object to be used for showing location points on maps. */ public class Place implements OnMapElement { private static final int CLICK_BOX_SIZE = 16; private Placemark defaultPlacemark; private Placemark activePlacemark; private WgsPoint wgs; private MapPos mapPosition; private final Label label; private final int id; private OnMapElement[] elements; private final boolean serverSideRender; private boolean centered; // TODO jaanus : do something about all these overloaded constructors public Place(final int id, final String name, final Image icon, final WgsPoint coordinates) { this(id, name, new PlaceIcon(icon, icon.getWidth() / 2, icon .getHeight() / 2), coordinates); } public Place(final int id, final String name, final Placemark icon, final WgsPoint coordinates) { this(id, (name == null) ? null : new PlaceLabel(name), icon, coordinates, false); } public Place(final int id, final Label label, final Placemark icon, final WgsPoint coordinates) { this(id, label, icon, coordinates, false); } public Place(final int id, final Label label, final Placemark defaultPlacemark, final Placemark activePlacemark, final WgsPoint coordinates) { this(id, label, defaultPlacemark, activePlacemark, coordinates, false); } public Place(final int id, final Label label, final Placemark defaultPlacemark, final Placemark activePlacemark, final WgsPoint coordinates, final boolean serverSideRender) { this.id = id; this.label = label; this.defaultPlacemark = defaultPlacemark; this.activePlacemark = activePlacemark; wgs = coordinates; this.serverSideRender = serverSideRender; if (label != null && (label instanceof PlaceLabel)) { ((PlaceLabel) label).setUsedIcon(defaultPlacemark); } } public Place(final int id, final Label label, final Placemark icon, final WgsPoint coordinates, final boolean serverSideRender) { this(id, label, icon, icon, coordinates, serverSideRender); } public Place(final int id, final String name, final Image icon, final double lonWgs, final double latWgs) { this(id, name, icon, new WgsPoint(lonWgs, latWgs)); } public Place(final int id, final Label label, final Image icon, final WgsPoint coordinates) { this(id, label, new PlaceIcon(icon, icon.getWidth() / 2, icon .getHeight() / 2), coordinates, false); } public Place(final int id, final Label label, final Image icon, final double lonWgs, final double latWgs) { this(id, label, new PlaceIcon(icon, icon.getWidth() / 2, icon .getHeight() / 2), new WgsPoint(lonWgs, latWgs), false); } /** * Place coordinates in WGS84 * * @return coordinates in WGS84 */ public WgsPoint getWgs() { return wgs; } /** * Not part of public API * * @return map position on pixel map */ public MapPos getMapPosition() { return mapPosition; } /** * Get place name * * @return name */ public String getName() { return label.getLabel(); } /** * Get place label * * @return place label */ public Label getLabel() { return label; } /** * Get place icon * * @return place icon */ public Image getIcon() { return (defaultPlacemark instanceof PlaceIcon) ? ((PlaceIcon) defaultPlacemark) .getIcon() : null; } public Placemark getPlacemark() { return defaultPlacemark; } /** * Get place id * * @return place id */ public int getId() { return id; } public boolean isVisible(final int viewX, final int viewY, final int viewWidth, final int viewHeight, final int zoom) { if (wgs != null && mapPosition != null && defaultPlacemark != null) { if (Utils.rectanglesIntersect(viewX, viewY, viewWidth, viewHeight, mapPosition.getX() - defaultPlacemark.getAnchorX(zoom), mapPosition.getY() - defaultPlacemark.getAnchorY(zoom), defaultPlacemark.getWidth(zoom), defaultPlacemark .getHeight(zoom))) { return true; } } if (elements != null && elements.length > 0) { for (int i = 0; i < elements.length; i++) { if (elements[i].isVisible(viewX, viewY, viewWidth, viewHeight, zoom)) { return true; } } } return false; } /** * Not part of public API */ public void paint(final Graphics g, final MapPos middlePoint, final int displayCenterX, final int displayCenterY, final Rectangle changedMapArea) { if (serverSideRender) { return; } if (elements != null) { for (int i = 0; i < elements.length; i++) { elements[i].paint(g, middlePoint, displayCenterX, displayCenterY, changedMapArea); } } if (wgs == null) { return; } final Placemark usedPlacemark = centered ? activePlacemark : defaultPlacemark; final int topX = mapPosition.getX() - middlePoint.getX() + displayCenterX - usedPlacemark.getAnchorX(middlePoint.getZoom()); final int topY = mapPosition.getY() - middlePoint.getY() + displayCenterY - usedPlacemark.getAnchorY(middlePoint.getZoom()); usedPlacemark.paint(g, topX, topY, middlePoint.getZoom()); } public boolean isCentered(final MapPos middlePoint) { if (mapPosition != null && defaultPlacemark != null) { Log.debug("placeMark " + this.getName()); Log.debug("mapPosition " + mapPosition + " middlePoint " + middlePoint + " " + middlePoint); int diffx = mapPosition.getX() - middlePoint.getX(); int diffy = mapPosition.getY() - middlePoint.getY(); Log.debug("diffx " + diffx + " y " + diffy); if ((Math.abs(diffx) < CLICK_BOX_SIZE) && (Math.abs(diffy) < CLICK_BOX_SIZE)) { Log.debug("Clicked " + this.getName()); return true; } else { Log.debug("NOT clicked " + this.getName()); } // return Utils.rectanglesIntersect(middlePoint.getX(), // middlePoint.getY(), CLICK_BOX_SIZE, CLICK_BOX_SIZE, mapPosition // .getX() // - defaultPlacemark.getAnchorX(middlePoint.getZoom()), // mapPosition.getY() // - defaultPlacemark.getAnchorY(middlePoint.getZoom()), // defaultPlacemark // .getWidth(middlePoint.getZoom()), // defaultPlacemark.getHeight(middlePoint.getZoom())); } if (elements != null && elements.length > 0) { for (int i = 0; i < elements.length; i++) { if (elements[i].isCentered(middlePoint)) { return true; } } } return false; } public boolean equals(final Object obj) { if (obj == this) { return true; } // TODO jaanus : looks like bad design if (obj instanceof KmlPlace) { final Place p = ((KmlPlace) obj).getPlace(); return equals(p); } if (!(obj instanceof Place)) { return false; } final Place other = (Place) obj; if (elements != null && other.elements != null && elements.length > 0 && elements.length == other.elements.length) { for (int i = 0; i < elements.length; i++) { if (!elements[i].equals(other.elements[i])) { return false; } } return true; } else { return wgs != null && other.wgs != null && wgs.toInternalWgs().equals(other.wgs.toInternalWgs()) && ((label == null && other.label == null) || (label != null && label .equals(other.label))); } } public int hashCode() { throw new RuntimeException("hashCode() not implemented!"); } /** * Not part of public API */ public void setIcon(final Image image) { if (image == null) { defaultPlacemark = null; } else { this.setIcon(image, image.getWidth() / 2, image.getHeight() / 2); } } /** * Set the icon for this place and the icon anchor position. * * @param image * icon used * @param anchorX * icon anchor position (x) * @param anchorY * icon anchor position (y) */ private void setIcon(final Image image, final int anchorX, final int anchorY) { defaultPlacemark = new PlaceIcon(image, anchorX, anchorY); activePlacemark = new PlaceIcon(image, anchorX, anchorY); if (label != null && (label instanceof PlaceLabel)) { ((PlaceLabel) label).setUsedIcon(defaultPlacemark); } } /** * Not part of public API */ public void setOnMapElements(final OnMapElement[] elements) { this.elements = elements; } /** * Not part of public API */ public void calculatePosition(final GeoMap displayedMap, final int zoomLevel) { if (wgs != null) { // if we have some concrete place, like POI, not some area or line mapPosition = displayedMap.wgsToMapPos(wgs.toInternalWgs(), zoomLevel); } if (elements != null && elements.length > 0) { for (int i = 0; i < elements.length; i++) { elements[i].calculatePosition(displayedMap, zoomLevel); } } } /** * Not part of public API */ public OnMapElement[] getElements() { return elements; } /** * Set the point for this place. Should only be called before adding the * place to the map. * * @param p * new point * @deprecated since 0.4.0 */ public void setWgs(WgsPoint p) { // if we call this after the point is added to the map, we should also // call // calculatePosition, but we can't do that because we don't know the // GeoMap // that contains this point this.wgs = p; } public int distanceInPixels(final MapPos middlePoint) { if (mapPosition != null) { return mapPosition.distanceInPixels(middlePoint); } if (elements != null && elements.length > 0) { int distance = Integer.MAX_VALUE; for (int i = 0; i < elements.length; i++) { distance = Math.min(distance, elements[i] .distanceInPixels(middlePoint)); if (distance == 0) { break; } } return distance; } return Integer.MAX_VALUE; } public void labelClicked(final MapPos middlePoint, final int displayWidth, final int displayHeight, final int clickX, final int clickY) { if (label == null) { return; } final int screenX = mapPosition.getX() - middlePoint.getX() + displayWidth / 2; final int screenY = mapPosition.getY() - middlePoint.getY() + displayHeight / 2; label.labelClicked(screenX, screenY, displayWidth, displayHeight, clickX, clickY); } public boolean pointOnLabel(final MapPos middlePoint, final int displayWidth, final int displayHeight, final int clickX, final int clickY) { if (label == null || mapPosition == null) { return false; } final int screenX = mapPosition.getX() - middlePoint.getX() + displayWidth / 2; final int screenY = mapPosition.getY() - middlePoint.getY() + displayHeight / 2; return label.pointOnLabel(screenX, screenY, displayWidth, displayHeight, clickX, clickY); } public Point getLabelViewUpdate(final MapPos middlePoint, final int displayWidth, final int displayHeight) { if (label == null || mapPosition == null) { return null; } final int screenX = mapPosition.getX() - middlePoint.getX() + displayWidth / 2; final int screenY = mapPosition.getY() - middlePoint.getY() + displayHeight / 2; return label.getViewUpdate(screenX, screenY, displayWidth, displayHeight); } public void setIsActive(final boolean nextActivityState) { centered = nextActivityState; } public Rectangle toMapArea(final int zoom) { // TODO jaanus : can placemarks be null? if (mapPosition != null) { final Rectangle activeArea = new Rectangle(mapPosition.getX() - activePlacemark.getAnchorX(zoom), mapPosition.getY() - activePlacemark.getAnchorY(zoom), activePlacemark .getWidth(zoom), activePlacemark.getHeight(zoom)); final Rectangle defaultArea = new Rectangle(mapPosition.getX() - defaultPlacemark.getAnchorX(zoom), mapPosition.getY() - defaultPlacemark.getAnchorY(zoom), defaultPlacemark .getWidth(zoom), defaultPlacemark.getHeight(zoom)); return Utils.mergeAreas(activeArea, defaultArea); } return new Rectangle(0, 0, 0, 0); } public WgsPoint[] getPoints() { final WgsPoint[] ret = { wgs }; return ret; } }