总结日常工作中计算家具模型需要用到的方法,需要用到JTS库 /** * 点(point)到直线(pt1_pt2)的垂足点 * @param point * @param pt1 * @param pt2 * @return */ public static Point getFootPoint(Point point, Point pt1, Point pt2) { double A=pt2.getY()-pt1.getY(); //y2-y1 double B=pt1.getX()-pt2.getX(); //x1-x2; double C=pt2.getX()*pt1.getY()-pt1.getX()*pt2.getY(); //x2*y1-x1*y2 if (A * A + B * B < 1e-13) { return pt1; //pt1与pt2重叠 } else if (Math.abs(A * point.getX() + B * point.getY() + C) < 1e-13) { return point; //point在直线上(pt1_pt2) } else { double x = (B * B * point.getX() - A * B * point.getY() - A * C) / (A * A + B * B); double y = (-A * B * point.getX() + A * A * point.getY() - B * C) / (A * A + B * B); return new Point(x,y); } }
/** * 判断两条线段是否相交 * * @param p1 l1的起点 * @param p2 l1的终点 * @param p3 l2的起点 * @param p4 l2的终点 * @return */ public static boolean lineIntersect(Point p1,Point p2,Point p3,Point p4) { if (Math.min(p1.getX(), p2.getX()) <= Math.max(p3.getX(), p4.getX()) && Math.max(p1.getX(), p2.getX()) >= Math.min(p3.getX(), p4.getX()) && Math.min(p1.getY(), p2.getY()) <= Math.max(p3.getY(), p4.getY()) && Math.max(p1.getY(), p2.getY()) >= Math.min(p3.getY(), p4.getY()) && mulVector(p3, p1, p4) * mulVector(p3, p4, p2) >= 0 && mulVector(p1, p3, p2) * mulVector(p1, p2, p4) >= 0) { return true; } return false; } /** * 判定点是否在区域内 * @param vertx 区域的所有x点 * @param verty 区域的所有y点 * @param point * @return */ public static boolean pnpoly(Double[] vertx,Double[] verty,Point point){ boolean c = false; double testx = point.getX(); double testy = point.getY(); double minX = Arrays.stream(vertx).min(Double::compareTo).orElse(0D); double minY = Arrays.stream(verty).min(Double::compareTo).orElse(0D); double maxX = Arrays.stream(vertx).max(Double::compareTo).orElse(0D); double maxY = Arrays.stream(verty).max(Double::compareTo).orElse(0D); if (testx < minX || testx > maxX || testy < minY || testy > maxY) { return c; } int nvert = vertx.length; int i, j; for (i = 0, j = nvert-1; i < nvert; j = i++) { if ( ((verty[i]>testy) != (verty[j]>testy)) && (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ) { c = !c; } } //拓展,点正好在边界上 if(!c){ for (i = 0, j = nvert-1; i < nvert; j = i++) { c = onSegment(new Point(vertx[i],verty[i]),new Point(vertx[j],verty[j]),point); if(c){ break; } } } return c; }
/** * 根据直线方程获取在直线上且与p1距离为L的某点的坐标 * @param l 距离 正数时取直线之间的点,负数时取直线之外的点 * @param p1 * @param p2 * @return */ public static Point getPointByEquation(double l, Point p1, Point p2) { if(l==0){ return new Point(p1.getX(),p1.getY(),0); } double d = AlgorithmUtils.getDistance(p1,p2); if(l==d){ return new Point(p2.getX(),p2.getY(),0); } Double[] equation = equation(p1, p2); Double k = equation[0]; if(k.isInfinite() || Math.abs(k)==1.5707963267948966 || Math.abs(k)==4.71238898038469){ if(p1.getY()>p2.getY()){ return new Point(p1.getX(),p1.getY()-l,0); }else { return new Point(p1.getX(),p1.getY()+l,0); } }else if(Math.abs(k)==0){ if(p1.getX()>p2.getX()){ return new Point(p1.getX()-l,p1.getY(),0); }else { return new Point(p1.getX()+l,p1.getY(),0); } }else{ // double A = Math.pow(k, 2) + 1;// A=k^2+1; // double B = 2 * ((b - p1.getY()) * k - p1.getX());// B=2[(b-y0)k-x0]; // // C=(b-y0)^2+x0^2-L^2 // double C = Math.pow(b - p1.getY(), 2) + Math.pow(p1.getX(), 2) - Math.pow(l, 2); // // 两根x1,x2= [-B±√(B^2-4AC)]/2A // double x1 = (-B + Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A); // double x2 = (-B - Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A); // double x = 0;// 最后确定是在已知两点之间的某点 // if (x1 == x2) { // x = x1; // } else if (p1.getX() <= x1 && x1 <= p2.getX() || p2.getX() <= x1 // && x1 <= p1.getX()) { // x = x1; // } else if (p1.getX() <= x2 && x2 <= p2.getX() || p2.getX() <= x2 // && x2 <= p1.getX()) { // x = x2; // } // double y = k * x + b; // return new Point( x, y,0); return JtsUtils.getExtractPoint(p1,p2,l,0); } }
/** * 获取点关于线的对称点 * @param p1 * @param p2 * @param p * @return */ public static Point getSymmetryPoint(Point p1,Point p2, Point p){ double a=p2.getY()-p1.getY(); double b=p1.getX()-p2.getX(); double c=p2.getX()*p1.getY()-p1.getX()*p2.getY(); double k = - 2 * (a*p.getX() + b*p.getY() + c) / (a*a+b*b); double x = p.getX()+k*a; double y = p.getY()+k*b; return new Point(x,y); }