From 76f7bfb93f7727a25e14e501b4e3d48e4cf15685 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Mar 2014 20:52:20 +0200 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20TriangleClip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/annimon/graphics/Clip.java | 4 +- src/com/annimon/graphics/Point.java | 2 +- src/com/annimon/graphics/TriangleClip.java | 111 +++++++++++++++++++++ 3 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/com/annimon/graphics/TriangleClip.java diff --git a/src/com/annimon/graphics/Clip.java b/src/com/annimon/graphics/Clip.java index 534166c..25ba74f 100644 --- a/src/com/annimon/graphics/Clip.java +++ b/src/com/annimon/graphics/Clip.java @@ -27,7 +27,7 @@ public class Clip extends Rect { public double[] clip(double x1, double y1, double x2, double y2) { int c1 = getClipCode(x1, y1); int c2 = getClipCode(x2, y2); - while (c1 != 0 || (c2 != 0)) { + while (c1 != 0 || c2 != 0) { if (c1 == 0 && c2 == 0) { return new double[] { x1, y1, x2, y2 }; } @@ -66,7 +66,7 @@ public class Clip extends Rect { } } return new double[] { x1, y1, x2, y2 }; - } + } public int getClipCode(double x, double y) { int xmin = (x < super.x) ? 1 : 0; diff --git a/src/com/annimon/graphics/Point.java b/src/com/annimon/graphics/Point.java index 7c2c83b..841f656 100644 --- a/src/com/annimon/graphics/Point.java +++ b/src/com/annimon/graphics/Point.java @@ -6,7 +6,7 @@ package com.annimon.graphics; */ public class Point { - private double x, y; + public double x, y; public Point() { x = y = 0; diff --git a/src/com/annimon/graphics/TriangleClip.java b/src/com/annimon/graphics/TriangleClip.java new file mode 100644 index 0000000..43b6b88 --- /dev/null +++ b/src/com/annimon/graphics/TriangleClip.java @@ -0,0 +1,111 @@ +package com.annimon.graphics; + +/** + * + * @author aNNiMON + */ +public class TriangleClip extends Clip { + + private Polygon poly; + + public TriangleClip(Point[] points) { + super(0, 0, 0, 0); + poly = new Polygon(points); + } + + @Override + public double[] clip(double x1, double y1, double x2, double y2) { + return clipCyrusBeck(new Point(x1, y1), new Point(x2, y2), calcNormals(poly, poly.v)); + } + + private Point[] calcNormals(Polygon p, Point[] n) { + Point v = new Point(); + for (int i = 0; i < p.nPoints; i++) { + int j = (i+1) % p.nPoints; + int k = (i+2) % p.nPoints; + // make vector be -1/mI + 1J + n[i].setX( -(p.v[j].getY() - p.v[i].getY()) / (p.v[j].getX() - p.v[i].getX()) ); + n[i].setY(1.0); + + v.setX( p.v[k].getX() - p.v[i].getX() ); + v.setY( p.v[k].getY() - p.v[i].getY() ); + if (pointProduction(n[i], v) > 0) { + // inner normal + n[i].setX(n[i].getX() * -1); + n[i].setY(n[i].getY() * -1); + } + } + return n; + } + + private double pointProduction(Point v1, Point v2) { + return v1.getX() * v2.getX() + v1.getY() * v2.getY(); + } + + private double[] clipCyrusBeck(Point p1, Point p2, Point[] n) { + double t,num,den; + // vectors + Point dirV = new Point(); + Point F = new Point(); + + // start largest at smallest legal value and smallest + // at largest legal value + double t1 = 0.0; + double t2 = 1.0; + // compute the direction vector + dirV.x = p2.x - p1.x; + dirV.y = p2.y - p1.y; + + boolean visible = true; + int i = 0; + while ((i < poly.nPoints) && visible) { + F.x = p1.x - poly.v[i].x; + F.y = p1.y - poly.v[i].y; + + num = pointProduction(n[i], F); + den = pointProduction(n[i], dirV); + + // Parallel or Point + if (den == 0.0) { +// parallel - if outside then forget the line; if inside then there are no + // intersections with this side + // but there may be with other edges, so in this case just keep going + if (num > 0.0) { + // Parallel and outside or point (p1 == p2) and outside + visible = false; + } + } else { + t = -(num/den); + if (den < 0.0) { + // entering + if (t <= 1.0 && t > t1) t1 = t; + } else if ( t >= 0.0 && t < t2) t2 = t; + } + i++; + } + /*if (t1 <= t2) { + return new double[] { + p1.x + t1*dirV.x, + p1.y + t1*dirV.y, + p1.x + t2*dirV.x, + p1.y + t2*dirV.y + }; + } else visible = false;*/ + return new double[] { + p1.x + t1*dirV.x, + p1.y + t1*dirV.y, + p1.x + t2*dirV.x, + p1.y + t2*dirV.y + }; + } + + private class Polygon { + int nPoints; + Point[] v; + + public Polygon(Point[] points) { + this.v = points; + nPoints = points.length; + } + } +}