From c6878853e53e283a95216f8c1f586f9a9737f6fe Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Tue, 25 Jun 2002 00:22:44 +0000 Subject: [PATCH] Fun with geometry. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1535 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- src/java/com/threerings/geom/GeomUtil.java | 53 ++++++++++++ .../java/com/threerings/geom/NearestViz.java | 80 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/java/com/threerings/geom/GeomUtil.java create mode 100644 tests/src/java/com/threerings/geom/NearestViz.java diff --git a/src/java/com/threerings/geom/GeomUtil.java b/src/java/com/threerings/geom/GeomUtil.java new file mode 100644 index 000000000..989436cdf --- /dev/null +++ b/src/java/com/threerings/geom/GeomUtil.java @@ -0,0 +1,53 @@ +// +// $Id: GeomUtil.java,v 1.1 2002/06/25 00:22:44 mdb Exp $ + +package com.threerings.geom; + +import java.awt.Point; + +/** + * General geometry utilites. + */ +public class GeomUtil +{ + /** + * Computes and returns the dot product of the two vectors. + * + * @param v1s the starting point of the first vector. + * @param v1e the ending point of the first vector. + * @param v2s the starting point of the second vector. + * @param v2e the ending point of the second vector. + */ + public static int dot (Point v1s, Point v1e, Point v2s, Point v2e) + { + return ((v1e.x - v1s.x) * (v2e.x - v2s.x) + + (v1e.y - v1s.y) * (v2e.y - v2s.y)); + } + + /** + * Computes the point nearest to the specified point p3 + * on the line defined by the two points p1 and + * p2. The computed point is stored into n. + * Note: p1 and p2 must not be + * coincident. + * + * @param p1 one point on the line. + * @param p2 another point on the line (not equal to p1). + * @param p3 the point to which we wish to be most near. + * @param n the point on the line defined by p1 and + * p2 that is nearest to p. + * + * @return the point object supplied via n. + */ + public static Point nearestToLine (Point p1, Point p2, Point p3, Point n) + { + // see http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ + // for a (not very good) explanation of the math + int Ax = p2.x - p1.x, Ay = p2.y - p1.y; + float u = (p3.x - p1.x) * Ax + (p3.y - p1.y) * Ay; + u /= (Ax * Ax + Ay * Ay); + n.x = p1.x + Math.round(Ax * u); + n.y = p1.y + Math.round(Ay * u); + return n; + } +} diff --git a/tests/src/java/com/threerings/geom/NearestViz.java b/tests/src/java/com/threerings/geom/NearestViz.java new file mode 100644 index 000000000..725bd16ba --- /dev/null +++ b/tests/src/java/com/threerings/geom/NearestViz.java @@ -0,0 +1,80 @@ +// +// $Id: NearestViz.java,v 1.1 2002/06/25 00:22:44 mdb Exp $ + +package com.threerings.geom; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +/** + * Renders the nearest point on a line just for kicks. + */ +public class NearestViz extends JPanel + implements MouseMotionListener +{ + public NearestViz () + { + addMouseMotionListener(this); + } + + public void doLayout () + { + super.doLayout(); + _center = new Point(getWidth() / 2, getHeight() / 2); + } + + public void paintComponent (Graphics g) + { + super.paintComponent(g); + + int dx = (int)Math.round(Math.cos(_theta) * 200); + int dy = (int)Math.round(Math.sin(_theta) * 200); + + g.setColor(Color.blue); + g.drawLine(_center.x, _center.y, _center.x + dx, _center.y - dy); + g.drawLine(_center.x, _center.y, _center.x - dx, _center.y + dy); + + // locate the point nearest the spot + Point p2 = new Point(_center.x + dx, _center.y - dy); + Point n = new Point(); + GeomUtil.nearestToLine(_center, p2, _spot, n); + + g.setColor(Color.red); + g.drawOval(n.x - 4, n.y - 4, 8, 8); + + // kick theta along for the next tick because it's fun + _theta += (float)(Math.PI/100); + } + + public void mouseDragged (MouseEvent event) + { + } + + public void mouseMoved (MouseEvent event) + { + _spot.x = event.getX(); + _spot.y = event.getY(); + repaint(); + } + + public static void main (String[] args) + { + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(new NearestViz(), BorderLayout.CENTER); + frame.setSize(300, 300); + frame.show(); + } + + protected float _theta = (float)(3 * Math.PI / 5); + protected Point _center; + protected Point _spot = new Point(); +}