/*license*\
XBN-Java: http://xbnjava.aliteralmind.com
Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
This software is dual-licensed under the:
- Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
- Apache Software License (ASL) version 2.0.
Either license may be applied at your discretion. More information may be found at
- http://en.wikipedia.org/wiki/Multi-licensing.
The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
- LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
- ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package com.github.xbn.util.matrix;
import com.github.xbn.lang.CrashIfObject;
/**
* <p>The distance and direction between two elements.</p>
*
* {@.codelet.and.out com.github.xbn.examples.util.matrix.DistanceDirectionXmpl%eliminateCommentBlocksAndPackageDecl()}
* @since 0.1.5
* @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://xbnjava.aliteralmind.com">{@code http://xbnjava.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/xbnjava">{@code https://github.com/aliteralmind/xbnjava}</a>
*/
public class DistanceDirection extends AbstractElement {
private final MatrixDirection dir;
/**
* <p>Create a new item from its elements.</p>
* @param horiz_dist The number of columns the end is away from
* the start element. For example, if the start and end elements
* are {@code [1, 1]} and {@code [2, 1]}, respectively, then
* {@code horiz_dist} is one. Get with {@link #getHorizDistance() getHorizDistance}{@code ()}.
* @param vert_dist The number of rows the end is away from
* the start element. For example, if the start and end elements
* are {@code [1, 1]} and {@code [2, 1]}, respectively, then
* {@code horiz_dist} is zero. If zero, both items are in the same row.
* Get with {@link #getVertDistance() getVertDistance}{@code ()}.
*/
public DistanceDirection(int horiz_dist, int vert_dist) {
super(horiz_dist, vert_dist);
dir = getDirectionFromDistances(horiz_dist, vert_dist);
}
/**
* The direction between the two elements, if it happens to be a
* directly horizontal, vertical, or diagonal.
* @return The direction between the two elements. If {@code null},
* then either both elements are the same, or the direction is not
* directly left, right, up, down, up-left, up-right, down-left, or
* down-right.
*/
public MatrixDirection getDirection() {
return dir;
}
/**
* The number of horizontal spaces the second element is from the first.
* @return {@link AbstractElement#getColumnIndex() getColumnIndex}{@code ()} (Equivalent to {@code horiz_dist}, as provided to the {@linkplain #DistanceDirection(int, int) constructor})
*/
public int getHorizDistance() {
return getColumnIndex();
}
/**
* The number of vertical spaces the second element is from the first.
* @return {@link AbstractElement#getRowIndex() getRowIndex}{@code ()} (Equivalent to {@code vert_dist}, as provided to the {@linkplain #DistanceDirection(int, int) constructor})
*/
public int getVertDistance() {
return getRowIndex();
}
/**
* @return <code>{@link #appendToString(java.lang.StringBuilder) appendToString}(new {@link java.lang.StringBuilder#StringBuilder() StringBuilder}()).toString()</code>
*/
public String toString() {
return appendToString(new StringBuilder()).toString();
}
/**
* @param bldr May not be <code>null</code>.
* @see #toString()
*/
public StringBuilder appendToString(StringBuilder bldr) {
try {
bldr.append("[horiz=").append(getHorizDistance()).append(",vert=").append(getVertDistance()).append("]").append("direction=").
append((getDirection() != null) ? getDirection()
: "SELF-OR-UNKNOWN");
} catch(NullPointerException npx) {
CrashIfObject.nullOrReturnCause(bldr, "bldr", null, npx);
}
return bldr;
}
public static final DistanceDirection newForStartEnd(MatrixElement start,
MatrixElement end) {
return new DistanceDirection(start.getHorizDistance(end),
start.getVertDistance(end));
}
/**
*
* @param start May not be <code>null</code>
* @param end May not be <code>null</code>
* @return <blockquote><pre>{@link #getDirectionFromDistances(int, int) getDirectionFromDistances}(start.{@link MatrixElement#getHorizDistance(MatrixElement) getHorizDistance}(end),
* start.{@link MatrixElement#getVertDistance(MatrixElement) getVertDistance}(end))</pre></blockquote>
*/
public static final MatrixDirection getDirectionFromDistances(
MatrixElement start, MatrixElement end) {
return getDirectionFromDistances(start.getHorizDistance(end),
start.getVertDistance(end));
}
/**
* Given the relative distances, get the direction between two
* elements.
* @param horiz_dist The difference between the start and end
* elements' horizontal values. Specifically,
* <br/> <code><i>[end-coord]</i>.{@link MatrixElement#getColumnIndex() getColumnIndex}() - <i>[start-coord]</i>.getColumnIndex()</code>
* @param vert_dist The difference between the start and end
* elements' vertical values. Specifically,
* <br/> <code><i>[end-coord]</i>.{@link MatrixElement#getRowIndex() getRowIndex}() - <i>[start-coord]</i>.getRowIndex()</code>
* @return If the distances are both zero, or the direction is not
* directly horizontal, vertical, or forty-five degrees diagonal, this
* returns {@code null}. Otherwise, this returns the direction between
* the two.
* @see #getDirectionFromDistances(com.github.xbn.util.matrix.MatrixElement, com.github.xbn.util.matrix.MatrixElement)
*/
public static final MatrixDirection getDirectionFromDistances(int horiz_dist, int vert_dist) {
MatrixDirection dir = null;
if(horiz_dist != 0) {
if(vert_dist == 0) {
dir = ((horiz_dist < 0) ? MatrixDirection.LEFT : MatrixDirection.RIGHT);
} else if(Math.abs(horiz_dist) == Math.abs(vert_dist)) {
//Directly diagonal
if(horiz_dist < 0) {
//This is to the left
dir = ((vert_dist < 0) ? MatrixDirection.UP_LEFT: MatrixDirection.DOWN_LEFT);
} else {
//This is to the right
dir = ((vert_dist < 0) ? MatrixDirection.UP_RIGHT: MatrixDirection.DOWN_RIGHT);
}
} //Not directly diagonal, vert_distical, or horizontal
} else if(vert_dist != 0) {
//Horiz is zero, vert_dist is not
dir = ((vert_dist < 0) ? MatrixDirection.UP : MatrixDirection.DOWN);
}
return dir;
}
/**
* <p>Get a reference to <i>this</i> object.</p>
* @return <i>{@code this}</i>
*/
public DistanceDirection getObjectCopy() {
return this;
}
}