/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package armyc2.c2sd.JavaLineArray;
/**
* A class to provide the utility functions required for calculating the line
* points.
*
* @author Michael Deutch
*/
import java.util.ArrayList;
import armyc2.c2sd.renderer.utilities.ErrorLogger;
import armyc2.c2sd.renderer.utilities.RendererException;
import armyc2.c2sd.renderer.utilities.RendererSettings;
import java.io.*;
import armyc2.c2sd.graphics2d.*;
import armyc2.c2sd.renderer.utilities.IPointConversion;
import armyc2.c2sd.JavaTacticalRenderer.mdlGeodesic;
public final class lineutility {
private static final String _className = "lineutility";
public static final int extend_left = 0;
public static final int extend_right = 1;
public static final int extend_above = 2;
public static final int extend_below = 3;
/**
* Resizes the array to the length speicifed, called by the Channels class.
*
* @param pLinePoints the array to resize
* @param length the length to which to resize the array.
* @return the resized array
*/
protected static POINT2[] ResizeArray(POINT2[] pLinePoints, int length) {
POINT2[] array = new POINT2[length];
try {
if (pLinePoints.length <= length) {
return pLinePoints;
}
int j = 0;
for (j = 0; j < length; j++) {
array[j] = new POINT2(pLinePoints[j]);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ResizeArray",
new RendererException("Failed inside ResizeArray", exc));
}
return array;
}
/**
* post-segments a line segment into 50 pixel intervals
*
* @param pt0
* @param pt1
* @param shape
*/
protected static void SegmentLineShape(POINT2 pt0, POINT2 pt1, Shape2 shape) {
try {
if (pt0 == null || pt1 == null) {
return;
}
int j = 0, n = 0;
double dist = CalcDistanceDouble(pt0, pt1);
n = (int) (dist / 25d);
POINT2 pt = null;
shape.lineTo(pt0);
for (j = 1; j <= n; j++) {
pt = lineutility.ExtendAlongLineDouble(pt0, pt1, 25);
shape.lineTo(pt);
}
shape.lineTo(pt1);
} catch (Exception exc) {
ErrorLogger.LogException(_className, "SegmentLineShape",
new RendererException("Failed inside SegmentLineShape", exc));
}
}
/**
* Calculates the middle segment for the Direction of Attack Aviation symbol
*
* @param pLinePoints the point array
* @param vblSaveCounter the size of the point array
* @return the middle segment
*/
public static int GetDirAtkAirMiddleSegment(POINT2[] pLinePoints,
int vblSaveCounter) {
int middleSegment = -1;
try {
double d = 0;
int k = 0;
for (k = vblSaveCounter - 1; k > 0; k--) {
d += lineutility.CalcDistanceDouble(pLinePoints[k], pLinePoints[k - 1]);
if (d > 60) {
break;
}
}
if (d > 60) {
middleSegment = k;
} else {
if (vblSaveCounter <= 3) {
middleSegment = 1;
} else {
middleSegment = 2;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetDirAtkAirMiddleSegment",
new RendererException("Failed inside GetDirAtkAirMiddleSegment", exc));
}
return middleSegment;
}
/**
* Computes the angle in radians between two points
*
* @param pt0 the first point
* @param pt1 the last point
*
* @return the angle in radians
*/
protected static double CalcSegmentAngleDouble(POINT2 pt0,
POINT2 pt1) {
double dAngle = 0;
try {
//declarations
int nTemp = 0;
ref<double[]> m = new ref();
//end declarations
nTemp = CalcTrueSlopeDouble(pt0, pt1, m);
if (nTemp == 0) {
dAngle = Math.PI / 2;
} else {
dAngle = Math.atan(m.value[0]);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcSegmentAngleDouble",
new RendererException("Failed inside CalcSegmentAngleDouble", exc));
}
return dAngle;
}
/**
* POINT2 in previous applications has been a struct that did not require
* initialization.
*
* @param pts array of points to instantiate.
*/
protected static void InitializePOINT2Array(POINT2[] pts) {
//int j=0;
if (pts == null || pts.length == 0) {
return;
}
int n=pts.length;
//for (int j = 0; j < pts.length; j++)
for (int j = 0; j < n; j++)
{
pts[j] = new POINT2();
}
}
/**
* Calculates the center point of an area using the first vblCounter points
* in the array.
*
* @param pLinePoints the client points
* @param vblCounter the number of points in the array to use
*
* @return the center point
*/
protected static POINT2 CalcCenterPointDouble(POINT2[] pLinePoints,
int vblCounter) {
POINT2 CenterLinePoint = new POINT2(pLinePoints[0]);
try {
//declarations
int j = 0;
double dMinX = pLinePoints[0].x,
dMinY = pLinePoints[0].y,
dMaxX = pLinePoints[0].x,
dMaxY = pLinePoints[0].y;
//end declarations
dMinX = pLinePoints[0].x;
dMinY = pLinePoints[0].y;
dMaxX = pLinePoints[0].x;
dMaxY = pLinePoints[0].y;
for (j = 0; j < vblCounter; j++) {
if (pLinePoints[j].x < dMinX) {
dMinX = pLinePoints[j].x;
}
if (pLinePoints[j].y < dMinY) {
dMinY = pLinePoints[j].y;
}
if (pLinePoints[j].x > dMaxX) {
dMaxX = pLinePoints[j].x;
}
if (pLinePoints[j].y > dMaxY) {
dMaxY = pLinePoints[j].y;
}
} //end for
CenterLinePoint.x = (dMinX + dMaxX) / 2;
CenterLinePoint.y = (dMinY + dMaxY) / 2;
} catch (Error exc) {
ErrorLogger.LogException(_className, "CalcCenterPointDouble",
new RendererException("Failed inside CalcCenterPointDouble", exc));
}
return CenterLinePoint;
}
/**
* Called by renderer Modifier2 class after ArrayList.ToArray was called,
* which produces an array of objects.
*
* @param pLinePoints
* @param vblCounter
* @return
*/
public static POINT2 CalcCenterPointDouble2(Object[] pLinePoints,
int vblCounter) {
POINT2 pt0 = (POINT2) pLinePoints[0];
POINT2 CenterLinePoint = new POINT2();
try {
//declarations
int j = 0;
double dMinX = pt0.x,
dMinY = pt0.y,
dMaxX = pt0.x,
dMaxY = pt0.y;
//end declarations
dMinX = pt0.x;
dMinY = pt0.y;
dMaxX = pt0.x;
dMaxY = pt0.y;
POINT2 pt;
for (j = 0; j < vblCounter; j++) {
pt = (POINT2) pLinePoints[j];
if (pt.x < dMinX) {
dMinX = pt.x;
}
if (pt.y < dMinY) {
dMinY = pt.y;
}
if (pt.x > dMaxX) {
dMaxX = pt.x;
}
if (pt.y > dMaxY) {
dMaxY = pt.y;
}
} //end for
CenterLinePoint.x = (dMinX + dMaxX) / 2;
CenterLinePoint.y = (dMinY + dMaxY) / 2;
} catch (Error exc) {
ErrorLogger.LogException(_className, "CalcCenterPointDouble2",
new RendererException("Failed inside CalcCenterPointDouble2", exc));
}
return CenterLinePoint;
}
/**
* Calculates the distance in pixels between two points
*
* @param p1 the first point
* @param p2 the last point
*
* @return the distance between p1 and p2 in pixels
*/
public static double CalcDistanceDouble(POINT2 p1,
POINT2 p2) {
double returnValue = 0;
try {
returnValue = Math.sqrt((p1.x - p2.x)
* (p1.x - p2.x)
+ (p1.y - p2.y)
* (p1.y - p2.y));
//sanity check
//return x or y distance if returnValue is 0 or infinity
double xdist = Math.abs(p1.x - p2.x);
double ydist = Math.abs(p1.y - p2.y);
double max = xdist;
if (ydist > xdist) {
max = ydist;
}
if (returnValue == 0 || Double.isInfinite(returnValue)) {
if (max > 0) {
returnValue = max;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcDistanceDouble",
new RendererException("Failed inside CalcDistanceDouble", exc));
}
return returnValue;
}
/**
* Computes the slope of a line
*
* @param firstLinePoint the first line point
* @param lastLinePoint the last line point
* @param slope OUT - object with member to hold the slope of the line
*
* @return 1 if successful, else return 0
*/
protected static int CalcTrueSlopeDouble(POINT2 firstLinePoint,
POINT2 lastLinePoint,
ref<double[]> slope)//ref is a double
{
int result = 1;
try {
if (slope.value == null) {
slope.value = new double[1];
}
double deltaX = 0, deltaY = 0;
deltaX = firstLinePoint.x - lastLinePoint.x;
//if (deltaX == 0)
if (Math.abs(deltaX) < 1)
{
//deltaX = 1;
if(deltaX>=0)
deltaX=1;
else
deltaX=-1;
result = 1;
}
deltaY = firstLinePoint.y - lastLinePoint.y;
slope.value[0] = deltaY / deltaX; //cannot blow up
} catch (Error exc) {
ErrorLogger.LogException(_className, "CalcTrueSlopeDouble",
new RendererException("Failed inside CalcTrueSlopeDouble", exc));
}
return result;
}
public static void WriteFile(String str) {
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Test.txt"));
bufferedWriter.write(str);
bufferedWriter.close();
bufferedWriter = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "WriteFile",
new RendererException("Failed inside WriteFile", exc));
}
}
/**
* reverses the first vblCounter points
*
* @param pLowerLinePoints OUT - points to reverse
* @param vblCounter
*/
protected static void ReversePointsDouble2(POINT2[] pLowerLinePoints,
int vblCounter) {
try {
POINT2[] pResultPoints = new POINT2[vblCounter];
int k = 0;
for (k = 0; k < vblCounter; k++) {
pResultPoints[k] = new POINT2(pLowerLinePoints[vblCounter - k - 1]);
}
for (k = 0; k < vblCounter; k++) {
pLowerLinePoints[k] = new POINT2(pResultPoints[k]);
}
pResultPoints = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ReversePointsDouble2",
new RendererException("Failed inside ReversePointsDouble2", exc));
}
}
public static boolean CalcTrueSlopeDoubleForRoutes(POINT2 firstLinePoint,
POINT2 lastLinePoint,
ref<double[]> slope) {
try {
double deltaX = 0, deltaY = 0;
deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x);
if (Math.abs(deltaX) < 2) //was 2,infinite slope
{
return (false);
}
deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y);
if (slope.value == null) {
slope.value = new double[1];
}
slope.value[0] = deltaY / deltaX;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcTrueSlopeDoubleForRoutes",
new RendererException("Failed inside CalcTrueSlopeDoubleForRoutes", exc));
}
return true;
}
/**
* Computes the slope of a line
*
* @param firstLinePoint the first line point
* @param lastLinePoint the last line point
* @param slope OUT - object with member to hold the slope of the line
*
* @return true if successful
*/
public static boolean CalcTrueSlopeDouble2(POINT2 firstLinePoint,
POINT2 lastLinePoint,
ref<double[]> slope) {
Boolean result = true;
try {
double deltaX = 0, deltaY = 0;
deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x);
//if (deltaX == 0)
if (Math.abs(deltaX) < 1)
{
//deltaX = 1;
if(deltaX>=0)
deltaX=1;
else
deltaX=-1;
result = false;
}
deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y);
if (slope.value == null) {
slope.value = new double[1];
}
slope.value[0] = deltaY / deltaX;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcTrueSlopeDouble2",
new RendererException("Failed inside CalcTrueSlopeDouble2", exc));
}
return result;
}
/**
* Calculates the slopes and y intercepts in pixels for the line from pt1 to
* pt2 and a parallel line a vertical distance from the line
*
* @param nDistance the distance in pixels
* @param linePoint1 first point on the line
* @param linePoint2 last point on the line
* @param pdResult OUT - array to hold m, b for both lines
*
* @return 1 if the lines are not vertical, else return 0
*/
protected static int CalcTrueLinesDouble(long nDistance,
POINT2 linePoint1,
POINT2 linePoint2,
ref<double[]> pdResult) //for vertical line e.g. if line equation is x=7
{
try {
//declarations
int nTemp = 0;
double b = 0;
double delta = 0;
ref<double[]> m = new ref();
//end declarations
nTemp = CalcTrueSlopeDouble(linePoint1, linePoint2, m);
pdResult.value = new double[6];
//Fill the result array with the line parameters
if (nTemp == 0) //vertical lines
{
pdResult.value[3] = linePoint1.x + (double) nDistance; //the lower line eqn, e.g. x=7
pdResult.value[5] = linePoint1.x - (double) nDistance; //the upper line eqn,
return 0;
} else {
b = linePoint2.y - m.value[0] * linePoint2.x;
delta = Math.sqrt(m.value[0] * m.value[0] * ((double) (nDistance) * (double) (nDistance))
+ ((double) (nDistance) * (double) (nDistance)));
pdResult.value[0] = m.value[0]; //original line eq'n: y = mx + b
pdResult.value[1] = b;
pdResult.value[2] = m.value[0]; //lower line eq'n: y = mx + (b+dDistance)
pdResult.value[3] = b + delta;
pdResult.value[4] = m.value[0]; //upper line eq'n: y = mx + (b-dDistance)
pdResult.value[5] = b - delta;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcTrueLinesDouble",
new RendererException("Failed inside CalcTrueLinesDouble", exc));
}
return 1;
}
/**
* Calculates the intersection of two lines.
*
* @param m1 slope of first line
* @param b1 Y intercept of first line
* @param m2 slope of second line
* @param b2 Y intercept of second line
* @param bolVertical1 0 if first line is vertical, else 1
* @param bolVertical2 0 if second line is vertical, else 1
* @param X1 X intercept if first line is vertical
* @param X2 X intercept if 2nd line is vertical.
*
* @return intersection point
*/
public static POINT2 CalcTrueIntersectDouble2(double m1,
double b1,
double m2,
double b2,
int bolVertical1,
int bolVertical2,
double X1, //x intercept if line1 is vertical
double X2) {
POINT2 ptIntersect = new POINT2();
try {
//declarations
double x = 0, y = 0;
//end declarations
//initialize ptIntersect
ptIntersect.x = X1;
ptIntersect.y = X2;
if (bolVertical1 == 0 && bolVertical2 == 0) //both lines vertical
{
return ptIntersect;
}
//the following 3 if blocks are the only ways to get an intersection
if (bolVertical1 == 0 && bolVertical2 == 1) //line1 vertical, line2 not
{
ptIntersect.x = X1;
ptIntersect.y = m2 * X1 + b2;
return ptIntersect;
}
if (bolVertical1 == 1 && bolVertical2 == 0) //line2 vertical, line1 not
{
ptIntersect.x = X2;
ptIntersect.y = m1 * X2 + b1;
return ptIntersect;
}
//if either of the lines is vertical function has already returned
//so both m1 and m2 should be valid
if (m1 != m2) {
x = (b2 - b1) / (m1 - m2); //cannot blow up
y = (m1 * x + b1);
ptIntersect.x = x;
ptIntersect.y = y;
return ptIntersect;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcTrueIntersectDouble2",
new RendererException("Failed inside CalcTrueIntersectDouble2", exc));
}
return ptIntersect;
}
/**
* Calculates an offset point for channel types which require arrows.
*
* @param startLinePoint the first point
* @param endLinePoint the last point
* @param nOffset the offset in pixels
*
* @return the offset point
*/
protected static POINT2 GetOffsetPointDouble(POINT2 startLinePoint,
POINT2 endLinePoint,
long nOffset) {
POINT2 tempLinePoint = new POINT2(startLinePoint);
try {
//declarations
double dx = endLinePoint.x - startLinePoint.x,
dy = endLinePoint.y - startLinePoint.y,
dOffset = (double) nOffset,
dHypotenuse = 0,
dAngle = 0;
//end declarations
if (dx == 0) {
if (dy > 0) {
tempLinePoint.x = endLinePoint.x;
tempLinePoint.y = endLinePoint.y + dOffset;
} else {
tempLinePoint.x = endLinePoint.x;
tempLinePoint.y = endLinePoint.y - dOffset;
}
return tempLinePoint;
}
if (dy == 0) {
if (dx > 0) {
tempLinePoint.x = endLinePoint.x + dOffset;
tempLinePoint.y = endLinePoint.y;
} else {
tempLinePoint.x = endLinePoint.x - dOffset;
tempLinePoint.y = endLinePoint.y;
}
return tempLinePoint;
}
if (dy == 0) {
dAngle = 0;
} else {
dAngle = Math.atan(dx / dy) + Math.PI / 2;//1.570795;
}
dHypotenuse = (double) nOffset;
if (endLinePoint.x > startLinePoint.x) {
tempLinePoint.x = endLinePoint.x + dHypotenuse * Math.abs(Math.cos(dAngle));
} else {
tempLinePoint.x = endLinePoint.x - dHypotenuse * Math.abs(Math.cos(dAngle));
}
if (endLinePoint.y > startLinePoint.y) {
tempLinePoint.y = endLinePoint.y + dHypotenuse * Math.abs(Math.sin(dAngle));
} else {
tempLinePoint.y = endLinePoint.y - dHypotenuse * Math.abs(Math.sin(dAngle));
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetOffsetPointDouble",
new RendererException("Failed inside GetOffsetPointDouble", exc));
}
return (tempLinePoint);
}
/**
* Computes the arc points for FEBA Assumes pResultLinePoints has been
* allocated.
*
* @param dRadius the arc radius in pixels
* @param pLinePoints the client points, each one is a center for a computed
* arc (cricle)
* @param vblCounter number of client points to use
* @param pResultLinePoints OUT - the arc points to return
*/
protected static POINT2[] GetArcFEBADouble(double dRadius,
POINT2[] pLinePoints,
int vblCounter,
POINT2[] pResultLinePoints) {
try {
//declarations
double dStartAngle = 0,
dEndAngle = 2 * Math.PI,
dIncrement = (dEndAngle - dStartAngle) / 25.0;
int i = 0, j = 0, nArcCounter = 0;
double x = 0, y = 0;
POINT2 CenterLinePoint = new POINT2(pLinePoints[0]);
POINT2[] pArcLinePoints = new POINT2[26];
//end declarations
InitializePOINT2Array(pArcLinePoints);
for (i = 0; i < vblCounter; i++) //stuff the pArcLinePoints collector
{
CenterLinePoint = new POINT2(pLinePoints[i]);
CalcCircleDouble(CenterLinePoint, dRadius, 26, pArcLinePoints, 0);
for (j = 0; j < 26; j++) {
pResultLinePoints[nArcCounter] = new POINT2(pArcLinePoints[j]);
nArcCounter++;
}
pResultLinePoints[nArcCounter - 1].style = 5;
} //end for
pResultLinePoints[26 * vblCounter - 1].style = 5;
pArcLinePoints = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetArcFEBADouble",
new RendererException("Failed inside GetArcFEBADouble", exc));
}
return pResultLinePoints;
}
/**
* Used for DMAF
*
* @param pLinePoints the client points
* @return ArrayList of X points
*/
protected static ArrayList LineOfXPoints(POINT2[] pLinePoints) {
ArrayList xPoints = new ArrayList();
try {
int j = 0, k = 0;
double dist = 0;
int iterations = 0;
POINT2 frontPt = null, backPt = null;
POINT2 extendFrontAbove = null, extendFrontBelow = null;
POINT2 extendBackAbove = null, extendBackBelow = null;
POINT2 xPoint1 = null, xPoint2 = null;
int n=pLinePoints.length;
//for (j = 0; j < pLinePoints.length - 1; j++)
for (j = 0; j < n - 1; j++)
{
dist = CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
iterations = (int) ((dist - 5.0) / 20.0);
if (dist - iterations * 20 > 10) {
iterations += 1;
}
for (k = 0; k < iterations; k++) {
frontPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * 20 - 5);
backPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * 20 + 5);
extendFrontAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 2, 5);
extendFrontBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 3, 5);
extendBackAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 2, 5);
extendBackBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 3, 5);
xPoints.add(extendFrontAbove);
extendBackBelow.style = 5;
xPoints.add(extendBackBelow);
xPoints.add(extendBackAbove);
extendFrontBelow.style = 5;
xPoints.add(extendFrontBelow);
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "LineOfXPoints",
new RendererException("Failed inside LineOfXPoints", exc));
}
return xPoints;
}
/**
* Computes the "X" points for FEBA Assumes pResultLinePoints has been
* allocated.
*
* @param pLinePoints the client points
* @param dSize size in pixels to use for X
* @param vblCounter number of client points to use
* @param pResultLinePoints OUT - the points to return
*/
protected static void GetXFEBADouble(POINT2[] pLinePoints,
double dSize,
long vblCounter,
POINT2[] pResultLinePoints
) {
try {
//declarations
int j = 0, nXcounter = 0;
POINT2 upperLeftLinePoint = new POINT2(pLinePoints[0]),
lowerLeftLinePoint = new POINT2(pLinePoints[0]),
upperRightLinePoint = new POINT2(pLinePoints[0]),
lowerRightLinePoint = new POINT2(pLinePoints[0]);
//end declarations
for (j = 0; j < vblCounter; j++) {
upperRightLinePoint.x = pLinePoints[j].x + dSize;
upperRightLinePoint.y = pLinePoints[j].y + dSize;
lowerRightLinePoint.x = pLinePoints[j].x + dSize;
lowerRightLinePoint.y = pLinePoints[j].y - dSize;
upperLeftLinePoint.x = pLinePoints[j].x - dSize;
upperLeftLinePoint.y = pLinePoints[j].y + dSize;
lowerLeftLinePoint.x = pLinePoints[j].x - dSize;
lowerLeftLinePoint.y = pLinePoints[j].y - dSize;
pResultLinePoints[nXcounter] = new POINT2(lowerLeftLinePoint);
nXcounter++;
pResultLinePoints[nXcounter] = new POINT2(upperRightLinePoint);
pResultLinePoints[nXcounter].style = 5;
nXcounter++;
pResultLinePoints[nXcounter] = new POINT2(upperLeftLinePoint);
nXcounter++;
pResultLinePoints[nXcounter] = new POINT2(lowerRightLinePoint);
pResultLinePoints[nXcounter].style = 5;
nXcounter++;
} //end for
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetXFEBADouble",
new RendererException("Failed inside GetXFEBADouble", exc));
}
}
/**
* Reorders points for HOLD, BRDGHD
*
* @param pLinePoints OUT - client points also reordered points
*/
protected static void ReorderPoints(POINT2[] pLinePoints) {
try {
//int n = 3;//pLinePoints.length;
int n = pLinePoints.length;
POINT2 pt = new POINT2();
POINT2 pt1 = new POINT2(pLinePoints[1]);
//reorder the points
for (int j = 1; j < n - 1; j++) {
pt = new POINT2(pLinePoints[j + 1]);
pLinePoints[j] = new POINT2(pt);
}
pLinePoints[n - 1] = new POINT2(pt1);
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ReorderPoints",
new RendererException("Failed inside ReorderPoints", exc));
}
}
/**
* Computes the distance in pixels of pt3 to the line from pt1 to pt2.
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt3 point distance to compute
* @return distance to pt3
*/
public static double CalcDistanceToLineDouble(POINT2 pt1,
POINT2 pt2,
POINT2 pt3) {
double dResult = 0;
try {
//declarations
double m1 = 1, b = 0, b1 = 0;
POINT2 ptIntersect = new POINT2(pt1);
int bolVertical = 0;
ref<double[]> m = new ref();
//end declarations
bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
//get line y intercepts
if (bolVertical != 0 && m.value[0] != 0) {
m1 = -1 / m.value[0];
b = pt1.y - m.value[0] * pt1.x;
b1 = pt3.y - m1 * pt3.x;
ptIntersect = CalcTrueIntersectDouble2(m.value[0], b, m1, b1, 1, 1, ptIntersect.x, ptIntersect.y);
}
if (bolVertical != 0 && m.value[0] == 0) //horizontal line
{
ptIntersect.y = pt1.y;
ptIntersect.x = pt3.x;
}
if (bolVertical == 0) //vertical line
{
ptIntersect.y = pt3.y;
ptIntersect.x = pt1.x;
}
dResult = CalcDistanceDouble(pt3, ptIntersect);
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "CaclDistanceToLineDouble",
new RendererException("Failed inside CalcDistanceToLineDouble", exc));
}
return dResult;
}
/**
* Calculates a point along a line. Returns the past point if the distance
* is 0.
*
* @param pt1 first line point
* @param pt2 last line point
* @param dist extension distance in pixels from the beginning of the line
*
* @return the extension point
*/
public static POINT2 ExtendLineDouble(POINT2 pt1,
POINT2 pt2,
double dist) {
POINT2 pt3 = new POINT2();
try {
double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
if (dOriginalDistance == 0 || dist == 0) {
return pt2;
}
pt3.x = (dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x;
pt3.y = (dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y;
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendLineDouble",
new RendererException("Failed inside ExtendLineDouble", exc));
}
return pt3;
}
/**
* Extends a point along a line. If dist is 0 returns last point.
*
* @param pt1 first point on the line
* @param pt2 last point on the line
* @param dist the distance in pixels from pt1
*
* @return the extended point
*/
public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist) {
POINT2 pt3 = new POINT2();
try {
double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
if (dOriginalDistance == 0 || dist == 0) {
return pt2;
}
pt3.x = ((dist / dOriginalDistance) * (pt2.x - pt1.x) + pt1.x);
pt3.y = ((dist / dOriginalDistance) * (pt2.y - pt1.y) + pt1.y);
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendAlongLineDouble",
new RendererException("Failed inside ExtendAlongLineDouble", exc));
}
return pt3;
}
public static POINT2 ExtendAlongLineDouble2(POINT2 pt1, POINT2 pt2, double dist) {
POINT2 pt3 = new POINT2();
try {
double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
if (dOriginalDistance == 0 || dist == 0) {
return pt1;
}
pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendAlongLineDouble2",
new RendererException("Failed inside ExtendAlongLineDouble2", exc));
}
return pt3;
}
public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist, int styl) {
POINT2 pt3 = new POINT2();
try {
double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
if (dOriginalDistance == 0 || dist == 0) {
return pt2;
}
pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
pt3.style = styl;
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendAlongLineDouble",
new RendererException("Failed inside ExtendAlongLineDouble", exc));
}
return pt3;
}
/**
* Extends a point above a line
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt3 point at which to extend
* @param d distance in pixels to extend above the line
* @param X OUT - extended point x value
* @param Y OUT - extended point y value
* @param direction direction to extend the line
*
* @return 1 if successful, else return 0
*/
protected static int ExtendLineAbove(POINT2 pt1,
POINT2 pt2,
POINT2 pt3,
double d,
ref<double[]> X,
ref<double[]> Y,
int direction) {
try {
ref<double[]> m = new ref();
double dx = 0, dy = 0;
int bolVertical = 0;
X.value = new double[1];
Y.value = new double[1];
bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
if (bolVertical == 0) {
return 0; //cannot extend above a vertical line
}
if (m.value[0] == 0) {
X.value[0] = pt3.x;
if (direction == 0) //extend above the line
{
Y.value[0] = pt3.y - Math.abs(d);
} else //extend below the line
{
Y.value[0] = pt3.y + Math.abs(d);
}
return 1;
}
//the line is neither vertical nor horizontal
//else function would already have returned
if (direction == 0) //extend above the line
{
dy = -Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))));
} else //extend below the line
{
dy = Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))));
}
dx = -m.value[0] * dy;
X.value[0] = pt3.x + dx;
Y.value[0] = pt3.y + dy;
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendLineAbove",
new RendererException("Failed inside ExtendLineAbove", exc));
}
return 1;
}
/**
* Extends a point to the left of a line
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt3 point at which to extend
* @param d distance in pixels to extend above the line
* @param X OUT - extended point x value
* @param Y OUT - extended point y value
* @param direction direction to extend the line
*
* @return 1 if successful, else return 0
*/
protected static int ExtendLineLeft(POINT2 pt1,
POINT2 pt2,
POINT2 pt3,
double d,
ref<double[]> X,
ref<double[]> Y,
int direction) {
try {
ref<double[]> m = new ref();
double dx = 0, dy = 0;
int bolVertical = 0;
X.value = new double[1];
Y.value = new double[1];
bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
if (bolVertical != 0 && m.value[0] == 0) {
return 0; //cannot left of horiz line
}
if (bolVertical == 0) //vertical line
{
Y.value[0] = pt3.y;
if (direction == 0) //extend left of the line
{
X.value[0] = pt3.x - Math.abs(d);
} else //extend right of the line
{
X.value[0] = pt3.x + Math.abs(d);
}
return 1;
}
//the line is neither vertical nor horizontal
//else function would already have returned
if (direction == 0) //extend left of the line
{
dx = -Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0])));
} else //extend right of the line
{
dx = Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0])));
}
dy = -(1 / m.value[0]) * dx;
X.value[0] = pt3.x + dx;
Y.value[0] = pt3.y + dy;
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendLineLeft",
new RendererException("Failed inside ExtendLineLeft", exc));
}
return 1;
}
/**
* Calculates the direction of a point relative to a line
*
* @param pt0 first point fo the line
* @param pt1 last point of the line
* @param pt2 relative point
* @deprecated
* @return 0 if left, 1 if right, 2 if above, 3 if below
*/
protected static int CalcDirectionFromLine(POINT2 pt0,
POINT2 pt1,
POINT2 pt2) {
int result = -1;
try {
double m2 = 0, b1 = 0, b2 = 0;
ref<double[]> m1 = new ref();
POINT2 ptIntersect = new POINT2();
//int direction=-1;
//handle vertical line
if (pt0.x == pt1.x) {
if (pt2.x < pt0.x) {
return 0;
} else {
return 1;
}
}
//handle horizontal line so that we do not have slope = 0.
if (pt0.y == pt1.y) {
if (pt2.y < pt0.y) {
return 2;
} else {
return 3;
}
}
CalcTrueSlopeDouble(pt0, pt1, m1);
m2 = -1 / m1.value[0]; //slope for the perpendicular line from the line to pt2
//b=mx-y line equation for line
b1 = pt0.y - m1.value[0] * pt0.x;
//b=mx-y line equation for perpendicular line which contains pt2
b2 = pt2.y - m2 * pt2.x;
ptIntersect = CalcTrueIntersectDouble2(m1.value[0], b1, m2, b2, 1, 1, 0, 0);
//compare the intersection point with pt2 to get the direction,
//i.e. the direction from the line is the same as the direction
//from the interseciton point.
if (m1.value[0] > 1) //line is steep, use left/right
{
if (pt2.x < ptIntersect.x) {
return 0;
} else {
return 1;
}
} else //line is not steep, use above/below
{
if (pt2.y < ptIntersect.y) {
return 2;
} else {
return 3;
}
}
//should not reach this point
//return direction;
} catch (Exception e) {
System.out.println(e.getMessage());
}
return result;
}
/**
* Returns a point extended perpendicularly from a line at a given direction
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt0 on line from which to extend
* @param direction the direction to extend: above, below, left, right
* @param d the length to extend in pixels
*
*/
public static POINT2 ExtendDirectedLine(POINT2 pt1,
POINT2 pt2,
POINT2 pt0,
int direction,
double d) {
POINT2 ptResult = new POINT2();
try {
ref<double[]> X = new ref(), Y = new ref();
ptResult = new POINT2(pt0);
switch (direction) {
case 0: //extend left
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
break;
case 1: //extend right
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
break;
case 2: //extend above
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
break;
case 3: //extend below
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
break;
default:
break;
}
ptResult.x = X.value[0];
ptResult.y = Y.value[0];
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendDirectedLine",
new RendererException("Failed inside ExtendDirectedLine", exc));
}
return ptResult;
}
/**
* @deprecated Returns a point extended perpendicularly from a line at a
* given direction same as original function except it accounts for vertical
* lines and negative d values
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt0 on line from which to extend
* @param direction the direction to extend: above, below, left, right
* @param d the length to extend in pixels
*
*/
public static POINT2 ExtendDirectedLineText(POINT2 pt1,
POINT2 pt2,
POINT2 pt0,
int direction,
double d) {
POINT2 ptResult = new POINT2();
try {
ref<double[]> X = new ref(), Y = new ref();
ptResult = new POINT2(pt0);
if (d < 0) {
switch (direction) {
case 0:
direction = extend_right;
break;
case 1:
direction = extend_left;
break;
case 2:
direction = extend_below;
break;
case 3:
direction = extend_above;
break;
default:
break;
}
d = Math.abs(d);
}
if (pt1.y == pt2.y)//horizontal segment
{
switch (direction) {
case 0://left means above
direction = extend_above;
case 1://right means below
direction = extend_below;
default:
break;
}
}
if (pt1.x == pt2.x)//vertical segment
{
switch (direction) {
case 2://above means left
direction = extend_left;
case 3://below means right
direction = extend_right;
default:
break;
}
}
switch (direction) {
case 0: //extend left
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
break;
case 1: //extend right
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
break;
case 2: //extend above
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
break;
case 3: //extend below
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
break;
default:
break;
}
ptResult.x = X.value[0];
ptResult.y = Y.value[0];
} catch (Exception exc) {
//System.out.println(e.getMessage());
ErrorLogger.LogException(_className, "ExtendDirectedLine",
new RendererException("Failed inside ExtendDirectedLine", exc));
}
return ptResult;
}
/**
* Returns a point extended perpendicularly from a line at a given direction
*
* @param pt1 first line point
* @param pt2 last line point
* @param pt0 on line from which to extend
* @param direction the direction to extend: above, below, left, right
* @param d the length to extend in pixels
* @param style the style to assign the return point
*
*/
public static POINT2 ExtendDirectedLine(POINT2 pt1,
POINT2 pt2,
POINT2 pt0,
int direction,
double d,
int style) {
POINT2 ptResult = new POINT2(pt0);
try {
ref<double[]> X = new ref(), Y = new ref();
//int bolResult=0;
//handle parallel, perpendicular cases
if (pt1.x == pt2.x) {
if (direction == 2) {
direction = 0;
}
if (direction == 3) {
direction = 1;
}
}
if (pt1.y == pt2.y) {
if (direction == 0) {
direction = 2;
}
if (direction == 1) {
direction = 3;
}
}
switch (direction) {
case 0: //extend left
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
break;
case 1: //extend right
ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
break;
case 2: //extend above
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
break;
case 3: //extend below
ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
break;
}
ptResult.x = X.value[0];
ptResult.y = Y.value[0];
ptResult.style = style;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ExtendDirectedLine",
new RendererException("Failed inside ExtendDirectedLine", exc));
}
return ptResult;
}
/**
* Calculates a point along a line
*
* @param pt1 first line point
* @param pt2 last line point
* @param dist extension distance in pixels from the beginning of the line
* @param styl the line style to assign the point
*
* @return the extension point
*/
protected static POINT2 ExtendLine2Double(POINT2 pt1,
POINT2 pt2,
double dist,
int styl) {
POINT2 pt3 = new POINT2();
try {
double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
pt3.x = pt2.x;
pt3.y = pt2.y;
if (dOriginalDistance > 0) {
pt3.x = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
pt3.y = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
pt3.style = styl;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ExtendLine2Double",
new RendererException("Failed inside ExtendLine2Double", exc));
}
return pt3;
}
/**
* Extends a point at an angle from a line.
*
* @param pt0 the first line point
* @param pt1 the second line point
* @param pt2 point on line from which to extend
* @param alpha angle of extension in degrees
* @param d the distance in pixels to extend
*
* @return the extension point
*/
public static POINT2 ExtendAngledLine(POINT2 pt0,
POINT2 pt1,
POINT2 pt2,
double alpha,
double d) {
POINT2 pt = new POINT2();
try {
//first get the angle psi between pt0 and pt1
double psi = Math.atan((pt1.y - pt0.y) / (pt1.x - pt0.x));
//convert alpha to radians
double alpha1 = Math.PI * alpha / 180;
//theta is the angle of extension from the x axis
double theta = psi + alpha1;
//dx is the x extension from pt2
double dx = d * Math.cos(theta);
//dy is the y extension form pt2
double dy = d * Math.sin(theta);
pt.x = pt2.x + dx;
pt.y = pt2.y + dy;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ExtendAngledLine",
new RendererException("Failed inside ExtendAngledLine", exc));
}
return pt;
}
/**
* Returns an integer indicating the quadrant for the direction of the line
* from pt1 to pt2
*
* @param pt1 first line point
* @param pt2 second line point
*
* @return the quadrant
*/
public static int GetQuadrantDouble(POINT2 pt1,
POINT2 pt2) {
int nQuadrant = 1;
try {
if (pt2.x >= pt1.x && pt2.y <= pt1.y) {
nQuadrant = 1;
}
if (pt2.x >= pt1.x && pt2.y >= pt1.y) {
nQuadrant = 2;
}
if (pt2.x <= pt1.x && pt2.y >= pt1.y) {
nQuadrant = 3;
}
if (pt2.x <= pt1.x && pt2.y <= pt1.y) {
nQuadrant = 4;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetQuadrantDouble",
new RendererException("Failed inside GetQuadrantDouble", exc));
}
return nQuadrant;
}
public static int GetQuadrantDouble(double x1, double y1,
double x2, double y2) {
int nQuadrant = 1;
try {
// if(pt2.x>=pt1.x && pt2.y<=pt1.y)
// nQuadrant=1;
// if(pt2.x>=pt1.x && pt2.y>=pt1.y)
// nQuadrant=2;
// if(pt2.x<=pt1.x && pt2.y>=pt1.y)
// nQuadrant=3;
// if(pt2.x<=pt1.x && pt2.y<=pt1.y)
// nQuadrant=4;
if (x2 >= x1 && y2 <= y1) {
nQuadrant = 1;
}
if (x2 >= x1 && y2 >= y1) {
nQuadrant = 2;
}
if (x2 <= x1 && y2 >= y1) {
nQuadrant = 3;
}
if (x2 <= x1 && y2 <= y1) {
nQuadrant = 4;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetQuadrantDouble",
new RendererException("Failed inside GetQuadrantDouble", exc));
}
return nQuadrant;
}
/**
* Returns the smallest x and y pixel values from an array of points
*
* @param ptsSeize array of points from which to find minimum vaules
* @param vblCounter the number of points to test in the array
* @param x OUT - an object with a member to hold the xminimum
* @param y OUT - an object with a member to hold the y minimum value
*
*/
protected static void GetPixelsMin(POINT2[] ptsSeize,
int vblCounter,
ref<double[]> x,
ref<double[]> y) {
try {
double xmin = Double.POSITIVE_INFINITY;
double ymin = Double.POSITIVE_INFINITY;
int j = 0;
for (j = 0; j < vblCounter; j++) {
if (ptsSeize[j].x < xmin) {
xmin = ptsSeize[j].x;
}
if (ptsSeize[j].y < ymin) {
ymin = ptsSeize[j].y;
}
}
x.value = new double[1];
y.value = new double[1];
x.value[0] = xmin;
y.value[0] = ymin;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetPixelsMin",
new RendererException("Failed inside GetPixelsMin", exc));
}
}
/**
* Returns center point for a clockwise arc to connect pts 1 and 2. Also
* returns an extended point on the line between pt1 and the new center
* Caller passes a POINT1 array of size 2 for ptsSeize, passes pt1 and pt2
* in ptsSeize Returns the radius of the 90 degree arc between C (arc
* center) and pt1
*
* @param ptsSeize OUT - two point array also used for the returned two
* points
*
* @return the radius
*/
protected static double CalcClockwiseCenterDouble(POINT2[] ptsSeize) {
double dRadius = 0;
try {
//declarations
POINT2 pt1 = new POINT2(ptsSeize[0]);
POINT2 pt2 = new POINT2(ptsSeize[1]);
POINT2 C = new POINT2(pt1), midPt = new POINT2(pt1); //the center to calculate
POINT2 E = new POINT2(pt1); //the extended point to calculate
POINT2 ptYIntercept = new POINT2(pt1);
int nQuadrant = 1;
double b = 0, b1 = 0, b2 = 0, dLength = 0;
ref<double[]> m = new ref();
int bolVertical = 0;
ref<double[]> offsetX = new ref(), offsetY = new ref();
POINT2[] ptsTemp = new POINT2[2];
//end declarations
//must offset the points if necessary because there will be calculations
//extending from the Y Intercept
ptsTemp[0] = new POINT2(pt1);
ptsTemp[1] = new POINT2(pt2);
GetPixelsMin(ptsTemp, 2, offsetX, offsetY);
if (offsetX.value[0] < 0) {
offsetX.value[0] = offsetX.value[0] - 100;
} else {
offsetX.value[0] = 0;
}
//end section
midPt.x = (pt1.x + pt2.x) / 2;
midPt.y = (pt1.y + pt2.y) / 2;
dLength = CalcDistanceDouble(pt1, pt2);
dRadius = dLength / Math.sqrt(2);
nQuadrant = GetQuadrantDouble(pt1, pt2);
bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
if (bolVertical != 0 && m.value[0] != 0) //line not vertical or horizontal
{
b = pt1.y - m.value[0] * pt1.x;
//y intercept of line perpendicular to midPt of pt,p2
b1 = midPt.y + (1 / m.value[0]) * midPt.x;
//we want to shift the Y axis to the left by offsetX
//so we get the new Y intercept at x=offsetX
b2 = (-1 / m.value[0]) * offsetX.value[0] + b1;
ptYIntercept.x = offsetX.value[0];
ptYIntercept.y = b2;
switch (nQuadrant) {
case 1:
case 4:
C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2);
break;
case 2:
case 3:
C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2);
break;
default:
break;
}
}
if (bolVertical != 0 && m.value[0] == 0) //horizontal line
{
C.x = midPt.x;
if (pt1.x < pt2.x) {
C.y = midPt.y + dLength / 2;
} else {
C.y = midPt.y - dLength / 2;
}
}
if (bolVertical == 0) //vertical line
{
ptYIntercept.x = offsetX.value[0];
ptYIntercept.y = midPt.y;
switch (nQuadrant) {
case 1:
case 4:
C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2);
break;
case 2:
case 3:
C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2);
break;
default:
break;
}
}
E = ExtendLineDouble(C, pt1, 50);
ptsSeize[0] = new POINT2(C);
ptsSeize[1] = new POINT2(E);
ptsTemp = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcClockwiseCenterDouble",
new RendererException("Failed inside CalcClockwiseCenterDouble", exc));
}
return dRadius;
}
/**
* Computes the points for an arrowhead based on a line segment
*
* @param startLinePoint segment start point
* @param endLinePoint segment end point
* @param nBiSector bisecotr in pixels
* @param nBase base size in pixels
* @param pResultLinePoints OUT - the arrowhead points
* @param styl the line style to assign the last aroowhead point
*/
protected static void GetArrowHead4Double(POINT2 startLinePoint,
POINT2 endLinePoint,
int nBiSector,
int nBase,
POINT2[] pResultLinePoints,
int styl) {
try {
//declarations
int j = 0;
double dy = (double) (endLinePoint.y - startLinePoint.y),
dx = (double) (endLinePoint.x - startLinePoint.x),
dSign = 1.0,
AHBY = 0,
AHBX = 0,
AHBLY = 0,
AHBLX = 0,
AHBRY = 0,
AHBRX = 0,
dAngle = 0,
dHypotenuse = 0;
POINT2 tempLinePoint = new POINT2(startLinePoint);
//end declarations
if (dy == 0) {
if (dx > 0) {
dAngle = Math.PI;
} else {
dAngle = 0;
}
} else {
dAngle = Math.atan(dx / dy) + Math.PI / 2;
}
tempLinePoint.style = 0;//PS_SOLID;
if (dx <= 0.0 && dy <= 0.0) {
dSign = -1.0;
}
if (dx >= 0.0 && dy <= 0.0) {
dSign = -1.0;
}
if (dx <= 0.0 && dy >= 0.0) {
dSign = 1.0;
}
if (dx >= 0.0 && dy >= 0.0) {
dSign = 1.0;
}
dHypotenuse = dSign * (double) nBiSector;
//Find x, y for Arrow Head nBase startLinePoint POINT1
AHBX = (double) endLinePoint.x + dHypotenuse * Math.cos(dAngle);
AHBY = (double) endLinePoint.y - dHypotenuse * Math.sin(dAngle);
//Half of the arrow head's length will be 10 units
dHypotenuse = dSign * (double) (nBase / 2.0);
//Find x, y of Arrow Head nBase Left side end POINT1
AHBLX = AHBX - dHypotenuse * Math.sin(dAngle);
AHBLY = AHBY - dHypotenuse * Math.cos(dAngle);
//Find x, y of Arrow Head nBase Right side end POINT1
AHBRX = AHBX + dHypotenuse * Math.sin(dAngle);
AHBRY = AHBY + dHypotenuse * Math.cos(dAngle);
//replacement, just trying to return the POINT1s
tempLinePoint.x = (int) AHBLX;
tempLinePoint.y = (int) AHBLY;
pResultLinePoints[0] = new POINT2(tempLinePoint);
pResultLinePoints[1] = new POINT2(endLinePoint);
tempLinePoint.x = (int) AHBRX;
tempLinePoint.y = (int) AHBRY;
pResultLinePoints[2] = new POINT2(tempLinePoint);
switch (styl) {
case 0:
for (j = 0; j < 2; j++) {
pResultLinePoints[j].style = 0;
}
pResultLinePoints[2].style = 5;
break;
case 9:
for (j = 0; j < 2; j++) {
pResultLinePoints[j].style = 9;
}
pResultLinePoints[2].style = 10;
break;
case 18:
for (j = 0; j < 2; j++) {
pResultLinePoints[j].style = 18;
}
pResultLinePoints[2].style = 5;
break;
default:
for (j = 0; j < 2; j++) {
pResultLinePoints[j].style = styl;
}
pResultLinePoints[2].style = 5;
break;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetArrowhead4Double",
new RendererException("Failed inside GetArrowhead4Double", exc));
}
}
/**
* Returns the midpoint between two points.
*
* @param pt0 the first point
* @param pt1 the second point
* @param styl the style to assign the mid point
*
* @return the mid point
*/
public static POINT2 MidPointDouble(POINT2 pt0,
POINT2 pt1,
int styl) {
POINT2 ptResult = new POINT2(pt0);
try {
ptResult.x = (pt0.x + pt1.x) / 2;
ptResult.y = (pt0.y + pt1.y) / 2;
ptResult.style = styl;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "MidPointDouble",
new RendererException("Failed inside MidPointDouble", exc));
}
return ptResult;
}
/**
* Rotates an the first vblCounter points in the array about its first point
*
* @param pLinePoints OUT - the points to rotate
* @param vblCounter the number of points to rotate
* @param lAngle the angle in degrees to rotate
*
* @return pLinePoints
*/
protected static POINT2[] RotateGeometryDoubleOrigin(POINT2[] pLinePoints,
int vblCounter,
int lAngle) {
try {
//declarations
int j = 0;
double dRotate = 0,
dTheta = 0,
dGamma = 0,
x = 0,
y = 0;
//end declarations
if (lAngle != 0) {
POINT2 pdCenter = new POINT2();
dRotate = (double) lAngle * Math.PI / 180d;
//pdCenter = CalcCenterPointDouble(pLinePoints,vblCounter);
pdCenter = new POINT2(pLinePoints[0]);
for (j = 0; j < vblCounter; j++) {
dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y)
/ (pLinePoints[j].x - pdCenter.x));
if (pLinePoints[j].x >= pdCenter.x) {
dGamma = dGamma + Math.PI;
}
dTheta = dRotate + dGamma;
y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta);
x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta);
pLinePoints[j].y = pdCenter.y + y;
pLinePoints[j].x = pdCenter.x + x;
} //end for
return pLinePoints;
} //end if
} catch (Exception exc) {
ErrorLogger.LogException(_className, "RotateGeometryDoubleOrigin",
new RendererException("Failed inside RotateGeometryDoubleOrigin", exc));
}
return pLinePoints;
} // end function
/**
* Returns a point a distance d pixels perpendicular to the pt0-pt1 line and
* going toward pt2
*
* @param pt0 the first line point
* @param pt1 the second line point
* @param pt2 the relative line point
* @param d the distance in pixels
* @param styl the linestyle to assign the computed point
*
* @return the extended point
*/
public static POINT2 ExtendTrueLinePerpDouble(POINT2 pt0,
POINT2 pt1,
POINT2 pt2,
double d,
int styl) {
POINT2 ptResult = new POINT2(pt0);
try {
POINT2 ptYIntercept = new POINT2(pt0);
ref<double[]> m = new ref();
double b = 0, b1 = 0; //b is the normal Y intercept (at 0)
int nTemp = 0; //b1 is the y intercept at offsetX
//must obtain x minimum to get the y-intercept to the left of
//the left-most point
ref<double[]> offsetX = new ref(), offsetY = new ref();
POINT2[] pts = new POINT2[3];
pts[0] = new POINT2(pt0);
pts[1] = new POINT2(pt1);
pts[2] = new POINT2(pt2);
GetPixelsMin(pts, 3, offsetX, offsetY);
if (offsetX.value[0] <= 0) //was < 0
{
offsetX.value[0] = offsetX.value[0] - 100;
} else {
offsetX.value[0] = 0;
}
//end section
nTemp = CalcTrueSlopeDouble(pt0, pt1, m);
switch (nTemp) {
case 0: //vertical line
if (pt0.y < pt1.y) {
ptResult.x = pt2.x - d;
ptResult.y = pt2.y;
} else {
ptResult.x = pt2.x + d;
ptResult.y = pt2.y;
}
break;
default: //non-vertical line
if (m.value[0] == 0) {
ptResult.x = pt2.x;
ptResult.y = pt2.y + d;
} else {
b = (double) pt2.y + (1 / m.value[0]) * (double) pt2.x;
//we need the y-intercept at the -offset
b1 = (-1 / m.value[0]) * offsetX.value[0] + b;
ptYIntercept.x = offsetX.value[0];
ptYIntercept.y = b1;
ptResult = ExtendLineDouble(ptYIntercept, pt2, d);
}
break;
}
ptResult.style = styl;
pts = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ExtendTrueLinePerpDouble",
new RendererException("Failed inside ExtendTrueLinePerpDouble", exc));
}
return ptResult;
}
/**
* Calculates the intersection of 2 lines pelative to a point. if one of the
* lines is vertical use a distance dWidth above or below the line. pass
* bolVertical1 = 1, or bolVertical2 = 1 if either line segment is vertical,
* else pass 0. return the unique intersection in X,Y pointers. p2 is the
* point that connects the 2 line segments to which the intersecting lines
* are related, i.e. the intersecting lines are a distance dWidth pixels
* above or below p2. uses dWidth and lOrient for cases in which at least
* one of the lines is vertical. for normal lines this function assumes the
* caller has passed the m, b for the appropriate upper or lower lines to
* get the desired intgercept. this function is used for calculating the
* upper and lower channel lines for channel types. For lOrient: see
* comments in Channels.ConnectTrueDouble2
*
* @param m1 slope of the first line
* @param b1 intercept of the first line
* @param m2 slope of the second line
* @param b2 y intercept of the second line
* @param p2 point that connects the 2 line segments to which the
* intersecting lines are related
* @param bolVerticalSlope1 1 if first segment is vertical, else 0
* @param bolVerticalSlope2 1 if second line segment is vertical, else 0
* @param dWidth the distance of the intersecting lines from p2 in pixels
* @param lOrient the orientation of the intersecting lines relative to the
* segments connecting p2
* @param X OUT - object holds the x value of the intersection point
* @param Y OUT - object holds the y value of the intersection point
*/
protected static int CalcTrueIntersectDouble(double m1,
double b1,
double m2,
double b2,
POINT2 p2, //can use for vertical lines
int bolVerticalSlope1,
int bolVerticalSlope2,
double dWidth, //use for vertical lines, use + for upper line, - for lower line
int lOrient,
ref<double[]> X, //intersection x value
ref<double[]> Y) //intersection y value
{
try {
//case both lines are vertical
double dWidth2 = Math.abs(dWidth);
double b = 0;
double dx = 0, dy = 0, m = 0;
X.value = new double[1];
Y.value = new double[1];
//cannot get out of having to do this
//the problem is caused by inexact slopes which are created by
//clsLineUtility.DisplayIntersectPixels. This occurs when setting
//pt2 or pt3 with X or Y on the boundary +/-maxPixels
//if you try to walk out until you get exactly the same slope
//it can be thousands of pixels, so you have to accept an arbitrary
//and, unfortuantely, inexact slope
if (m1 != m2 && Math.abs(m1 - m2) <= Double.MIN_VALUE) {
m1 = m2;
}
if (b1 != b2 && Math.abs(b1 - b2) <= Double.MIN_VALUE) {
b1 = b2;
}
//M. Deutch 10-24-11
if (b1 == b2 && m1 + b1 == m2 + b2) {
m1 = m2;
}
if (bolVerticalSlope1 == 0 && bolVerticalSlope2 == 0) //both lines vertical
{
switch (lOrient) {
case 0:
X.value[0] = p2.x - dWidth2;
Y.value[0] = p2.y;
break;
case 3:
X.value[0] = p2.x + dWidth2;
Y.value[0] = p2.y;
break;
default: //can never occur
X.value[0] = p2.x;
Y.value[0] = p2.y;
break;
}
return 1;
}
if (bolVerticalSlope1 == 0 && bolVerticalSlope2 != 0) //line1 vertical, line2 is not
{ //there is a unique intersection
switch (lOrient) {
case 0: //Line1 above segment1
case 1:
X.value[0] = p2.x - dWidth2;
Y.value[0] = m2 * X.value[0] + b2;
break;
case 2: //Line1 below segment1
case 3:
X.value[0] = p2.x + dWidth2;
Y.value[0] = m2 * X.value[0] + b2;
break;
default: //can not occur
X.value[0] = p2.x;
Y.value[0] = p2.y;
break;
}
return 1;
}
if (bolVerticalSlope2 == 0 && bolVerticalSlope1 != 0) //line2 vertical, line1 is not
{ //there is a unique intersection
switch (lOrient) {
case 0: //Line1 above segment2
case 2:
X.value[0] = p2.x - dWidth2;
Y.value[0] = m1 * (X.value[0]) + b1;
break;
case 1: //Line1 below segment2
case 3:
X.value[0] = p2.x + dWidth2;
Y.value[0] = m1 * (X.value[0]) + b1;
break;
default: //can not occur
X.value[0] = p2.x;
Y.value[0] = p2.y;
break;
}
return 1;
}//end if
//must deal with this case separately because normal lines use m1-m2 as a denominator
//but we've handled all the vertical cases above so can assume it's not vertical
//if the b's are different then one is an upper line, the other is a lower, no intersection
//m and b will be used to build the perpendicular line thru p2 which we will use to
//build the intersection, so must assume slopes are not 0, handle separately
if (m1 == m2 && m1 != 0) {
if (b1 == b2) //then the intercept is the point joining the 2 segments
{
//build the perpendicular line
m = -1 / m1;
b = p2.y - m * p2.x;
X.value[0] = (b2 - b) / (m - m2); //intersect the lines (cannot blow up, m = m2 not possible)
Y.value[0] = (m1 * (X.value[0]) + b1);
return 1;
} else //can not occur
{
X.value[0] = p2.x;
Y.value[0] = p2.y;
return 1;
}
}
//slope is zero
if (m1 == m2 && m1 == 0) {
switch (lOrient) {
case 0: //Line1 above the line
case 1: //should never happen
X.value[0] = p2.x;
Y.value[0] = p2.y - dWidth2;
break;
case 3: //Line1 below the line
case 2: //should never happen
X.value[0] = p2.x;
Y.value[0] = p2.y + dWidth2;
break;
default: //can not occur
X.value[0] = p2.x;
Y.value[0] = p2.y;
break;
}
return 1;
}
if (m1 == m2 && b1 == b2 && bolVerticalSlope1 != 0 && bolVerticalSlope2 != 0) {
switch (lOrient) {
case 0: //Line1 is above the line
if (m1 < 0) {
dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative
dx = dy / m1; //dx is negative
X.value[0] = p2.x + dx;
Y.value[0] = p2.y + dy;
}
if (m1 > 0) //slope is positive
{
dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative
dx = -dy / m1; //dx is positive
X.value[0] = p2.x + dx;
Y.value[0] = p2.y + dy;
}
break;
case 3: //Line1 is below the line
if (m1 <= 0) {
dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive
dx = dy / m1; //dx is positive
X.value[0] = p2.x + dx;
Y.value[0] = p2.y + dy;
} else {
dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive
dx = -dy / m1; //dx is negative
X.value[0] = p2.x + dx;
Y.value[0] = p2.y + dy;
}
break;
default:
X.value[0] = p2.x;
Y.value[0] = p2.y;
break;
}
return 1;
}//end if
//a normal line. no vertical or identical slopes
//if m1=m2 function will not reach this point
X.value[0] = (b2 - b1) / (m1 - m2); //intersect the lines
Y.value[0] = (m1 * (X.value[0]) + b1);
return 1;
}//end try
catch (Exception exc) {
X.value[0] = p2.x;
Y.value[0] = p2.y;
ErrorLogger.LogException(_className, "CalcTrueIntersectDouble",
new RendererException("Failed inside ExtendTrueIntersectDouble", exc));
}
return 1;
}
/**
* Returns the distance in pixels from x1,y1 to x2,y2
*
* @param x1 first point x location in pixels
* @param y1 first point y location in pixels
* @param x2 second point x location in pixels
* @param y2 second point y location in pixels
*
* @return the distance
*/
protected static double CalcDistance2(long x1,
long y1,
long x2,
long y2) {
double dResult = 0;
try {
dResult = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
//sanity check
//return x or y distance if return value is 0 or infinity
double xdist = Math.abs(x1 - x2);
double ydist = Math.abs(y1 - y2);
double max = xdist;
if (ydist > xdist) {
max = ydist;
}
if (dResult == 0 || Double.isInfinite(dResult)) {
if (max > 0) {
dResult = max;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcDistance2",
new RendererException("Failed inside CalcDistance2", exc));
}
return dResult;
}
/**
* gets the middle line for Rev B air corridors AC, LLTR, MRR, UAV
* Middle line is handled separately now because the line may have been segmented
* @param pLinePoints
* @return
*/
protected static POINT2[] GetSAAFRMiddleLine(POINT2[] pLinePoints) {
POINT2[] pts = null;
try {
int j = 0, count = 0;
for (j = 0; j < pLinePoints.length-1; j++) {
if (pLinePoints[j].style > 0) {
count++;
}
}
pts = new POINT2[count*2];
count=0;
double dMRR=0;
POINT2 firstSegPt=null,lastSegPt=null,pt0=null,pt1=null;
for (j = 0; j < pLinePoints.length; j++) {
if(pLinePoints[j].style>=0 || j==pLinePoints.length-1)
{
if(lastSegPt != null)
{
firstSegPt=new POINT2(lastSegPt);
lastSegPt=new POINT2(pLinePoints[j]);
dMRR=firstSegPt.style;
pt0 = ExtendLine2Double(lastSegPt, firstSegPt, -dMRR, 0);
pt1 = ExtendLine2Double(firstSegPt, lastSegPt, -dMRR, 5);
pts[count++]=pt0;
pts[count++]=pt1;
}
else
{
lastSegPt=new POINT2(pLinePoints[j]);
}
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetSAAFRMiddleLine",
new RendererException("Failed inside GetSAAFRMiddleLine", exc));
}
return pts;
}
/**
* Computes the points for a SAAFR segment
*
* @param pLinePoints OUT - the client points also used for the returned
* points
* @param lineType the line type
* @param dMRR the symbol width
*/
protected static void GetSAAFRSegment(POINT2[] pLinePoints,
int lineType,
double dMRR,
int rev) {
try {
POINT2 pt0 = new POINT2();
POINT2 pt1 = new POINT2();
POINT2 pt2 = new POINT2();
POINT2 pt3 = new POINT2();
POINT2 pt4 = new POINT2();
POINT2 pt5 = new POINT2();
ref<double[]> m = new ref();
int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m);
//shortened line
//pt1=ExtendLine2Double(pLinePoints[0],pLinePoints[1],-dMRR/2,5);
//pt0=ExtendLine2Double(pLinePoints[1],pLinePoints[0],-dMRR/2,0);
pt1 = ExtendLine2Double(pLinePoints[0], pLinePoints[1], -dMRR, 5);
pt0 = ExtendLine2Double(pLinePoints[1], pLinePoints[0], -dMRR, 0);
if (bolVertical != 0 && m.value[0] < 1) {
//upper line
pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR);
pt2.style = 0;
pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR);
pt3.style = 5;
//lower line
pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR);
pt4.style = 0;
pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR);
pt5.style = 5;
} //if( (bolVertical!=0 && m>1) || bolVertical==0)
else {
//left line
pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR);
pt2.style = 0;
pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR);
pt3.style = 5;
//right line
pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR);
pt4.style = 0;
pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR);
pt5.style = 5;
}
//load the line points
pLinePoints[0] = new POINT2(pt0);
pLinePoints[1] = new POINT2(pt1);
pLinePoints[2] = new POINT2(pt2);
pLinePoints[3] = new POINT2(pt3);
pLinePoints[4] = new POINT2(pt4);
pLinePoints[5] = new POINT2(pt5);
pLinePoints[5].style = 5;
// if (lineType == TacticalLines.SAAFR) {
// pLinePoints[0].style = 5;
// }
// if (rev == RendererSettings.Symbology_2525C) {
// pLinePoints[0].style = 5;
// }
pLinePoints[0].style = 5;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetSAAFRSegment",
new RendererException("Failed inside GetSAAFRSegment", exc));
}
}
/**
* Called by arraysupport for SAAFR and AC fill shapes
* @param pLinePoints
* @param lineType
* @param dMRR
* @param rev
*/
protected static void GetSAAFRFillSegment(POINT2[] pLinePoints,
double dMRR) {
try {
POINT2 pt2 = new POINT2();
POINT2 pt3 = new POINT2();
POINT2 pt4 = new POINT2();
POINT2 pt5 = new POINT2();
ref<double[]> m = new ref();
int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m);
if (bolVertical != 0 && m.value[0] < 1) {
//upper line
pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR);
pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR);
//lower line
pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR);
pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR);
} //if( (bolVertical!=0 && m>1) || bolVertical==0)
else {
//left line
pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR);
pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR);
//right line
pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR);
pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR);
}
//load the line points
pLinePoints[0] = new POINT2(pt2);
pLinePoints[1] = new POINT2(pt3);
pLinePoints[2] = new POINT2(pt5);
pLinePoints[3] = new POINT2(pt4);
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetSAAFRFillSegment",
new RendererException("Failed inside GetSAAFRFillSegment", exc));
}
//return;
}
/**
* Computes an arc.
*
* @param pResultlinePoints OUT - contains center and start point and holds
* the result arc points
* @param vblCounter the number of client points
* @param dRadius the arc radius in pixels
* @param linetype the linetype determines start andgle and end angle for
* the arc
*
*/
protected static POINT2[] ArcArrayDouble(POINT2[] pResultLinePoints,
int vblCounter,
double dRadius,
int linetype,
IPointConversion converter) {
try {
//declarations
double startangle = 0, //start of pArcLinePoints
endangle = 0, //end of the pArcLinePoints
increment = 0,
//m = 0,
length = 0, //length of a to e
M = 0;
int j, numarcpts = 0, bolVertical = 0;
ref<double[]> m = new ref();
//C is the center of the pArcLinePoints derived from a and e
POINT2 C = new POINT2(pResultLinePoints[0]),
a = new POINT2(pResultLinePoints[1]),
e = new POINT2(pResultLinePoints[0]);
POINT2[] pArcLinePoints = null;
//end declarations
bolVertical = CalcTrueSlopeDouble(a, e, m);
if (bolVertical != 0) {
M = Math.atan(m.value[0]);
} else {
if (a.y < e.y) {
M = -Math.PI / 2;
} else {
M = Math.PI / 2;
}
}
if(converter != null)
{
Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y);
//boolean reverseM=false;
pt02d=converter.PixelsToGeo(pt02d);
pt12d=converter.PixelsToGeo(pt12d);
//M=mdlGeodesic.GetAzimuth(pt02d,pt12d);
M=mdlGeodesic.GetAzimuth(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY() ) );
M*=(Math.PI/180);
if(M<0)
M+=Math.PI;
}
length = CalcDistanceDouble(a, e);
if(converter != null)
{
Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y);
pt02d=converter.PixelsToGeo(pt02d);
pt12d=converter.PixelsToGeo(pt12d);
//length=mdlGeodesic.geodesic_distance(pt02d,pt12d,null,null);
length=mdlGeodesic.geodesic_distance(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY()),null,null);
}
switch (linetype) {
case TacticalLines.CLUSTER:
startangle = M - 90 * Math.PI / 180.0;
endangle = startangle + 2 * 90 * Math.PI / 180.0;
break;
case TacticalLines.TRIP:
startangle = M - 45 * Math.PI / 180.0;
endangle = startangle + 2 * 45 * Math.PI / 180.0;
break;
case TacticalLines.ISOLATE:
case TacticalLines.CORDONKNOCK:
case TacticalLines.CORDONSEARCH:
startangle = M;
endangle = startangle + 330 * Math.PI / 180;
break;
case TacticalLines.TURN:
startangle = M;
endangle = startangle + 90 * Math.PI / 180;
break;
case TacticalLines.OCCUPY:
case TacticalLines.RETAIN:
case TacticalLines.SECURE:
startangle = M;
//if(CELineArrayGlobals.Change1==false)
endangle = startangle + 338 * Math.PI / 180;
//else
// endangle=startangle+330*pi/180;
break;
default:
startangle = 0;
endangle = 2 * Math.PI;
break;
}
if (a.x < e.x) {
switch (linetype) {
case TacticalLines.ISOLATE:
case TacticalLines.CORDONKNOCK:
case TacticalLines.CORDONSEARCH:
startangle = M - Math.PI;
endangle = startangle + 330 * Math.PI / 180;
break;
case TacticalLines.OCCUPY:
case TacticalLines.RETAIN:
case TacticalLines.SECURE:
startangle = M - Math.PI;
//if(CELineArrayGlobals.Change1==false)
endangle = startangle + 338 * Math.PI / 180;
//else
// endangle=startangle+330*pi/180;
break;
case TacticalLines.TURN:
startangle = M - Math.PI;
endangle = startangle + 90 * Math.PI / 180;
break;
case TacticalLines.CLUSTER:
startangle = M - Math.PI + 90 * Math.PI / 180.0;
endangle = startangle - 2 * 90 * Math.PI / 180.0;
break;
case TacticalLines.TRIP:
startangle = M - Math.PI + 45 * Math.PI / 180.0;
endangle = startangle - 2 * 45 * Math.PI / 180.0;
break;
default:
break;
}
}
numarcpts = 26;
pArcLinePoints = new POINT2[numarcpts];
InitializePOINT2Array(pArcLinePoints);
increment = (endangle - startangle) / (numarcpts - 1);
if(dRadius != 0 && length != 0)
{
C.x = (int) ((double) e.x - (dRadius / length)
* ((double) a.x - (double) e.x));
C.y = (int) ((double) e.y - (dRadius / length)
* ((double) a.y - (double) e.y));
}
else
{
C.x=e.x;
C.y=e.y;
}
if (converter != null)
{
Point2D C2d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
C2d=converter.PixelsToGeo(C2d);
double az=0;
Point2D ptGeo2d=null;
POINT2 ptGeo=null;
POINT2 ptPixels=null;
for (j = 0; j < numarcpts; j++) {
az=startangle*180/Math.PI+j*increment*180/Math.PI;
//ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az);
ptGeo=mdlGeodesic.geodesic_coordinate(new POINT2(C2d.getX(),C2d.getY()),length,az);
ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y);
ptGeo2d=converter.GeoToPixels(ptGeo2d);
ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY());
pArcLinePoints[j].x = ptPixels.x;
pArcLinePoints[j].y = ptPixels.y;
}
}
else
{
for (j = 0; j < numarcpts; j++) {
//pArcLinePoints[j]=pResultLinePoints[0]; //initialize
pArcLinePoints[j].x = (int) (dRadius * Math.cos(startangle + j * increment));
pArcLinePoints[j].y = (int) (dRadius * Math.sin(startangle + j * increment));
}
for (j = 0; j < numarcpts; j++) {
pArcLinePoints[j].x += C.x;
pArcLinePoints[j].y += C.y;
}
}
switch (linetype) {
case TacticalLines.ISOLATE:
case TacticalLines.CORDONKNOCK:
case TacticalLines.CORDONSEARCH:
case TacticalLines.OCCUPY:
case TacticalLines.RETAIN:
case TacticalLines.SECURE:
case TacticalLines.CLUSTER:
case TacticalLines.TURN:
case TacticalLines.TRIP:
for (j = 0; j < numarcpts; j++) {
pResultLinePoints[j] = new POINT2(pArcLinePoints[j]);
}
break;
default:
for (j = 0; j < numarcpts; j++) {
pResultLinePoints[j] = new POINT2(pArcLinePoints[j]);
}
break;
}
pArcLinePoints = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "ArcArrayDouble",
new RendererException("Failed inside ArcArrayDouble", exc));
}
return pResultLinePoints;
}
/**
* Gets geodesic circle using the converter
* @param Center in pixels
* @param pt1 a point on the radius in pixels
* @param numpts number of points to return
* @param CirclePoints the result points
* @param converter
*/
protected static void CalcCircleDouble2(POINT2 Center,
POINT2 pt1,
int numpts,
POINT2[] CirclePoints,
IPointConversion converter) {
try {
int j = 0;
double increment = (Math.PI * 2) / (numpts - 1);
Point2D ptCenter2d=new Point2D.Double(Center.x,Center.y);
ptCenter2d=converter.PixelsToGeo(ptCenter2d);
Point2D pt12d=new Point2D.Double(pt1.x,pt1.y);
pt12d=converter.PixelsToGeo(pt12d);
Center=new POINT2(ptCenter2d.getX(),ptCenter2d.getY());
pt1=new POINT2(pt12d.getX(),pt12d.getY());
double dist=mdlGeodesic.geodesic_distance(Center, pt1, null, null);
//double dSegmentAngle = 2 * Math.PI / numpts;
double az=0;
double startangle=0,endAngle=Math.PI*2;
POINT2 ptGeo=null,ptPixels=null;
Point2D ptGeo2d=null;
for (j = 0; j < numpts - 1; j++) {
az=startangle*180/Math.PI+j*increment*180/Math.PI;
//ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az);
ptGeo=mdlGeodesic.geodesic_coordinate(Center,dist,az);
ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y);
ptGeo2d=converter.GeoToPixels(ptGeo2d);
ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY());
CirclePoints[j].x = ptPixels.x;
CirclePoints[j].y = ptPixels.y;
}
CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]);
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcCircleDouble2",
new RendererException("Failed inside CalcCircleDouble2", exc));
}
return;
}
/**
* Computes the points for a circle. Assumes CirclePoints has been allocated
* with size numpts.
*
* @param Center the cicle center
* @param radius the circle radius in pixels
* @param numpts the number of circle points
* @param CirclePoints - OUT - array of circle points
* @param styl the style to set the last circle point
*/
protected static void CalcCircleDouble(POINT2 Center,
double radius,
int numpts,
POINT2[] CirclePoints,
int styl) {
try {
int j = 0;
double dSegmentAngle = 2 * Math.PI / numpts;
double x = 0, y = 0;
for (j = 0; j < numpts - 1; j++) {
x = Center.x + (radius * Math.cos((double) j * dSegmentAngle));
y = Center.y + (radius * Math.sin((double) j * dSegmentAngle));
CirclePoints[j] = new POINT2(x, y);
CirclePoints[j].style = styl;
}
CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]);
switch (styl) {
case 0:
CirclePoints[numpts - 1].style = 0;
break;
case 9:
CirclePoints[numpts - 1].style = 10;
break;
case 11:
CirclePoints[numpts - 1].style = 12;
break;
default:
CirclePoints[numpts - 1].style = 5;
break;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcCircleDouble",
new RendererException("Failed inside CalcCircleDouble", exc));
}
}
protected static Shape2 CalcCircleShape(POINT2 Center,
double radius,
int numpts,
POINT2[] CirclePoints,
int styl) {
Shape2 shape;
if (styl == 9) {
shape = new Shape2(Shape2.SHAPE_TYPE_FILL);
} else {
shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
}
shape.set_Style(styl);
try {
int j = 0;
CalcCircleDouble(Center, radius, numpts, CirclePoints, styl);
shape.moveTo(CirclePoints[0]);
for (j = 1; j < numpts; j++) {
shape.lineTo(CirclePoints[j]);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcCircleShape",
new RendererException("Failed inside CalcCircleShape", exc));
}
return shape;
}
private static void GetSquallCurve(POINT2 StartPt,
POINT2 EndPt,
POINT2[] pSquallPts,
int sign,
int amplitude,
int quantity) {
try {
double dist = CalcDistanceDouble(StartPt, EndPt);
POINT2 ptTemp = new POINT2();
int j = 0;
//end declarations
//get points along the horizontal segment between StartPt and EndPt2;
for (j = 0; j < quantity; j++) {
ptTemp = ExtendLineDouble(EndPt, StartPt, -dist * (double) j / (double) quantity);
pSquallPts[j].x = ptTemp.x;
//calculate the sin value along the x axis
pSquallPts[j].y = ptTemp.y + amplitude * sign * Math.sin((double) j * 180 / (double) quantity * Math.PI / 180);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetSquallShape",
new RendererException("Failed inside GeSquallShape", exc));
}
}
//caller needs to instantiate sign.value
/**
* Gets the squall curves for a line segment Assumes pSquallPts has been
* allocated the proper number of points.
*
* @param StartPt segment start point
* @param EndPt segment end point
* @param pSquallPts OUT - the squall points
* @param sign OUT - an object with a member to hold the starting curve sign
* for the segment.
* @param amplitude the sin curve amplitutde
* @param quantity the number of points for each sin curve
* @param length the desired length of the curve along the segment for each
* sin curve
*
* @return segment squall points count
*/
protected static int GetSquallSegment(POINT2 StartPt,
POINT2 EndPt,
POINT2[] pSquallPts,
ref<int[]> sign,
int amplitude,
int quantity,
int length) {
int counter = 0;
try {
POINT2 StartCurvePt, EndCurvePt; //use these for the curve points
POINT2[] pSquallPts2 = new POINT2[quantity];
double dist = CalcDistanceDouble(StartPt, EndPt);
int numCurves = (int) (dist / (double) length);
int j = 0, k = 0;
POINT2 EndPt2 = new POINT2();
double angle = Math.atan((StartPt.y - EndPt.y) / (StartPt.x - EndPt.x));
int lAngle = (int) ((180 / Math.PI) * angle);
InitializePOINT2Array(pSquallPts2);
//define EndPt2 to be the point dist from StartPt along the x axis
if (StartPt.x < EndPt.x) {
EndPt2.x = StartPt.x + dist;
} else {
EndPt2.x = StartPt.x - dist;
}
EndPt2.y = StartPt.y;
EndCurvePt = StartPt;
for (j = 0; j < numCurves; j++) {
StartCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) (j * length));
EndCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) ((j + 1) * length));
//get the curve points
GetSquallCurve(StartCurvePt, EndCurvePt, pSquallPts2, sign.value[0], amplitude, quantity);
//fill the segment points with the curve points
for (k = 0; k < quantity; k++) {
//pSquallPts[counter].x=pSquallPts2[k].x;
//pSquallPts[counter].y=pSquallPts2[k].y;
pSquallPts[counter] = new POINT2(pSquallPts2[k]);
counter++;
}
//reverse the sign
sign.value[0] = -sign.value[0];
}
if (numCurves == 0) {
pSquallPts[counter] = new POINT2(StartPt);
counter++;
pSquallPts[counter] = new POINT2(EndPt);
counter++;
}
//the points are along the x axis. Rotate them about the first point as the origin
RotateGeometryDoubleOrigin(pSquallPts, counter, lAngle);
pSquallPts2 = null;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetSquallSegment",
new RendererException("Failed inside GetSquallSegment", exc));
}
return counter;
}
//temporarily using 2000 pixels
private static int PointInBounds(POINT2 pt) {
try {
//double maxPixels=CELineArrayGlobals.MaxPixels2;
double maxPixels = 100000;//was 2000
if (Math.abs(pt.x) <= maxPixels && Math.abs(pt.y) <= maxPixels) {
return 1;
} else {
return 0;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "PointInBounds",
new RendererException("Failed inside PointInBounds", exc));
}
return 1;
}
/**
* @param pt
* @param ul
* @param lr
* @return
*/
private static int PointInBounds2(POINT2 pt, POINT2 ul, POINT2 lr) {
try {
double maxX = lr.x, minX = ul.x, maxY = lr.y, minY = ul.y;
if (pt.x <= maxX && pt.x >= minX && pt.y <= maxY && pt.y >= minY) {
return 1;
} else {
return 0;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "PointInBounds2",
new RendererException("Failed inside PointInBounds2", exc));
}
return 1;
}
/**
* Analyzes if line from pt0 to pt 1 intersects a side and returns the
* intersection or null assumes pt0 to pt1 is not vertical. the caller will
* replace pt0 with the intersection point if it is not null
*
* @param pt0
* @param pt1
* @param sidePt0 vertical or horizontal side first point
* @param sidePt1
* @return null if it does not intersect the side
*/
private static POINT2 intersectSegment(POINT2 pt0, POINT2 pt1, POINT2 sidePt0, POINT2 sidePt1) {
POINT2 pt = null;
try {
if (pt0.x == pt1.x) {
return null;
}
double m = (pt1.y - pt0.y) / (pt1.x - pt0.x);
double dx = 0, dy = 0, x = 0, y = 0;
POINT2 upper = null, lower = null, left = null, right = null;
Boolean bolVertical = false;
//the side is either vertical or horizontal
if (sidePt0.x == sidePt1.x) //vertical side
{
bolVertical = true;
if (sidePt0.y < sidePt1.y) {
upper = sidePt0;
lower = sidePt1;
} else {
upper = sidePt1;
lower = sidePt0;
}
} else //horizontal side
{
if (sidePt0.x < sidePt1.x) {
left = sidePt0;
right = sidePt1;
} else {
left = sidePt1;
right = sidePt0;
}
}
//travel in the direction from pt0 to pt1 to find the pt0 intersect
if (bolVertical) { //the side to intersect is vertical
dx = upper.x - pt0.x;
dy = m * dx;
x = upper.x;
y = pt0.y + dy;
//the potential intersection point
pt = new POINT2(x, y);
if (pt0.x <= pt.x && pt.x <= pt1.x) //left to right
{
if (upper.y <= pt.y && pt.y <= lower.y) {
return pt;
}
} else if (pt0.x >= pt.x && pt.x >= pt1.x) //right to left
{
if (upper.y <= pt.y && pt.y <= lower.y) {
return pt;
}
}
} else //horizontal side
{
dy = left.y - pt0.y;
dx = dy / m;
x = pt0.x + dx;
y = left.y;
//the potential intersection point
pt = new POINT2(x, y);
if (pt0.y <= pt.y && pt.y <= pt1.y) {
if (left.x <= pt.x && pt.x <= right.x) {
return pt;
}
} else if (pt0.y >= pt.y && pt.y >= pt1.y) {
if (left.x <= pt.x && pt.x <= right.x) {
return pt;
}
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "intersectSegment",
new RendererException("Failed inside intersectSegment", exc));
}
return null;
}
/**
* side 1 ----- | | side 0 | | side 2 | | ------ side 3 bounds one segment
* for autoshapes that need it: bydif, fordif, fix, mnfldfix if null is
* returned the client should conect the original line points (i.e. no
* jaggies)
*
* @param pt0
* @param pt1
* @param ul
* @param lr
* @return bounded segment or null
*/
public static POINT2[] BoundOneSegment(POINT2 pt0, POINT2 pt1, POINT2 ul, POINT2 lr) {
POINT2[] line = new POINT2[2];
try {
if (pt0.y < ul.y && pt1.y < ul.y) {
return null;
}
if (pt0.y > lr.y && pt1.y > lr.y) {
return null;
}
if (pt0.x < ul.x && pt1.x < ul.x) {
return null;
}
if (pt0.x > lr.x && pt1.x > lr.x) {
return null;
}
Boolean bolVertical = false;
InitializePOINT2Array(line);
if (pt0.x == pt1.x) {
bolVertical = true;
}
if (bolVertical) {
line[0] = new POINT2(pt0);
if (line[0].y < ul.y) {
line[0].y = ul.y;
}
if (line[0].y > lr.y) {
line[0].y = lr.y;
}
line[1] = new POINT2(pt1);
if (line[1].y < ul.y) {
line[1].y = ul.y;
}
if (line[1].y > lr.y) {
line[1].y = lr.y;
}
return line;
}
double dx = 0, dy = 0, x = 0, y = 0;
double m = (pt1.y - pt0.y) / (pt1.x - pt0.x);
Boolean side0Intersect = false,
side1Intersect = false,
side2Intersect = false,
side3Intersect = false;
//travel in the direction from pt0 to pt1 to find pt0 intersect
POINT2 ur = new POINT2(lr.x, ul.y);
POINT2 ll = new POINT2(ul.x, lr.y);
POINT2 pt0Intersect = null;
if (PointInBounds2(pt0, ul, lr) == 1) {
pt0Intersect = pt0;
}
if (pt0Intersect == null) {
pt0Intersect = intersectSegment(pt0, pt1, ll, ul); //interesect side 0
side0Intersect = true;
}
if (pt0Intersect == null) {
pt0Intersect = intersectSegment(pt0, pt1, ul, ur); //interesect side 1
side1Intersect = true;
}
if (pt0Intersect == null) {
pt0Intersect = intersectSegment(pt0, pt1, ur, lr); //interesect side 2
side2Intersect = true;
}
if (pt0Intersect == null) {
pt0Intersect = intersectSegment(pt0, pt1, ll, lr); //interesect side 3
side3Intersect = true;
}
//travel in the direction from pt1 to pt0 to find pt1 intersect
POINT2 pt1Intersect = null;
if (PointInBounds2(pt1, ul, lr) == 1) {
pt1Intersect = pt1;
}
if (pt1Intersect == null && side0Intersect == false) {
pt1Intersect = intersectSegment(pt1, pt0, ll, ul); //interesect side 0
}
if (pt1Intersect == null && side1Intersect == false) {
pt1Intersect = intersectSegment(pt1, pt0, ul, ur); //interesect side 1
}
if (pt1Intersect == null && side2Intersect == false) {
pt1Intersect = intersectSegment(pt1, pt0, ur, lr); //interesect side 2
}
if (pt1Intersect == null && side3Intersect == false) {
pt1Intersect = intersectSegment(pt1, pt0, ll, lr); //interesect side 3
}
if (pt0Intersect != null && pt1Intersect != null) {
line[0] = pt0Intersect;
line[1] = pt1Intersect;
//return line;
} else {
line = null;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "BoundOneSegment",
new RendererException("Failed inside BoundOneSegment", exc));
}
return line;
}
private static int DisplayIntersectPixels(POINT2 pt0,
POINT2 pt1,
ref<double[]> pt2x,
ref<double[]> pt2y,
ref<double[]> pt3x,
ref<double[]> pt3y) //POINT2 ul,
//POINT2 lr)
{
int nResult = -1;
try {
//declarations
double X = 0, Y = 0;
ref<double[]> m = new ref();
//double maxPixels=CELineArrayGlobals.MaxPixels2;
double maxPixels = 2000;
//double maxX=lr.x,minX=ul.x,maxY=lr.y,minY=ul.y;
int bol0Inside = 0, bol1Inside = 0;
int bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
double b = pt0.y - m.value[0] * pt0.x; //the y intercept for the segment line
POINT2 pt2, pt3;
//end declarations
pt2x.value = new double[1];
pt2y.value = new double[1];
pt3x.value = new double[1];
pt3y.value = new double[1];
pt2 = new POINT2(pt0);
pt3 = new POINT2(pt1);
//diagnostic
if (pt0.x <= maxPixels && pt0.x >= -maxPixels
&& pt0.y <= maxPixels && pt0.y >= -maxPixels) {
bol0Inside = 1;
}
if (pt1.x <= maxPixels && pt1.x >= -maxPixels
&& pt1.y <= maxPixels && pt1.y >= -maxPixels) {
bol1Inside = 1;
}
//if both points are inside the area then use the whole segment
if (bol0Inside == 1 && bol1Inside == 1) {
return 0;
}
//if at leat one of the points is inside the area then use some of the segment
if (bol0Inside == 1 || bol1Inside == 1) {
nResult = 1;
}
//segment is not vertical
if (bolVertical != 0) {
//analysis for side 0, get the intersection for either point if it exists
//diagnostic
X = -maxPixels;
//X=minX;
Y = m.value[0] * X + b;
if (pt0.x < -maxPixels && -maxPixels < pt1.x) //pt0 is outside the area
{
if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0
//if(minY<=Y && Y<=maxY) //intersection is on side 0
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
}
if (pt1.x < -maxPixels && -maxPixels < pt0.x) //pt1 is outside the area
//if(pt1.x<minX && minX<pt0.x) //pt1 is outside the area
{
if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
}
//analysis for side 1, get the intersection for either point if it exists
Y = -maxPixels;
if (m.value[0] != 0) {
X = (Y - b) / m.value[0];
if (pt0.y < -maxPixels && -maxPixels < pt1.y) //pt0 is outside the area
{
if (-maxPixels <= X && X <= maxPixels) //intersection is on side 1
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
}
if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 is outside the area
{
if (-maxPixels < X && X < maxPixels) //intersection is on the boundary
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
}
}
//analysis for side 2, get the intersection for either point if it exists
X = maxPixels;
Y = m.value[0] * X + b;
if (pt0.x < maxPixels && maxPixels < pt1.x) //pt1 is outside the area
{
if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
}
if (pt1.x < maxPixels && maxPixels < pt0.x) //pt0 is outside the area
{
if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
}
//analysis for side 3, get the intersection for either point if it exists
Y = maxPixels;
if (m.value[0] != 0) {
X = (Y - b) / m.value[0];
if (pt0.y < maxPixels && maxPixels < pt1.y) //pt1 is outside the area
{
if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
}
if (pt1.y < maxPixels && maxPixels < pt0.y) //pt0 is outside the area
{
if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
}
}
}
//segment is vertical
if (bolVertical == 0) {
//analysis for side 1
X = pt0.x;
Y = -maxPixels;
if (-maxPixels < pt0.x && pt0.x < maxPixels) {
if (pt0.y <= -maxPixels && -maxPixels <= pt1.y) //pt0 outside the area
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 outside the area
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
}
//analysis for side 3
X = pt0.x;
Y = maxPixels;
if (-maxPixels < pt0.x && pt0.x < maxPixels) {
if (pt0.y <= maxPixels && maxPixels <= pt1.y) //pt1 outside the area
{
pt3.x = X;
pt3.y = Y;
nResult = 1; //use at least some of the pixels
}
if (pt1.y <= maxPixels && maxPixels <= pt0.y) //pt0 outside the area
{
pt2.x = X;
pt2.y = Y;
nResult = 1; //use at least some of the pixels
}
}
}
pt2x.value[0] = pt2.x;
pt2y.value[0] = pt2.y;
pt3x.value[0] = pt3.x;
pt3y.value[0] = pt3.y;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "DisplayIntersectPixels",
new RendererException("Failed inside DisplayIntersectPixels", exc));
}
return nResult;
}
/**
* Computes Ditch spikes for the ATDITCH line types. This function uses
* linestyles provided by the caller to skip segments.
*
* @param pLinePoints OUT - the client points also used for the return
* points
* @param nOldCounter the number of client points
* @param bWayIs the parallel line to use (0) for inner or outer spikes
* @param linetype the line type
*
* @return the symbol point count
*/
protected static int GetDitchSpikeDouble(POINT2[] pLinePoints,
int nOldCounter,
int bWayIs,
int linetype) {
int nSpikeCounter = 0;
try {
//declarations
int nNumberOfSegments = 0,
lCircleCounter = 0,
bolVertical = 0,
nTemp = 0,
i,
j;
double dPrinter = 1.0;
double dIntLocation1x = 0,
dIntLocation2x = 0,
dIntLocation1y = 0,
dIntLocation2y = 0,
r = 0,
s = 0,
use = 0,
length = 0,
k = 0,
bint = 0;
ref<double[]> pdAnswer = new ref();//new double[6];
ref<double[]> m = new ref();
POINT2 UpperLinePoint = new POINT2(pLinePoints[0]),
Lower1LinePoint = new POINT2(pLinePoints[0]),
Lower2LinePoint = new POINT2(pLinePoints[0]),
a = new POINT2(pLinePoints[0]),
b = new POINT2(pLinePoints[0]);
POINT2[] pCirclePoints = new POINT2[pLinePoints.length];
POINT2 averagePoint = new POINT2();
POINT2 lastAveragePoint = new POINT2();
POINT2[] pTempLinePoints = null;
double minLength = 24;
//end declarations
pTempLinePoints = new POINT2[nOldCounter];
for (j = 0; j < nOldCounter; j++) {
pTempLinePoints[j] = new POINT2(pLinePoints[j]);
}
ArrayList<POINT2> basePoints = new ArrayList();
InitializePOINT2Array(pCirclePoints);
nSpikeCounter = nOldCounter;
for (i = 0; i < nOldCounter - 1; i++) {
if (linetype == TacticalLines.ATDITCHM && i == 0) {
minLength = 38;
}
nTemp = CalcTrueLinesDouble(15 * (int) dPrinter, pLinePoints[i], pLinePoints[i + 1], pdAnswer);
r = pdAnswer.value[3];
s = pdAnswer.value[5];
length = CalcDistanceDouble(pLinePoints[i], pLinePoints[i + 1]);
bolVertical = CalcTrueSlopeDouble(pLinePoints[i], pLinePoints[i + 1], m);
nNumberOfSegments = (int) ((length - 1) / (12 * dPrinter));
if (length > minLength * dPrinter) { //minLength was 24
if (bWayIs != 0) {
if (pLinePoints[i].x <= pLinePoints[i + 1].x) {
use = r;
}
if (pLinePoints[i].x >= pLinePoints[i + 1].x) {
use = s;
}
} //end if
else {
if (pLinePoints[i].x <= pLinePoints[i + 1].x) {
use = s;
}
if (pLinePoints[i].x >= pLinePoints[i + 1].x) {
use = r;
}
} //end else
for (j = 1; j <= nNumberOfSegments; j++) {
k = (double) j;
a = new POINT2(pLinePoints[i]);
b = new POINT2(pLinePoints[i + 1]);
if (j > 1) {
dIntLocation1x = dIntLocation2x;
} else {
dIntLocation1x
= (double) pLinePoints[i].x + ((k * 12.0 - 12) * dPrinter / length)
* (double) (pLinePoints[i + 1].x - pLinePoints[i].x);
}
if (j > 1) //added M. Deutch 2-23-99
{
dIntLocation1y = dIntLocation2y;
} else {
dIntLocation1y
= (double) pLinePoints[i].y + ((k * 12.0 - 6.0) * dPrinter / length)
* (double) (pLinePoints[i + 1].y - pLinePoints[i].y);
}
dIntLocation2x = (double) pLinePoints[i].x
+ ((k * 12.0 + 6.0) * dPrinter / length)
* (double) (pLinePoints[i + 1].x
- pLinePoints[i].x);
dIntLocation2y = (double) pLinePoints[i].y
+ ((k * 12.0 + 6.0) * dPrinter / length)
* (double) (pLinePoints[i + 1].y
- pLinePoints[i].y);
if (m.value[0] != 0 && bolVertical != 0) {
bint = (dIntLocation1y + dIntLocation2y) / 2.0
+ (1 / m.value[0]) * (dIntLocation1x + dIntLocation2x) / 2.0;
//independent of direction
UpperLinePoint = CalcTrueIntersectDouble2(m.value[0], use, -1 / m.value[0], bint, 1, 1, pLinePoints[0].x, pLinePoints[0].y);
}
if (bolVertical == 0) //vertical segment
{
if (dIntLocation1y < dIntLocation2y) {
UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments / 2);
} else {
UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments / 2);
}
if (pLinePoints[i].y < pLinePoints[i + 1].y) {
UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments);
} else {
UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments);
}
}
if (m.value[0] == 0 && bolVertical != 0) {
if (dIntLocation1x < dIntLocation2x) {
UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments / 2);
} else {
UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments / 2);
}
if (pLinePoints[i + 1].x < pLinePoints[i].x) {
UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments);
} else {
UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments);
}
}
//end section
Lower1LinePoint.x = dIntLocation1x;
Lower1LinePoint.y = dIntLocation1y;
Lower2LinePoint.x = dIntLocation2x;
Lower2LinePoint.y = dIntLocation2y;
pLinePoints[nSpikeCounter] = new POINT2(Lower1LinePoint);
if (linetype == TacticalLines.ATDITCHC || linetype == TacticalLines.ATDITCHM) {
pLinePoints[nSpikeCounter].style = 9;
}
if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
{
pLinePoints[nSpikeCounter].style = 5;
}
nSpikeCounter++;
pLinePoints[nSpikeCounter] = new POINT2(UpperLinePoint);
if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) {
pLinePoints[nSpikeCounter].style = 9;
}
if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
{
pLinePoints[nSpikeCounter].style = 5;
}
nSpikeCounter++;
pLinePoints[nSpikeCounter] = new POINT2(Lower2LinePoint);
if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) {
pLinePoints[nSpikeCounter].style = 10;
}
if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
{
pLinePoints[nSpikeCounter].style = 5;
}
nSpikeCounter++;
if (linetype == TacticalLines.ATDITCHM) {
if (j % 2 == 0) {
averagePoint = lineutility.MidPointDouble(Lower1LinePoint, Lower2LinePoint, 0);
averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0);
} else if (j == 1) {
averagePoint = lineutility.ExtendLineDouble(Lower2LinePoint, Lower1LinePoint, 5);
averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0);
}
}
//end section
if (j > 1 && j < nNumberOfSegments) {
basePoints.add(new POINT2(Lower1LinePoint));
//if(j==nNumberOfSegments-1)
// basePoints.get(basePoints.size()-1).style=5;
} else if (j == 1) {
basePoints.add(new POINT2(pLinePoints[i]));
} else if (j == nNumberOfSegments) {
basePoints.add(new POINT2(pLinePoints[i + 1]));
basePoints.get(basePoints.size() - 1).style = 5;
}
if (linetype == TacticalLines.ATDITCHM && j > 1) {
if (j % 2 == 0) {
pCirclePoints[lCircleCounter] = lineutility.MidPointDouble(averagePoint, lastAveragePoint, 20);
lCircleCounter++;
}
//end section
}
if (j < nNumberOfSegments && linetype == TacticalLines.ATDITCHM) {
if (j == 1 || j % 2 == 0) {
//LastUpperLinePoint = new POINT2(UpperLinePoint);
lastAveragePoint = new POINT2(averagePoint);
}
//end section
}
}//end for j<numberOfsegments
} //end if length big enough
else {
//diagnostic
pLinePoints[nSpikeCounter].x = pLinePoints[i].x;
pLinePoints[nSpikeCounter].y = pLinePoints[i].y;
pLinePoints[nSpikeCounter].style = 0;
nSpikeCounter++;
pLinePoints[nSpikeCounter].x = pLinePoints[i + 1].x;
pLinePoints[nSpikeCounter].y = pLinePoints[i + 1].y;
pLinePoints[nSpikeCounter].style = 5;
nSpikeCounter++;
}
}
for (j = 0; j < nOldCounter; j++) //reverse the first nOldCounter points for
{
pLinePoints[j] = new POINT2(pTempLinePoints[nOldCounter - j - 1]); //purpose of drawing
pLinePoints[j].style = 5;
}
if (pLinePoints[nSpikeCounter - 1].style == 0) {
pLinePoints[nSpikeCounter - 1].style = 5;
}
int t=basePoints.size();
//for (j = nSpikeCounter; j < nSpikeCounter + basePoints.size(); j++)
for (j = nSpikeCounter; j < nSpikeCounter + t; j++)
{
pLinePoints[j] = new POINT2(basePoints.get(j - nSpikeCounter));
//if(linetype == TacticalLines.ATDITCHM && pLinePoints[j].style != 5)
if (pLinePoints[j].style != 5) {
pLinePoints[j].style = 0;
}
}
nSpikeCounter += basePoints.size();
if (linetype == (int) TacticalLines.ATDITCHM) {
pLinePoints[nSpikeCounter - 1].style = 5;//was 10
for (j = nSpikeCounter; j < nSpikeCounter + lCircleCounter; j++) {
pLinePoints[j] = new POINT2(pCirclePoints[j - nSpikeCounter]);
pLinePoints[j].style = 20;
}
nSpikeCounter += lCircleCounter;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "GetDitchSpikeDouble",
new RendererException("Failed inside GetDitchSpikeDouble", exc));
}
return nSpikeCounter;
}
/**
* Moves pixels if points are identical, used for the channel types
*
* @param pLinePoints OUT - client points also for returned points
*/
protected static void MoveChannelPixels(POINT2[] pLinePoints) {
try {
if (pLinePoints == null || pLinePoints.length <= 0) {
return;
}
double[] pixels = new double[pLinePoints.length * 2];
boolean bolNoRepeats;
int j, k = 0;
double x1;
double y1;
double x2;
double y2;
int count = pLinePoints.length;
//stuff pixels
for (j = 0; j < count; j++) {
pixels[k++] = pLinePoints[j].x;
pixels[k++] = pLinePoints[j].y;
}
bolNoRepeats = false;
do {
bolNoRepeats = true;
for (j = 0; j < count - 1; j++) {
x1 = pixels[2 * j];
y1 = pixels[2 * j + 1];
x2 = pixels[2 * j + 2];
y2 = pixels[2 * j + 3];
if (x1 == x2 && y1 == y2) //it's the same point
{
bolNoRepeats = false;
pixels[2 * j + 2] = (long) x2 + 1; //move the point
break;
}
}
} while (bolNoRepeats == false);
//stuff pLinePoints
k = 0;
for (j = 0; j < count; j++) {
pLinePoints[j].x = pixels[k++];
pLinePoints[j].y = pixels[k++];
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "MoveChannelPixels",
new RendererException("Failed inside MoveChannelPixels", exc));
}
}
/**
* Single Concertina cannot have horizontal first segment
*
* @param linetype
* @param pLinePoints
*/
protected static void moveSingleCPixels(int linetype, POINT2[] pLinePoints) {
try {
switch (linetype) {
case TacticalLines.SINGLEC:
break;
default:
return;
}
if (pLinePoints.length > 1) {
if (pLinePoints[1].y == pLinePoints[0].y) {
pLinePoints[1].y++;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "MoveSingleCPixels",
new RendererException("Failed inside MoveSingleCPixels", exc));
}
}
/**
* Rotates an the first vblCounter points in the array about its first point
*
* @param pLinePoints OUT - the points to rotate
* @param vblCounter the number of points to rotate
* @param lAngle the angle in degrees to rotate
*
* @return pLinePoints
*/
protected static void RotateGeometryDouble(POINT2[] pLinePoints,
int vblCounter,
double lAngle) {
try {
int j = 0;
double dRotate = 0,
dTheta = 0,
dGamma = 0,
x = 0,
y = 0;
if (lAngle != 0) //if the angle is 0 no rotation occurs
{
POINT2 pdCenter;
dRotate = lAngle * Math.PI / 180d;
pdCenter = CalcCenterPointDouble(pLinePoints, vblCounter);
for (j = 0; j < vblCounter; j++) {
//added if/else to get rid of divide by zero error 5/12/04 M. Deutch
if (pLinePoints[j].x == pdCenter.x) {
if ((pLinePoints[j].y > pdCenter.y)) {
dGamma = Math.PI + Math.PI / 2;
} else {
dGamma = Math.PI / 2;
}
} else {
dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y)
/ (pLinePoints[j].x - pdCenter.x));
}
if ((double) pLinePoints[j].x >= pdCenter.x) {
dGamma = dGamma + Math.PI;
}
dTheta = dRotate + dGamma;
y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta);
x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta);
pLinePoints[j].y = pdCenter.y + y;
pLinePoints[j].x = pdCenter.x + x;
} //end for
return;
} //end if
} catch (Exception exc) {
ErrorLogger.LogException(_className, "RotateGeometryDouble",
new RendererException("Failed inside RotateGeometryDouble", exc));
}
} // end
/**
* Returns the point perpendicular to the line (pt0 to pt1) at the midpoint
* the same distance from (and on the same side of) the the line as
* ptRelative.
*
* @param pt0 the first point
* @param pt1 the second point
* @param ptRelative the point to use for computing the return point
*
* @return the point perpendicular to the line at the midpoint
*/
protected static POINT2 PointRelativeToLine(POINT2 pt0,
POINT2 pt1,
POINT2 ptRelative) {
POINT2 ptResult = new POINT2(pt0);
try {
int bolVertical = 0;
ref<double[]> m = new ref();
POINT2 midPt = MidPointDouble(pt0, pt1, 0);
double b1 = 0, b2 = 0;
//end declarations
bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
if (bolVertical == 0) //line is vertical
{
ptResult.x = ptRelative.x;
ptResult.y = midPt.y;
}
if (bolVertical != 0 && m.value[0] == 0) {
ptResult.x = midPt.x;
ptResult.y = ptRelative.y;
}
if (bolVertical != 0 && m.value[0] != 0) {
b1 = midPt.y + (1 / m.value[0]) * midPt.x; //the line perp to midPt
b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2
ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "PointRelativeToLine",
new RendererException("Failed inside PointRelativeToLine", exc));
}
return ptResult;
}
/**
* shift the control point to match the shift that occurs in
* Channels.GetAXADDouble for CATKBYFIRE. This is because the rotary feature
* arrow tip must align with the anchor point
*
* @param linetype
* @param pLinePoints the anchor points including the control point
* @param minDist the minimum required distance from the front of the rotary
* arrow
*/
public static void adjustCATKBYFIREControlPoint(int linetype,
ArrayList<POINT2> pLinePoints,
double dist) {
try {
if (linetype != TacticalLines.CATKBYFIRE) {
return;
}
double dist2 = lineutility.CalcDistanceDouble(pLinePoints.get(0), pLinePoints.get(1));
if (dist2 <= dist) {
return;
}
POINT2 pt = null;
int count = pLinePoints.size();
POINT2 pt0 = new POINT2(pLinePoints.get(0));
POINT2 pt1 = new POINT2(pLinePoints.get(1));
POINT2 controlPt = new POINT2(pLinePoints.get(count - 1));
POINT2 pt4 = PointRelativeToLine(pt0, pt1, pt1, controlPt);
pt = lineutility.ExtendLineDouble(pt4, controlPt, dist);
pLinePoints.set(count - 1, pt);
} catch (Exception exc) {
ErrorLogger.LogException(_className, "adjustCATKBYFIREControlPoint",
new RendererException("Failed inside adjustCATKBYFIREControlPoint", exc));
}
}
/**
* Returns the point perpendicular to the line (pt0 to pt1) at atPoint the
* same distance from (and on the same side of) the the line as ptRelative.
*
* @param pt0 the first point
* @param pt1 the second point
* @param atPoint the point on the line at which to compute the extended
* point
* @param ptRelative the point to use for computing the return point
*
* @return the point perpendicular to the line at ptRelative
*/
public static POINT2 PointRelativeToLine(POINT2 pt0,
POINT2 pt1,
POINT2 atPoint,
POINT2 ptRelative) {
POINT2 ptResult = new POINT2(pt0);
try {
int bolVertical = 0;
ref<double[]> m = new ref();
double b1 = 0, b2 = 0;
bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
if (bolVertical == 0) //line is vertical
{
ptResult.x = ptRelative.x;
ptResult.y = atPoint.y;
}
if (bolVertical != 0 && m.value[0] == 0) {
ptResult.x = atPoint.x;
ptResult.y = ptRelative.y;
}
if (bolVertical != 0 && m.value[0] != 0) {
b1 = atPoint.y + (1 / m.value[0]) * atPoint.x; //the line perp to midPt
b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2
ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "PointRelativeToLine",
new RendererException("Failed inside PointRelativeToLine", exc));
}
return ptResult;
}
/**
* Returns in pt2 and pt3 the line segment parallel to segment pt0-pt1 which
* would contain ptRelative. pt2 corresponds to pt0 and pt3 corresponds to
* pt1.
*
* @param pt0 first line point
* @param pt1 second line point
* @param ptRelative relative line point
* @param pt2 OUT - first computed relative line point
* @param pt3 OUT - second computed relative line point
*/
public static void LineRelativeToLine(POINT2 pt0,
POINT2 pt1,
POINT2 ptRelative,
POINT2 pt2,
POINT2 pt3) {
try {
int bolVertical = 0;
ref<double[]> m = new ref();
double b1 = 0, b2 = 0;
POINT2 pt2Temp = null;
POINT2 pt3Temp = null;
bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
if (bolVertical == 0) //line is vertical
{
pt2.x = ptRelative.x;
pt2.y = pt0.y;
pt3.x = ptRelative.x;
pt3.y = pt1.y;
}
if (bolVertical != 0 && m.value[0] == 0) //line is horizontal
{
pt2.x = pt0.x;
pt2.y = ptRelative.y;
pt3.x = pt1.x;
pt3.y = ptRelative.y;
}
if (bolVertical != 0 && m.value[0] != 0) {
b1 = pt0.y + (1 / m.value[0]) * pt0.x; //the line perp to pt0
b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line the ptRelative with the slope of pt0-pt1
pt2Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
b1 = pt1.y + (1 / m.value[0]) * pt1.x; //the line perp to pt1
//b2=ptRelative.y-m*ptRelative.x; //the line the ptRelative with the slope of pt0-pt1
pt3Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
pt2.x = pt2Temp.x;
pt2.y = pt2Temp.y;
pt3.x = pt3Temp.x;
pt3.y = pt3Temp.y;
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "LineRelativeToLine",
new RendererException("Failed inside LineRelativeToLine", exc));
}
}
private static void CalcMBR(POINT2[] pLinePoints,
int numpts,
ref<double[]> ulx,
ref<double[]> uly,
ref<double[]> lrx,
ref<double[]> lry) {
try {
int j = 0;
//initialize the MBR
ulx.value = new double[1];
uly.value = new double[1];
lrx.value = new double[1];
lry.value = new double[1];
ulx.value[0] = Double.MAX_VALUE;//was 99999
uly.value[0] = Double.MAX_VALUE;//was 99999
lrx.value[0] = -Double.MAX_VALUE;//was -99999
lry.value[0] = -Double.MAX_VALUE;//was -99999
for (j = 0; j < numpts; j++) {
if (pLinePoints[j].x > lrx.value[0]) {
lrx.value[0] = pLinePoints[j].x;
}
if (pLinePoints[j].y > lry.value[0]) {
lry.value[0] = pLinePoints[j].y;
}
if (pLinePoints[j].x < ulx.value[0]) {
ulx.value[0] = pLinePoints[j].x;
}
if (pLinePoints[j].y < uly.value[0]) {
uly.value[0] = pLinePoints[j].y;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcMBR",
new RendererException("Failed inside CalcMBR", exc));
}
return;
}
public static void CalcMBRPoints(POINT2[] pLinePoints,
int numpts,
POINT2 ul,
POINT2 lr) {
try {
int j = 0;
ul.x = Double.MAX_VALUE;
ul.y = Double.MAX_VALUE;
lr.x = -Double.MAX_VALUE;
lr.y = -Double.MAX_VALUE;
for (j = 0; j < numpts; j++) {
if (pLinePoints[j].x > lr.x) {
lr.x = pLinePoints[j].x;
}
if (pLinePoints[j].y > lr.y) {
lr.y = pLinePoints[j].y;
}
if (pLinePoints[j].x < ul.x) {
ul.x = pLinePoints[j].x;
}
if (pLinePoints[j].y < ul.y) {
ul.y = pLinePoints[j].y;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "CalcMBRPoints",
new RendererException("Failed inside CalcMBRPoints", exc));
}
}
/**
* Computes the distance in pixels from upper left to lower right of the
* minimum bounding rectangle for the first numpts of pLinePoints
*
* @param pLinePoints the inpupt point array
* @param numpts the number of points to use
*
* @return the distance in pixels
*/
protected static double MBRDistance(POINT2[] pLinePoints,
int numpts) {
double result = 0;
try {
ref<double[]> ulx = new ref(), uly = new ref(), lrx = new ref(), lry = new ref();
CalcMBR(pLinePoints, numpts, ulx, uly, lrx, lry);
result = Math.sqrt((lrx.value[0] - ulx.value[0]) * (lrx.value[0] - ulx.value[0]) + (lry.value[0] - uly.value[0]) * (lry.value[0] - uly.value[0]));
//sanity check
//return x or y distance if returnValue is 0 or infinity
double xdist = Math.abs(lrx.value[0] - ulx.value[0]);
double ydist = Math.abs(lry.value[0] - uly.value[0]);
double max = xdist;
if (ydist > xdist) {
max = ydist;
}
if (result == 0 || Double.isInfinite(result)) {
if (max > 0) {
result = max;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "MBRDistance",
new RendererException("Failed inside MBRDistance", exc));
}
return result;
}
/**
* Swaps two points.
*
* @param pt1 OUT - first point
* @param pt2 OUT - second point
*
*/
protected static void Reverse2Points(POINT2 pt1, POINT2 pt2) {
try {
POINT2 tempPt = new POINT2();
//store pt1
tempPt.x = pt1.x;
tempPt.y = pt1.y;
pt1.x = pt2.x;
pt1.y = pt2.y;
pt2.x = tempPt.x;
pt2.y = tempPt.y;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "Reverse2Points",
new RendererException("Failed inside Reverse2Points", exc));
}
}
/**
* Creates a GeneralPath from a Path2D
*
* @param shape
* @return
*/
public static Shape createStrokedShape(Shape shape) {
GeneralPath newshape = new GeneralPath(); // Start with an empty shape
try {
// Iterate through the specified shape, perturb its coordinates, and
// use them to build up the new shape.
float[] coords = new float[6];
for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) {
int type = i.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
//perturb(coords, 2);
newshape.moveTo(coords[0], coords[1]);
break;
case PathIterator.SEG_LINETO:
//perturb(coords, 2);
newshape.lineTo(coords[0], coords[1]);
break;
case PathIterator.SEG_QUADTO:
//perturb(coords, 4);
newshape.quadTo(coords[0], coords[1], coords[2], coords[3]);
break;
case PathIterator.SEG_CUBICTO:
//perturb(coords, 6);
newshape.curveTo(coords[0], coords[1], coords[2], coords[3],
coords[4], coords[5]);
break;
case PathIterator.SEG_CLOSE:
newshape.closePath();
break;
}
}
} catch (Exception exc) {
ErrorLogger.LogException(_className, "createStrokedShape",
new RendererException("Failed inside createStrokedShape", exc));
}
return newshape;
}
//These functions were added to create a minimum bounding polygon
/**
* @deprecated Returns the determinant of the point matrix This determinant
* tells how far p3 is from vector p1p2 and on which side it is
* @param p1
* @param p2
* @param p3
* @return
*/
static private int distance(Point p1, Point p2, Point p3) {
try {
int x1 = p1.x;
int x2 = p2.x;
int x3 = p3.x;
int y1 = p1.y;
int y2 = p2.y;
int y3 = p3.y;
return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "distance",
new RendererException("Failed inside distance", exc));
}
return 0;
}
/**
* @deprecated Returns the determinant of the point matrix This determinant
* tells how far p3 is from vector p1p2 and on which side it is
* @param p1
* @param p2
* @param p3
* @return
*/
static private double distance2(POINT2 p1, POINT2 p2, POINT2 p3) {
try {
double x1 = p1.x;
double x2 = p2.x;
double x3 = p3.x;
double y1 = p1.y;
double y2 = p2.y;
double y3 = p3.y;
return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "distance2",
new RendererException("Failed inside distance2", exc));
}
return 0;
}
/**
* @deprecated @param points
* @param l
* @param r
* @param path
*/
static private void cHull(ArrayList<Point> points, Point l, Point r, ArrayList<Point> path) {
if (points.size() < 3) {
return;
}
int maxDist = 0;
int tmp;
Point p = null;
for (Point pt : points) {
if (pt != l && pt != r) {
tmp = distance(l, r, pt);
if (tmp > maxDist) {
maxDist = tmp;
p = pt;
}
}
}
ArrayList<Point> left = new ArrayList<Point>();
ArrayList<Point> right = new ArrayList<Point>();
left.add(l);
right.add(p);
for (Point pt : points) {
if (distance(l, p, pt) > 0) {
left.add(pt);
} else if (distance(p, r, pt) > 0) {
right.add(pt);
}
}
left.add(p);
right.add(r);
cHull(left, l, p, path);
path.add(p);
cHull(right, p, r, path);
}
/**
* @deprecated @param points
* @param l
* @param r
* @param path
*/
static private void cHull2(ArrayList<POINT2> points, POINT2 l, POINT2 r, ArrayList<POINT2> path) {
if (points.size() < 3) {
return;
}
double maxDist = 0;
double tmp;
POINT2 p = null;
for (POINT2 pt : points) {
if (pt != l && pt != r) {
tmp = distance2(l, r, pt);
if (tmp > maxDist) {
maxDist = tmp;
p = pt;
}
}
}
ArrayList<POINT2> left = new ArrayList<POINT2>();
ArrayList<POINT2> right = new ArrayList<POINT2>();
left.add(l);
right.add(p);
for (POINT2 pt : points) {
if (distance2(l, p, pt) > 0) {
left.add(pt);
} else if (distance2(p, r, pt) > 0) {
right.add(pt);
}
}
left.add(p);
right.add(r);
cHull2(left, l, p, path);
path.add(p);
cHull2(right, p, r, path);
}
//Returns the points of convex hull in the correct order
/**
* @deprecated @param array
* @return
*/
static public ArrayList<Point> cHull(ArrayList<Point> array) {
int size = array.size();
if (size < 2) {
return null;
}
Point l = array.get(0);
Point r = array.get(size - 1);
ArrayList<Point> path = new ArrayList<Point>();
path.add(l);
cHull(array, l, r, path);
path.add(r);
cHull(array, r, l, path);
return path;
}
/**
* @deprecated @param array
* @return
*/
static public ArrayList<POINT2> cHull2(ArrayList<POINT2> array) {
try {
int size = array.size();
if (size < 2) {
return null;
}
POINT2 l = array.get(0);
POINT2 r = array.get(size - 1);
ArrayList<POINT2> path = new ArrayList<POINT2>();
path.add(l);
cHull2(array, l, r, path);
path.add(r);
cHull2(array, r, l, path);
return path;
} catch (Exception exc) {
ErrorLogger.LogException(_className, "cHull2",
new RendererException("Failed inside cHull2", exc));
}
return null;
}
public static void getExteriorPoints(POINT2[] pLinePoints,
int vblCounter,
int lineType,
boolean interior
) {
int j;
int index;
POINT2 pt0, pt1, pt2;
ref<double[]> m01 = new ref(), m12 = new ref();
int direction;
POINT2 intersectPt;
//ref<double[]> m1 = new ref(), m2 = new ref();
ArrayList<POINT2> intersectPoints = new ArrayList();
double b01, b12; //the y intercepts for the lines corresponding to m1,m2
double dist = pLinePoints[0].style;
for (j = 0; j < vblCounter; j++) {
if (j == 0 || j == vblCounter - 1) {
pt0 = new POINT2(pLinePoints[vblCounter - 2]);
pt1 = new POINT2(pLinePoints[0]);
pt2 = new POINT2(pLinePoints[1]);
} else {
pt0 = new POINT2(pLinePoints[j - 1]);
pt1 = new POINT2(pLinePoints[j]);
pt2 = new POINT2(pLinePoints[j + 1]);
}
if (pt1.style > 0) {
dist = pt1.style;
}
//the exterior/interior points
POINT2 pt00, pt01, pt10, pt11;
index = j - 1;
if (index < 0) {
index = vblCounter - 1;
}
POINT2[] pts = new POINT2[pLinePoints.length];
int n=pLinePoints.length;
//for (int k = 0; k < pLinePoints.length; k++)
for (int k = 0; k < n; k++)
{
pts[k] = pLinePoints[k];
}
direction = arraysupport.GetInsideOutsideDouble2(pt0, pt1, pts, vblCounter, index, lineType);
//reverse the direction if these are interior points
if (interior == true) {
switch (direction) {
case 0:
direction = 1;
break;
case 1:
direction = 0;
break;
case 2:
direction = 3;
break;
case 3:
direction = 2;
break;
default:
break;
}
}
//pt00-pt01 will be the interior line inside line pt0-pt1
//pt00 is inside pt0, pt01 is inside pt1
pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, direction, dist);
pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, direction, dist);
//pt10-pt11 will be the interior line inside line pt1-pt2
//pt10 is inside pt1, pt11 is inside pt2
index = j;
if (j == vblCounter - 1) {
index = 0;
}
direction = arraysupport.GetInsideOutsideDouble2(pt1, pt2, (POINT2[]) pts, vblCounter, index, lineType);
//reverse the direction if these are interior points
if (interior == true) {
switch (direction) {
case 0:
direction = 1;
break;
case 1:
direction = 0;
break;
case 2:
direction = 3;
break;
case 3:
direction = 2;
break;
default:
break;
}
}
pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, direction, dist);
pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, direction, dist);
//intersectPt=new POINT2(null);
//get the intersection of pt01-p00 and pt10-pt11
//so it it is the interior intersection of pt0-pt1 and pt1-pt2
//first handle the case of vertical lines.
if (pt0.x == pt1.x && pt1.x == pt2.x) {
intersectPt = new POINT2(pt01);
intersectPoints.add(intersectPt);
continue;
}
//it's the same situation if the slopes are identical,
//simply use pt01 or pt10 since they already uniquely define the intesection
lineutility.CalcTrueSlopeDouble2(pt00, pt01, m01);
lineutility.CalcTrueSlopeDouble2(pt10, pt11, m12);
//if(m01.dbl==m12.dbl)
if (m01.value[0] == m12.value[0]) {
intersectPt = new POINT2(pt01);
intersectPoints.add(intersectPt);
continue;
}
//now we are assuming a non-trivial intersection
//calculate the y-intercepts using y=mx+b (use b=y-mx)
b01 = pt01.y - m01.value[0] * pt01.x;
b12 = pt11.y - m12.value[0] * pt11.x;
intersectPt = lineutility.CalcTrueIntersectDouble2(m01.value[0], b01, m12.value[0], b12, 1, 1, 0, 0);
intersectPoints.add(intersectPt);
}//end for
int n=intersectPoints.size();
//for (j = 0; j < intersectPoints.size(); j++)
for (j = 0; j < n; j++)
{
pLinePoints[j] = intersectPoints.get(j);
}
}
public static ArrayList<POINT2> getDeepCopy(ArrayList<POINT2>pts)
{
ArrayList<POINT2>deepCopy=null;
try
{
if(pts == null || pts.isEmpty())
return pts;
deepCopy=new ArrayList();
int j=0;
POINT2 pt=null;
for(j=0;j<pts.size();j++)
{
pt=new POINT2(pts.get(j).x,pts.get(j).y,pts.get(j).style);
deepCopy.add(pt);
}
}
catch (Exception exc) {
ErrorLogger.LogException(_className, "getDeepCopy",
new RendererException("Failed inside getDeepCopy", exc));
}
return deepCopy;
}
}//end lineutility