package com.spatialdev.osm.renderer;
import android.graphics.Paint;
import android.graphics.Path;
import com.mapbox.mapboxsdk.views.MapView;
import com.spatialdev.osm.model.OSMWay;
/**
* Created by Nicholas Hallahan on 1/22/15.
* nhallahan@spatialdev.com
*/
public class OSMLine extends OSMPath {
// OSM GREEN
public static final int DEFAULT_A = 125;
public static final int DEFAULT_R = 126;
public static final int DEFAULT_G = 188;
public static final int DEFAULT_B = 111;
public static final float DEFAULT_WIDTH = 13.0f;
// GOLD
public static final int DEFAULT_SELECTED_A = 180;
public static final int DEFAULT_SELECTED_R = 255;
public static final int DEFAULT_SELECTED_G = 140;
public static final int DEFAULT_SELECTED_B = 0;
public static final float DEFAULT_SELECTED_WIDTH = 15.0f;
// MAROON
public static final int DEFAULT_EDITED_A = 100;
public static final int DEFAULT_EDITED_R = 245;
public static final int DEFAULT_EDITED_G = 17;
public static final int DEFAULT_EDITED_B = 135;
private float width;
private int a;
private int r;
private int g;
private int b;
/**
* This should only be constructed by
* OSMPath.createOSMPath
* * * *
* @param w
*/
protected OSMLine(OSMWay w, MapView mv) {
super(w, mv);
// color polygon according to if it has been edited before
if (w.isModified()) {
this.a = DEFAULT_EDITED_A;
this.r = DEFAULT_EDITED_R;
this.g = DEFAULT_EDITED_G;
this.b = DEFAULT_EDITED_B;
} else {
this.a = DEFAULT_A;
this.r = DEFAULT_R;
this.g = DEFAULT_G;
this.b = DEFAULT_B;
}
width = DEFAULT_WIDTH;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setARGB(a, r, g, b);
setStrokeWidth(width);
}
@Override
public void select() {
paint.setARGB(DEFAULT_SELECTED_A, DEFAULT_SELECTED_R, DEFAULT_SELECTED_G, DEFAULT_SELECTED_B);
setStrokeWidth(DEFAULT_SELECTED_WIDTH);
}
@Override
public void deselect() {
paint.setARGB(a, r, g, b);
setStrokeWidth(width);
}
/**
* ^_^ !!! NICK'S DANGLING VERTEX LINE CLIPPER !!! ^_^
*
* For lines, we only want to draw paths if they are inside of the viewport.
* So, if the path is inside the viewport, we should either start the drawing
* point (moveTo), or connect the drawing point (lineTo).
*
* If it is outside of the viewport, we should do nothing but tell the canvas
* that it should start a new line (moveTo) next time it reenters the viewport.
*
* Unless the next vertex is in the viewport. Then we DO want to draw it.
*
* If I had more time, I'd do the trig to get you that vertex right on the viewport's
* edge.
*
* * * * * * * * * * * * * * *
* @param path
* @param projectedPoint
* @param screenPoint
*/
@Override
void clipOrDrawPath(Path path, double[] projectedPoint, double[] nextProjectedPoint, double[] screenPoint) {
int projX = (int) projectedPoint[0];
int projY = (int) projectedPoint[1];
if (viewPortBounds.contains(projX, projY)) {
if (pathLineToReady) {
path.lineTo( (float) screenPoint[0], (float) screenPoint[1] );
} else {
path.moveTo( (float) screenPoint[0], (float) screenPoint[1] );
pathLineToReady = true;
}
} else {
// last vertex was in the viewport, we want to make this last one dangle
if (pathLineToReady) {
path.lineTo( (float) screenPoint[0], (float) screenPoint[1] );
// If we're going back in, we want to move to the vertex...
pathLineToReady = false;
return;
}
/**
* If the next vertex is in the viewport, we want this vertex to be drawn.
* Think of this as allowing the drawing of 1 dangling vertex outside of
* the viewport. I'd be fine with drawing everything, but if it's too far out,
* the android canvas seg faults. (Wishing i could be closer to the metal...)
*/
if (nextProjectedPoint != null) {
int projXNext = (int) nextProjectedPoint[0];
int projYNext = (int) nextProjectedPoint[1];
if (viewPortBounds.contains(projXNext, projYNext)) {
path.moveTo( (float) screenPoint[0], (float) screenPoint[1] );
pathLineToReady = true;
}
}
/**
* The only other situation, the point is the last and the one before
* it was also outside of the viewport, obviously we do nothing...* *
*/
}
}
}