/*
* Copyright 2013 Serdar.
*
* 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 de.fub.agg2graphui.layers;
import com.infomatiq.jsi.rtree.RTree;
import de.fub.agg2graph.structs.GPSPoint;
import de.fub.agg2graph.structs.GPSSegment;
import de.fub.agg2graph.structs.ILocation;
import de.fub.agg2graph.ui.gui.RenderingOptions;
import de.fub.agg2graphui.controller.AbstractLayer;
import de.fub.mapviewer.ui.MapViewer;
import gnu.trove.TIntProcedure;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import org.jdesktop.swingx.mapviewer.GeoPosition;
/**
*
* @author Serdar
*/
public class GPSSegmentLayer extends AbstractLayer<GPSSegment> {
private RTree rtree;
private final HashMap<Integer, GPSSegment> META_DATA = new HashMap<Integer, GPSSegment>();
public GPSSegmentLayer(String name, RenderingOptions renderingOptions) {
super(name, renderingOptions);
reset();
}
public GPSSegmentLayer(String name, String description, RenderingOptions renderingOptions) {
super(name, description, renderingOptions);
reset();
}
private void reset() {
META_DATA.clear();
Properties p = new Properties();
p.setProperty("MinNodeEntries", "10");
p.setProperty("MaxNodeEntries", "50");
rtree = new RTree();
rtree.init(p);
}
@Override
public void add(GPSSegment item) {
super.add(item); //To change body of generated methods, choose Tools | Templates.
if (!META_DATA.containsKey(item.hashCode())) {
com.infomatiq.jsi.Rectangle boundingBox = getBoundingBox(item);
rtree.add(boundingBox, item.hashCode());
META_DATA.put(item.hashCode(), item);
}
}
@Override
public void addAll(Collection<GPSSegment> items) {
for (GPSSegment item : items) {
add(item);
}
}
@Override
public void remove(GPSSegment item) {
super.remove(item);
if (META_DATA.containsKey(item.hashCode())) {
com.infomatiq.jsi.Rectangle boundingBox = getBoundingBox(item);
rtree.delete(boundingBox, item.hashCode());
}
}
@Override
public void clearRenderObjects() {
super.clearRenderObjects(); //To change body of generated methods, choose Tools | Templates.
reset();
}
@Override
protected void drawDrawables(Graphics2D graphics, Rectangle rectangle) {
MapViewer mapViewer = getLayerManager().getMapViewer();
Dimension size = mapViewer.getSize();
GeoPosition position = mapViewer.convertPointToGeoPosition(new Point2D.Double(0, 0));
GeoPosition position1 = mapViewer.convertPointToGeoPosition(new Point2D.Double(size.width, size.height));
com.infomatiq.jsi.Rectangle rectangle1 = new com.infomatiq.jsi.Rectangle((float) position.getLongitude(),
(float) position.getLatitude(),
(float) position1.getLongitude(),
(float) position1.getLatitude());
rtree.intersects(rectangle1, new GPSSegmentSeachProcedure());
}
private com.infomatiq.jsi.Rectangle getBoundingBox(GPSSegment segment) {
Area area = new Area();
for (ILocation location : segment) {
// the added shape must have at least a size > 0
area.add(new Area(new Rectangle2D.Double(location.getLon(), location.getLat(), 0.0000000001, 0.0000000001)));
}
Rectangle2D boundingBox = area.getBounds2D();
float minLong = (float) boundingBox.getMinX();
float maxLat = (float) boundingBox.getMinY();
float maxLong = (float) boundingBox.getMaxX();
float minLat = (float) boundingBox.getMaxY();
com.infomatiq.jsi.Rectangle rectangle = new com.infomatiq.jsi.Rectangle(minLong, maxLat, maxLong, minLat);
return rectangle;
}
private class GPSSegmentSeachProcedure implements TIntProcedure {
private final HashSet<GPSSegment> segments = new HashSet<GPSSegment>(100);
public GPSSegmentSeachProcedure() {
}
@Override
public boolean execute(int value) {
GPSSegment segment = META_DATA.get(value);
GPSPoint lastPoint = null;
if (segment != null) {
for (GPSPoint point : segment) {
if (getLayerManager().getMapViewer().convertGeoPositionToPoint(new GeoPosition(point.getLat(), point.getLon())) != null) {
if (lastPoint != null) {
drawLine(lastPoint, point, getRenderingOptions());
}
drawPoint(point, getRenderingOptions());
}
lastPoint = point;
}
}
return true;
}
public Collection<GPSSegment> getSegments() {
return segments;
}
}
}