代码之家  ›  专栏  ›  技术社区  ›  Tom

Java尝试在2D中进行光线投射

  •  2
  • Tom  · 技术社区  · 8 年前

    我有一个类形状,它只包含顶点和用于绘制自身的函数,

    我已经试过三次了,但都不完全正确,有些光线甚至在某些位置上都没有出现。我已经测试了计算交点位置的代码,它可以工作:

    public static Point2D getLineIntersection(Line2D ray, Line2D segment) {
        if(ray.intersectsLine(segment)){
            double rx1 = ray.getX1(),
                    ry1 = ray.getY1(),
                    rx2 = ray.getX2(),
                    ry2 = ray.getY2(),
                    sx1 = segment.getX1(),
                    sy1 = segment.getY1(),
                    sx2 = segment.getX2(),
                    sy2 = segment.getY2(),
                    rdx = Math.abs(rx2 - rx1),
                    rdy = Math.abs(ry2 - ry1),
                    sdx = Math.abs(sx2 - sx1),
                    sdy = Math.abs(sy2 - sy1),
                    t1, t2,
                    ix, iy;
    
            t2 = (rdx * (sy1 - ry1) + rdy * (rx1 - sx1)) / (sdx * rdy - sdy * rdx);
            t1 = (sx1 + sdx * t2 - rx1) / rdx;
    
            if(t1 > 0 && 1 > t2 && t2 > 0){
                ix = rx1 + rdx * t1;
                iy = ry1 + rdy * t1;
                return new Point2D.Float((int) ix, (int) iy);
            }else
                return null;
        }else
            return null;
    }
    

    public void castRays(Graphics g, ArrayList<Shape> map){
        ArrayList<Ray> rays = new ArrayList<>();
        ArrayList<Point2D> vertices = new ArrayList<>();
        ArrayList<Line2D> segments = new ArrayList<>();
    
        //populate vertices and segments
        for(Shape s : map){
            vertices.addAll(Arrays.asList(s.getPoints()));
            segments.addAll(s.getLines());
        }
    
        for(Point2D v : vertices){
            Ray ray = new Ray(x, y, (int) v.getX(), (int) v.getY());
            ArrayList<Point2D> rayIntersects = new ArrayList<>();
            Point2D closestIntersect = null;
    
            for(Line2D s : segments)
                if(Utils.getLineIntersection(ray.getLine(), s) != null)
                    rayIntersects.add(Utils.getLineIntersection(ray.getLine(), s));
    
            if(rayIntersects.size() > 0){
                for(int i = 0; i < rayIntersects.size(); i++){
                    if(i == 0)
                        closestIntersect = rayIntersects.get(0);
                    else{
                        if(Utils.getLineLength(new Line2D.Float(x, y, (int) closestIntersect.getX(), (int) closestIntersect.getY()))
                                > Utils.getLineLength(new Line2D.Float(x, y, (int) rayIntersects.get(i).getX(), (int) rayIntersects.get(i).getY())))
                            closestIntersect = rayIntersects.get(i);
                    }
                }
            }
            if(closestIntersect != null)
                rays.add(new Ray(x, y, (int) closestIntersect.getX(), (int) closestIntersect.getY()));
        }
    
        for(Ray r : rays)
            r.render(g, Color.WHITE);
    }
    
    public static double getLineLength(Line2D line){
        double dx = Math.abs(line.getX2() - line.getX1()),
                dy = Math.abs(line.getY2() - line.getY1());
        return Math.sqrt(dx * dx + dy * dy);
    }
    

    如果你需要更多的代码,尽管问吧,但我认为问题出在castRays函数中

    1 回复  |  直到 8 年前
        1
  •  4
  •   Tom    8 年前

    发现了我的错误。结果证明我错了:

    public static Point2D getLineIntersection(Line2D ray, Line2D segment) {
        if(ray.intersectsLine(segment)){
            double rx1 = ray.getX1(),
                    ry1 = ray.getY1(),
                    rx2 = ray.getX2(),
                    ry2 = ray.getY2(),
                    sx1 = segment.getX1(),
                    sy1 = segment.getY1(),
                    sx2 = segment.getX2(),
                    sy2 = segment.getY2(),
                    rdx = rx2 - rx1,
                    rdy = ry2 - ry1,
                    sdx = sx2 - sx1,
                    sdy = sy2 - sy1,
                    t1, t2,
                    ix, iy;
    
            t2 = (rdx * (sy1 - ry1) + rdy * (rx1 - sx1)) / (sdx * rdy - sdy * rdx);
            t1 = (sx1 + sdx * t2 - rx1) / rdx;
    
            if(t1 > 0/* && 1 > t2 && t2 > 0*/){
                ix = rx1 + rdx * t1;
                iy = ry1 + rdy * t1;
                return new Point2D.Float((int) ix, (int) iy);
            }else
                return null;
        }else
            return null;
    }