Calculating the intersection Point2D(s) of two curves

Hi All

Does anyone know a good way of calculating the intersection points of two curves? i.e. so you can do this with e.g. a QuadCurve2D and another QuadCurve2D, or a QuadCurve2D and a CubicCurve2D or a straight line?

I suppose I could just Stroke the two curves, get the intersection area then join the four corners to find the middle, but surely there must be a more elegant way! In fact, I'm not sure if the Stroking would even yield an accurate result...

Cheers,

Brian G.

[507 byte] By [d1zzya] at [2007-11-26 15:45:44]
# 1

Adjust the flatness parameter to control accuracy.

import java.awt.*;

import java.awt.event.MouseEvent;

import java.awt.geom.*;

import java.awt.image.BufferedImage;

import javax.swing.*;

import javax.swing.event.MouseInputAdapter;

public class Searching extends JPanel {

QuadCurve2D.Double quad;

CubicCurve2D.Double cubic;

QuadCurve2D.Double liveQuad;

Point2D.Double[]points;

Point2D.Double[]p;

public void setPoint(int index, double x, double y) {

points[index].setLocation(x, y);

liveQuad.setCurve(points, 0);

setIntersects();

repaint();

}

protected void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

if(quad == null)

initGeoms();

g2.setPaint(Color.blue);

g2.draw(quad);

g2.draw(cubic);

g2.draw(liveQuad);

for(int j = 0; j < points.length; j++) {

Color color = (j%2 == 0) ? Color.red : Color.green.darker();

g2.setPaint(color);

g2.fill(new Ellipse2D.Double(points[j].x-2, points[j].y-2, 4, 4));

}

// Mark intersection points.

g2.setPaint(Color.magenta);

for(int j = 0; j < p.length; j++) {

g2.draw(new Line2D.Double(p[j].x, p[j].y-20, p[j].x, p[j].y+20));

g2.draw(new Line2D.Double(p[j].x-20, p[j].y, p[j].x+20, p[j].y));

}

}

private void setIntersects() {

p[0] = getIntersectionPoint(quad, liveQuad);

p[1] = getIntersectionPoint(cubic, liveQuad);

}

private Point2D.Double getIntersectionPoint(Shape s1, Shape s2) {

Point2D.Double closest = new Point2D.Double();

double min = Double.MAX_VALUE;

double flatness = 0.005;

PathIterator pit = s1.getPathIterator(null, flatness);

double[] coords = new double[6];

while(!pit.isDone()) {

int type = pit.currentSegment(coords);

Point2D.Double p = getClosestPoint(s2, coords[0], coords[1]);

double distance = p.distance(coords[0], coords[1]);

if(distance < min) {

min = distance;

closest.setLocation(coords[0], coords[1]);

}

pit.next();

}

return closest;

}

private Point2D.Double getClosestPoint(Shape s, double x, double y) {

Point2D.Double closest = new Point2D.Double();

double min = Double.MAX_VALUE;

double flatness = 0.005;

PathIterator pit = s.getPathIterator(null, flatness);

double[] coords = new double[6];

while(!pit.isDone()) {

int type = pit.currentSegment(coords);

double distance = Point2D.distance(x, y, coords[0], coords[1]);

if(distance < min) {

min = distance;

closest.setLocation(coords[0], coords[1]);

}

pit.next();

}

return closest;

}

private void initGeoms() {

int w = getWidth();

int h = getHeight();

double x1 = w/8;

double y1 = h/16;

double ctrlx1 = w*15/16;

double ctrly1 = h/3;

double x2 = w*3/4;

double y2 = h*7/8;

quad = new QuadCurve2D.Double(x1, y1, ctrlx1, ctrly1, x2, y2);

x1 = w/16;

y1 = h/8;

ctrlx1 = 0;

ctrly1 = h*2/3;

double ctrlx2 = w*2/3;

double ctrly2 = h*3/4;

x2 = w/2;

y2 = h*15/16;

cubic = new CubicCurve2D.Double(x1, y1, ctrlx1, ctrly1,

ctrlx2, ctrly2, x2, y2);

points = new Point2D.Double[3];

points[0] = new Point2D.Double(w/16, h*11/12);

points[1] = new Point2D.Double(w/2, h/4);

points[2] = new Point2D.Double(w*11/12, h/3);

liveQuad = new QuadCurve2D.Double();

liveQuad.setCurve(points, 0);

p = new Point2D.Double[] { new Point2D.Double(), new Point2D.Double() };

setIntersects();

}

public Dimension getPreferredSize() {

return new Dimension(400,400);

}

public static void main(String[] args) {

Searching test = new Searching();

ArcTester arcTester = new ArcTester(test);

test.addMouseListener(arcTester);

test.addMouseMotionListener(arcTester);

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(test);

f.pack();

f.setLocationRelativeTo(null);

f.setVisible(true);

}

}

class ArcTester extends MouseInputAdapter {

Searching component;

Cursor hitCursor;

Point2D.Double offset = new Point2D.Double();

int selectedIndex = -1;

boolean dragging = false;

final int PROXIMITY = 5;

public ArcTester(Searching s) {

component = s;

createCursor();

}

public void mousePressed(MouseEvent e) {

Point p = e.getPoint();

if(selectedIndex != -1) {

Point2D.Double[] points = component.points;

offset.x = p.x - points[selectedIndex].x;

offset.y = p.y - points[selectedIndex].y;

dragging = true;

}

}

public void mouseReleased(MouseEvent e) {

dragging = false;

}

public void mouseDragged(MouseEvent e) {

if(dragging) {

double x = e.getX() - offset.x;

double y = e.getY() - offset.y;

component.setPoint(selectedIndex, x, y);

}

}

public void mouseMoved(MouseEvent e) {

Point p = e.getPoint();

Point2D.Double[] points = component.points;

if(points == null) return;

boolean hovering = false;

for(int j = 0; j < points.length; j++) {

if(p.distance(points[j]) <= PROXIMITY) {

if(selectedIndex != j) {

selectedIndex = j;

component.setCursor(hitCursor);

}

hovering = true;

break;

}

}

if(!hovering && selectedIndex != -1) {

selectedIndex = -1;

component.setCursor(Cursor.getDefaultCursor());

}

}

private void createCursor() {

BufferedImage image = getImage();

Point hotSpot = new Point(image.getWidth()/2+3, image.getHeight()/2+3);

hitCursor = Toolkit.getDefaultToolkit()

.createCustomCursor(image, hotSpot, "hitCursor");

}

private BufferedImage getImage() {

int w = 27;

int h = 27;

int type = BufferedImage.TYPE_INT_ARGB_PRE;

BufferedImage image = new BufferedImage(w, h, type);

Graphics2D g2 = image.createGraphics();

g2.setPaint(Color.black);

g2.draw(new Line2D.Double(w/2, 0, w/2, 10));

g2.draw(new Line2D.Double(w-10, h/2, w, h/2));

g2.draw(new Line2D.Double(w/2, h-10, w/2, h));

g2.draw(new Line2D.Double(0, h/2, 10, h/2));

g2.dispose();

return image;

}

}

crwooda at 2007-7-8 22:04:58 > top of Java-index,Security,Cryptography...