trackeditor: show elevation at cursor position

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@9300 30fe4595-0a0c-4342-8851-515496e4dcbd
This commit is contained in:
iobyte 2024-02-02 00:21:58 +00:00
parent 0ddf3071db
commit 99b4b78eb0
3 changed files with 202 additions and 2 deletions

View File

@ -305,6 +305,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
/** input events management */
public void mouseClicked(MouseEvent e)
{
if (editorFrame.getTrackData() == null)
return;
if (e.getButton() == MouseEvent.BUTTON1)
{
screenToReal(e, clickPoint);
@ -716,6 +719,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
/** input events management */
public void mousePressed(MouseEvent e)
{
if (editorFrame.getTrackData() == null)
return;
if (e.getButton() == MouseEvent.BUTTON3)
{
Segment obj = findObjAtMousePos();
@ -925,6 +931,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
/** input events management */
public void mouseReleased(MouseEvent e)
{
if (editorFrame.getTrackData() == null)
return;
if (e.getButton() == MouseEvent.BUTTON1)
{
switch (currentState)
@ -987,6 +996,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
/** input events management */
public void mouseDragged(MouseEvent e)
{
if (editorFrame.getTrackData() == null)
return;
if (e.getModifiers() == 4)
{
if (objectShape != null && objectDragging == true)
@ -1079,6 +1091,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
/** input events management */
public void mouseMoved(MouseEvent e)
{
if (editorFrame.getTrackData() == null)
return;
screenToReal(e, mousePoint);
if (editorFrame.getCursorCoordinates())
@ -1194,6 +1209,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
public void mouseWheelMoved(MouseWheelEvent e)
{
if (editorFrame.getTrackData() == null)
return;
screenToReal(e, mousePoint);
getParent().dispatchEvent(e);
@ -1668,6 +1686,9 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
*/
public void paint(Graphics g)
{
if (editorFrame.getTrackData() == null)
return;
graphics = g;
// visible part of screen in pixels
@ -1677,7 +1698,37 @@ public class CircuitView extends JComponent implements KeyListener, MouseListene
{
if (editorFrame.getTrackData() != null)
{
String coordinates = String.format("x: %.3f y: %.3f", + mousePoint.x, + mousePoint.y);
String coordinates = null;
// must check for a object under the mouse
Segment obj = findObjAtMousePos();
if (obj != null)
{
if (obj.getType().equals("rgt") ||
obj.getType().equals("lft") ||
obj.getType().equals("str"))
{
double height = obj.getHeightAt(editorFrame, mousePoint.x, mousePoint.y);
coordinates = String.format("x: %.3f y: %.3f z: %.3f", mousePoint.x, mousePoint.y, height);
/*
MutableDouble height = new MutableDouble();
MutableDouble slopeLeft = new MutableDouble();
MutableDouble slopeRight = new MutableDouble();
if (obj.getHeightAndSlopeAt(editorFrame, mousePoint.x, mousePoint.y, height, slopeLeft, slopeRight))
{
double slope = (slopeLeft.getValue() + slopeRight.getValue()) / 2.0;
coordinates = String.format("x: %.3f y: %.3f z: %.3f slope: %.3f", mousePoint.x, mousePoint.y, height.getValue(), slope);
}
*/
}
}
if (coordinates == null)
{
coordinates = String.format("x: %.3f y: %.3f", mousePoint.x, mousePoint.y);
}
graphics.drawString(coordinates, r.x + 10, r.y + 20);
}

View File

@ -34,7 +34,7 @@ public class Properties
private static Properties instance = new Properties();
private Vector<ActionListener> propertiesListeners = new Vector<ActionListener>();
public final String title = "sd2-trackeditor";
public final String version = "1.4.27";
public final String version = "1.4.28";
private String path;
private double imageScale = 1;

View File

@ -30,6 +30,8 @@ import java.util.Arrays;
import java.util.Vector;
import gui.EditorFrame;
import utils.Editor;
import utils.MutableDouble;
/**
* @author Patrice Espie , Charalampos Alexopoulos
@ -2260,6 +2262,153 @@ public class Segment implements Cloneable
right.setSideBankingType(getValidRightSideBankingType(editorFrame));
}
public double getGradeAt(EditorFrame editorFrame, double splitPoint)
{
int splitStep = (int) (splitPoint * nbSteps);
int splitSubSeg = 4 * (7 + (Editor.getProperties().getShowArrows() > 0.0 ? 1 : 0)) * splitStep;
double startZ = (points[splitSubSeg].z + points[splitSubSeg + 3].z) / 2;
double endZ = (points[splitSubSeg + 1].z + points[splitSubSeg + 2].z) / 2;
return ((endZ - startZ) / stepLength) * 100;
}
public double getGradeAtLeft(EditorFrame editorFrame, double splitPoint)
{
int splitStep = (int) (splitPoint * nbSteps);
int splitSubSeg = 4 * (7 + (Editor.getProperties().getShowArrows() > 0.0 ? 1 : 0)) * splitStep;
double startZ = points[splitSubSeg].z;
double endZ = points[splitSubSeg + 1].z;
return ((endZ - startZ) / stepLength) * 100;
}
public double getGradeAtRight(EditorFrame editorFrame, double splitPoint)
{
int splitStep = (int) (splitPoint * nbSteps);
int splitSubSeg = 4 * (7 + (Editor.getProperties().getShowArrows() > 0.0 ? 1 : 0)) * splitStep;
double startZ = points[splitSubSeg + 3].z;
double endZ = points[splitSubSeg + 2].z;
return ((endZ - startZ) / stepLength) * 100;
}
// from https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
private static final double EPSILON = 0.0000001;
public static boolean rayIntersectsTriangle(Point3D rayOrigin,
Point3D rayVector,
Point3D vertex0,
Point3D vertex1,
Point3D vertex2,
Point3D outIntersectionPoint)
{
Point3D edge1 = new Point3D();
Point3D edge2 = new Point3D();
Point3D h = new Point3D();
Point3D s = new Point3D();
Point3D q = new Point3D();
double a, f, u, v;
edge1.sub(vertex1, vertex0);
edge2.sub(vertex2, vertex0);
h.cross(rayVector, edge2);
a = edge1.dot(h);
if (a > -EPSILON && a < EPSILON)
{
return false; // This ray is parallel to this triangle.
}
f = 1.0 / a;
s.sub(rayOrigin, vertex0);
u = f * (s.dot(h));
if (u < 0.0 || u > 1.0)
{
return false;
}
q.cross(s, edge1);
v = f * rayVector.dot(q);
if (v < 0.0 || u + v > 1.0)
{
return false;
}
// At this stage we can compute t to find out where the intersection point is on the line.
double t = f * edge2.dot(q);
if (t > EPSILON) // ray intersection
{
outIntersectionPoint.set(0.0, 0.0, 0.0);
outIntersectionPoint.scaleAdd(t, rayVector, rayOrigin);
return true;
}
else // This means that there is a line intersection but not a ray intersection.
{
return false;
}
}
public double getHeightAt(EditorFrame editorFrame, double x, double y)
{
if (points == null)
return 0.0;
Point3D rayOrigin = new Point3D(x, y, -1000.0);
Point3D rayVector = new Point3D(0.0, 0.0, 1.0);
Point3D intersectionPoint = new Point3D();
int stride = 4 * (7 + (Editor.getProperties().getShowArrows() > 0.0 ? 1 : 0));
for (int i = 0; i < points.length; i += stride)
{
if (rayIntersectsTriangle(rayOrigin, rayVector, points[i + 0], points[i + 1], points[i + 2], intersectionPoint))
{
return intersectionPoint.z;
}
if (rayIntersectsTriangle(rayOrigin, rayVector, points[i + 0], points[i + 2], points[i + 3], intersectionPoint))
{
return intersectionPoint.z;
}
}
return 0.0;
}
public boolean getHeightAndSlopeAt(EditorFrame editorFrame, double x, double y, MutableDouble height, MutableDouble slopeLeft, MutableDouble slopeRight)
{
if (points == null)
return false;
Point3D rayOrigin = new Point3D(x, y, -1000.0);
Point3D rayVector = new Point3D(0.0, 0.0, 1.0);
Point3D intersectionPoint = new Point3D();
int stride = 4 * (7 + (Editor.getProperties().getShowArrows() > 0.0 ? 1 : 0));
for (int i = 0; i < points.length; i += stride)
{
if (rayIntersectsTriangle(rayOrigin, rayVector, points[i + 0], points[i + 1], points[i + 2], intersectionPoint))
{
height.setValue(intersectionPoint.z);
double at = (((i / stride) * stepLength) + (stepLength / 2)) / length;
slopeLeft.setValue(getGradeAtLeft(editorFrame, at));
slopeRight.setValue(getGradeAtRight(editorFrame, at));
return true;
}
if (rayIntersectsTriangle(rayOrigin, rayVector, points[i + 0], points[i + 2], points[i + 3], intersectionPoint))
{
height.setValue(intersectionPoint.z);
double at = (((i / stride) * stepLength) + (stepLength / 2)) / length;
slopeLeft.setValue(getGradeAtLeft(editorFrame, at));
slopeRight.setValue(getGradeAtRight(editorFrame, at));
return true;
}
}
return false;
}
public void dump(String indent)
{
dump(indent, true, true, true, true);