/*
* Copyright (C) 2012 Dr. John Lindsay <jlindsay@uoguelph.ca>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package whitebox.cartographic;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import whitebox.cartographic.NorthArrowMarkers.MarkerStyle;
import whitebox.interfaces.CartographicElement;
/**
*
* @author johnlindsay
*/
public class NorthArrow implements CartographicElement, Comparable<CartographicElement> {
private String cartoElementType = "NorthArrow";
boolean visible = true;
boolean selected = false;
String name = "north arrow";
int number = -1;
int x = -32768;
int y = -32768;
int markerSize = 35;
int halfMarkerSize = markerSize / 2;
int margin = 4;
boolean borderVisible = false;
boolean backgroundVisible = false;
Color backColour = Color.WHITE;
Color borderColour = Color.BLACK;
Color outlineColour = Color.BLACK;
MarkerStyle markerStyle = MarkerStyle.STANDARD;
float lineWidth = 0.75f;
private int selectedOffsetX;
private int selectedOffsetY;
public NorthArrow(String name) {
this.name = name;
}
@Override
public boolean isVisible() {
return visible;
}
@Override
public void setVisible(boolean visible) {
this.visible = visible;
x = -1;
y = -1;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getMarkerSize() {
return markerSize;
}
public void setMarkerSize(int markerSize) {
this.markerSize = markerSize;
this.halfMarkerSize = markerSize / 2;
}
public MarkerStyle getMarkerStyle() {
return markerStyle;
}
public void setMarkerStyle(MarkerStyle markerStyle) {
this.markerStyle = markerStyle;
}
public int getHeight() {
return markerSize;
}
public int getWidth() {
return markerSize;
}
public Color getOutlineColour() {
return outlineColour;
}
public void setOutlineColour(Color outlineColour) {
this.outlineColour = outlineColour;
}
@Override
public int getUpperLeftX() {
return x - halfMarkerSize;
}
@Override
public int getUpperLeftY() {
return y - halfMarkerSize;
}
@Override
public void setUpperLeftX(int x) {
this.x = x + halfMarkerSize;
}
@Override
public void setUpperLeftY(int y) {
this.y = y + halfMarkerSize;
}
@Override
public int getLowerRightX() {
return x + halfMarkerSize;
}
@Override
public int getLowerRightY() {
return y + halfMarkerSize;
}
@Override
public int getSelectedOffsetX() {
return selectedOffsetX;
}
@Override
public void setSelectedOffsetX(int selectedOffsetX) {
this.selectedOffsetX = selectedOffsetX;
}
@Override
public int getSelectedOffsetY() {
return selectedOffsetY;
}
@Override
public void setSelectedOffsetY(int selectedOffsetY) {
this.selectedOffsetY = selectedOffsetY;
}
public Color getBackColour() {
return backColour;
}
public void setBackColour(Color backColour) {
this.backColour = backColour;
}
public boolean isBackgroundVisible() {
return backgroundVisible;
}
public void setBackgroundVisible(boolean backgroundVisible) {
this.backgroundVisible = backgroundVisible;
}
public Color getBorderColour() {
return borderColour;
}
public void setBorderColour(Color borderColour) {
this.borderColour = borderColour;
}
public boolean isBorderVisible() {
return borderVisible;
}
public void setBorderVisible(boolean borderVisible) {
this.borderVisible = borderVisible;
}
public int getMargin() {
return margin;
}
public void setMargin(int margin) {
if (margin > markerSize) {
markerSize = margin * 3;
halfMarkerSize = markerSize / 2;
}
this.margin = margin;
}
// public double getRotation() {
// return
// }
public ArrayList<GeneralPath> getMarkerData() {
ArrayList<GeneralPath> ret = new ArrayList<GeneralPath>();
markerDrawingInstructions.clear();
GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 1);
double[][] xyData = NorthArrowMarkers.getMarkerData(markerStyle, markerSize - 2 * margin);
boolean drawing = false;
for (int a = 0; a < xyData.length; a++) {
if (xyData[a][0] == 0) { // moveTo no fill
if (drawing) {
ret.add(gp);
}
drawing = true;
markerDrawingInstructions.add(new Integer(0));
gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 1);
gp.moveTo(x + xyData[a][1], y + xyData[a][2]);
} else if (xyData[a][0] == 1) { // lineTo
gp.lineTo(x + xyData[a][1], y + xyData[a][2]);
} else if (xyData[a][0] == 2) { // elipse2D
Ellipse2D circle = new Ellipse2D.Double((x - xyData[a][1]), (y - xyData[a][1]), xyData[a][2], xyData[a][2]);
gp.append(circle, true);
} else if (xyData[a][0] == 3) { // moveTo with fill
if (drawing) {
ret.add(gp);
}
drawing = true;
markerDrawingInstructions.add(new Integer(1));
gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 1);
gp.moveTo(x + xyData[a][1], y + xyData[a][2]);
}
}
ret.add(gp);
return ret;
}
ArrayList<Integer> markerDrawingInstructions = new ArrayList<Integer>();
public ArrayList<Integer> getMarkerDrawingInstructions() {
return markerDrawingInstructions;
}
@Override
public boolean isSelected() {
return selected;
}
@Override
public void setSelected(boolean selected) {
this.selected = selected;
}
@Override
public int getElementNumber() {
return number;
}
@Override
public void setElementNumber(int number) {
this.number = number;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
public float getLineWidth() {
return lineWidth;
}
public void setLineWidth(float lineWidth) {
this.lineWidth = lineWidth;
}
@Override
public int compareTo(CartographicElement other) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
// compare them based on their element (overlay) numbers
if (this.number < other.getElementNumber()) {
return BEFORE;
} else if (this.number > other.getElementNumber()) {
return AFTER;
}
return EQUAL;
}
@Override
public void resize(int newX, int newY, int resizeMode) {
int minMarkerSize = 20;
int deltaX = 0;
int deltaY = 0;
switch (resizeMode) {
case 0: // off the north edge
deltaY = newY - (y - markerSize / 2);
if (markerSize - 2 * deltaY >= minMarkerSize) {
markerSize -= 2 * deltaY;
}
break;
case 1: // off the south edge
deltaY = newY - (y + markerSize / 2);
if (markerSize + 2 * deltaY >= minMarkerSize) {
markerSize += 2 * deltaY;
}
break;
case 2: // off the east edge
deltaX = newX - (x + markerSize / 2);
if (markerSize + 2 * deltaX >= minMarkerSize) {
markerSize += 2 * deltaX;
}
break;
case 3: // off the west edge
deltaX = newX - (x - markerSize / 2);
if (markerSize - 2 * deltaX >= minMarkerSize) {
markerSize -= 2 * deltaX;
}
break;
case 4: // off the northeast edge
deltaY = newY - (y - markerSize / 2);
if (markerSize - 2 * deltaY >= minMarkerSize) {
markerSize -= 2 * deltaY;
}
deltaX = newX - (x + markerSize / 2);
if (markerSize + 2 * deltaX >= minMarkerSize) {
markerSize += 2 * deltaX;
}
break;
case 5: // off the northwest edge
deltaY = newY - (y - markerSize / 2);
if (markerSize - 2 * deltaY >= minMarkerSize) {
markerSize -= 2 * deltaY;
}
deltaX = newX - (x - markerSize / 2);
if (markerSize - 2 * deltaX >= minMarkerSize) {
markerSize -= 2 * deltaX;
}
break;
case 6: // off the southeast edge
deltaY = newY - (y + markerSize / 2);
if (markerSize + 2 * deltaY >= minMarkerSize) {
markerSize += 2 * deltaY;
}
deltaX = newX - (x + markerSize / 2);
if (markerSize + 2 * deltaX >= minMarkerSize) {
markerSize += 2 * deltaX;
}
break;
case 7: // off the southwest edge
deltaY = newY - (y + markerSize / 2);
if (markerSize + 2 * deltaY >= minMarkerSize) {
markerSize += 2 * deltaY;
}
deltaX = newX - (x - markerSize / 2);
if (markerSize - 2 * deltaX >= minMarkerSize) {
markerSize -= 2 * deltaX;
}
break;
}
}
@Override
public CartographicElementType getCartographicElementType() {
return CartographicElementType.NORTH_ARROW;
}
}