/* * Copyright (c) 2010, Frederik Vanhoutte This library is free software; you can * redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. * http://creativecommons.org/licenses/LGPL/2.1/ This library is distributed in * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. You should have * received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA */ package wblut.geom; import java.util.ArrayList; import wblut.WB_Epsilon; import wblut.math.WB_Fast; // TODO: Auto-generated Javadoc /** * 2D circle. */ public class WB_Circle { /** Center. */ private WB_Point2d _center; /** Radius. */ private double _radius; /** * Instantiates a new WB_Circle. */ public WB_Circle() { _center = new WB_Point2d(); _radius = 0; } /** * Center. * * @return center */ public WB_Point2d getCenter() { return _center; } /** * Sets center. * * @param center new center */ public void setCenter(final WB_Point2d center) { _center = center; } /** * Sets the. * * @param c the c */ public void set(final WB_Circle c) { _center = c.getCenter(); _radius = c.getRadius(); } /** * Sets center. * * @param x new center * @param y new center */ public void setCenter(final double x, final double y) { _center.set(x, y); } /** * Returns radius. * * @return radius */ public double getRadius() { return _radius; } /** * Sets radius. * * @param radius new radius */ public void setRadius(final double radius) { _radius = radius; } /** * Instantiates a new WB_Circle. * * @param c center * @param r radius */ public WB_Circle(final WB_Point2d c, final double r) { _center = c; _radius = r; } /** * Instantiates a new WB_Circle. * * @param x x-coordinate of center * @param y y-coordinate of center * @param r radius */ public WB_Circle(final double x, final double y, final double r) { _center = new WB_Point2d(x, y); _radius = r; } /** * Gets the circle through3 points. * * @param p0 the p0 * @param p1 the p1 * @param p2 the p2 * @return the circle through3 points */ public static WB_Circle getCircleThrough3Points(final WB_Point2d p0, final WB_Point2d p1, final WB_Point2d p2) { final WB_ExplicitTriangle2D T = new WB_ExplicitTriangle2D(p0, p1, p2); return T.getCircumcircle(); } /** * Gets the circle tangent to3 lines. * * @param L0 the l0 * @param L1 the l1 * @param L2 the l2 * @return the circle tangent to3 lines */ public static WB_Circle getCircleTangentTo3Lines(final WB_Line2D L0, final WB_Line2D L1, final WB_Line2D L2) { final WB_Point2d p0 = (WB_Point2d) WB_Intersection2D.closestPoint2D(L0, L1).object; final WB_Point2d p1 = (WB_Point2d) WB_Intersection2D.closestPoint2D(L1, L2).object; final WB_Point2d p2 = (WB_Point2d) WB_Intersection2D.closestPoint2D(L0, L2).object; final WB_ExplicitTriangle2D T = new WB_ExplicitTriangle2D(p0, p1, p2); return T.getIncircle(); } /** * Gets the circle through2 points. * * @param p0 the p0 * @param p1 the p1 * @param r the r * @return the circle through2 points */ public static ArrayList<WB_Circle> getCircleThrough2Points( final WB_Point2d p0, final WB_Point2d p1, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(); final WB_Circle C0 = new WB_Circle(p0, r); final WB_Circle C1 = new WB_Circle(p1, r); final ArrayList<WB_Point2d> intersection = WB_Intersection2D .intersect2D(C0, C1); for (int i = 0; i < intersection.size(); i++) { result.add(new WB_Circle(intersection.get(i), r)); } return result; } /** * Gets the circle tangent to line through point. * * @param L the l * @param p the p * @param r the r * @return the circle tangent to line through point */ public static ArrayList<WB_Circle> getCircleTangentToLineThroughPoint( final WB_Line2D L, final WB_Point2d p, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(); double cPrime = L.c() + L.a() * p.x + L.b() * p.y; if (WB_Epsilon.isZero(cPrime)) { result.add(new WB_Circle(p.addAndCopy(L.a(), L.b(), r), r)); result.add(new WB_Circle(p.addAndCopy(L.a(), L.b(), -r), r)); return result; } double a, b; if (cPrime < 0) { a = -L.a(); b = -L.b(); cPrime *= -1; } else { a = L.a(); b = L.b(); } final double tmp1 = cPrime - r; double tmp2 = r * r - tmp1 * tmp1; if (WB_Epsilon.isZero(tmp2)) { result.add(new WB_Circle(p.addAndCopy(a, b, -tmp1), r)); return result; } else if (tmp2 < 0) { return result; } else { tmp2 = Math.sqrt(tmp2); final WB_Point2d tmpp = new WB_Point2d(p.x - a * tmp1, p.y - b * tmp1); result.add(new WB_Circle(tmpp.addAndCopy(b, -a, tmp2), r)); result.add(new WB_Circle(tmpp.addAndCopy(-b, a, tmp2), r)); return result; } } /** * Gets the circle tangent to2 lines. * * @param L0 the l0 * @param L1 the l1 * @param r the r * @return the circle tangent to2 lines */ public static ArrayList<WB_Circle> getCircleTangentTo2Lines( final WB_Line2D L0, final WB_Line2D L1, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(4); final double discrm0 = r;// Math.sqrt(L0.a() * L0.a() + L0.b() * L0.b()) // * r; final double discrm1 = r;// Math.sqrt(L1.a() * L1.a() + L1.b() * L1.b()) // * r; final double invDenom = 1.0 / (-L1.a() * L0.b() + L0.a() * L1.b()); double cx = -(L1.b() * (L0.c() + discrm0) - L0.b() * (L1.c() + discrm1)) * invDenom; double cy = +(L1.a() * (L0.c() + discrm0) - L0.a() * (L1.c() + discrm1)) * invDenom; result.add(new WB_Circle(new WB_Point2d(cx, cy), r)); cx = -(L1.b() * (L0.c() + discrm0) - L0.b() * (L1.c() - discrm1)) * invDenom; cy = +(L1.a() * (L0.c() + discrm0) - L0.a() * (L1.c() - discrm1)) * invDenom; result.add(new WB_Circle(new WB_Point2d(cx, cy), r)); cx = -(L1.b() * (L0.c() - discrm0) - L0.b() * (L1.c() + discrm1)) * invDenom; cy = +(L1.a() * (L0.c() - discrm0) - L0.a() * (L1.c() + discrm1)) * invDenom; result.add(new WB_Circle(new WB_Point2d(cx, cy), r)); cx = -(L1.b() * (L0.c() - discrm0) - L0.b() * (L1.c() - discrm1)) * invDenom; cy = +(L1.a() * (L0.c() - discrm0) - L0.a() * (L1.c() - discrm1)) * invDenom; result.add(new WB_Circle(new WB_Point2d(cx, cy), r)); return result; } /** * Gets the circle through point tangent to circle. * * @param p the p * @param C the c * @param r the r * @return the circle through point tangent to circle */ public static ArrayList<WB_Circle> getCircleThroughPointTangentToCircle( final WB_Point2d p, final WB_Circle C, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(4); final double dcp = WB_Distance2D.distance(p, C.getCenter()); if (dcp > C.getRadius() + 2 * r) { return result; } else if (dcp < C.getRadius() - 2 * r) { return result; } else { final WB_Circle ctmp1 = new WB_Circle(p, r); WB_Circle ctmp2 = new WB_Circle(C.getCenter(), r + C.getRadius()); ArrayList<WB_Point2d> intersection = WB_Intersection2D.intersect2D( ctmp1, ctmp2); for (int i = 0; i < intersection.size(); i++) { result.add(new WB_Circle(intersection.get(i), r)); } ctmp2 = new WB_Circle(C.getCenter(), WB_Fast.abs(r - C.getRadius())); intersection = WB_Intersection2D.intersect2D(ctmp1, ctmp2); for (int i = 0; i < intersection.size(); i++) { result.add(new WB_Circle(intersection.get(i), r)); } } return result; } /** * Gets the circle tangent to line and circle. * * @param L the l * @param C the c * @param r the r * @return the circle tangent to line and circle */ public static ArrayList<WB_Circle> getCircleTangentToLineAndCircle( final WB_Line2D L, final WB_Circle C, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(8); final double d = WB_Distance2D.distance(C.getCenter(), L); if (d > 2 * r + C.getRadius()) { return result; } final WB_Line2D L1 = new WB_Line2D(L.getOrigin().addAndCopy( L.getDirection().y, -L.getDirection().x, r), L.getDirection()); final WB_Line2D L2 = new WB_Line2D(L.getOrigin().addAndCopy( -L.getDirection().y, +L.getDirection().x, r), L.getDirection()); final WB_Circle C1 = new WB_Circle(C.getCenter(), C.getRadius() + r); final WB_Circle C2 = new WB_Circle(C.getCenter(), WB_Fast.abs(C .getRadius() - r)); final ArrayList<WB_Point2d> intersections = new ArrayList<WB_Point2d>(); intersections.addAll(WB_Intersection2D.intersect2D(L1, C1)); intersections.addAll(WB_Intersection2D.intersect2D(L1, C2)); intersections.addAll(WB_Intersection2D.intersect2D(L2, C1)); intersections.addAll(WB_Intersection2D.intersect2D(L2, C2)); for (int i = 0; i < intersections.size(); i++) { result.add(new WB_Circle(intersections.get(i), r)); } return result; } /** * Gets the circle tangent to two circles. * * @param C0 the c0 * @param C1 the c1 * @param r the r * @return the circle tangent to two circles */ public static ArrayList<WB_Circle> getCircleTangentToTwoCircles( final WB_Circle C0, final WB_Circle C1, final double r) { final ArrayList<WB_Circle> result = new ArrayList<WB_Circle>(2); final WB_Circle C0r = new WB_Circle(C0.getCenter(), C0.getRadius() + r); final WB_Circle C1r = new WB_Circle(C1.getCenter(), C1.getRadius() + r); final ArrayList<WB_Point2d> intersections = new ArrayList<WB_Point2d>(); intersections.addAll(WB_Intersection2D.intersect2D(C0r, C1r)); for (int i = 0; i < intersections.size(); i++) { result.add(new WB_Circle(intersections.get(i), r)); } return result; } }