从4个角透视创建网格 [英] Create a grid in perspective from 4 corners

查看:78
本文介绍了从4个角透视创建网格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从其4个角生成一个点网格.由于可以自由放置这些角,因此看起来就像网格有一个视角.

I'm trying to generate a grid of points from its 4 corners. As this corners can be freely placed, it will look as the grid has a perspective.

我在Processing中编写了以下代码,其中角按顺时针顺序(从左上角开始)

I've written the following code in Processing, where corners are in clockwise order (starting at top-left)

PVector[][] setGrid(PVector[] corners, int cols, int rows) {
    PVector[][] grid = new PVector[rows][cols];
    for(int y = 0; y < rows; y++) {
        float fY = (float)y / (rows - 1);
        PVector p1 = PVector.lerp(corners[0], corners[3], fY);
        PVector p2 = PVector.lerp(corners[1], corners[2], fY);
        for(int x = 0; x < cols; x++) {
            grid[y][x] = PVector.lerp(p1, p2, (float)x / (cols-1));
        }
    }
    return grid;
}

这将生成一个带有插值点的网格,但它不对应于透视网格.所有串联的点都是等距的,而在透视图中,最接近的点应该比最远的点分开.

This generates a grid with interpolated points, but it doesn't correspond to a perspective grid. All in-line points are equidistant, while in perspective closest points should be more separated than farthest.

如果可以的话,我希望在Java/Processing中有一定的了解

I would appreciate some orientation, if possible, in Java/Processing

编辑

澄清我的答案.我定义了4个随机角点,我想获取所有创建透视变形网格的点.注意,由于透视图dX1!= dX2以及dY1!= dY2.我编写的代码没有这种效果(我知道这一点,但是我不知道该怎么做),因为对点进行插值会导致dX1 = dX2 = ... = dXi和dY1 = dY2 = ... = dYi

To clarify my answer. I define 4 random corner points, I want to get all the points that create a perspective deformed grid. Note that because of perspective dX1 != dX2 as well as dY1 != dY2 . The code I wrote does not this effect (I know this, but I don't know how to do what I require) as points are interpolated resulting dX1 = dX2 = ... = dXi and dY1 = dY2 = ... = dYi

我已经了解了透视变换,但是我不需要变换图像,我只需要获取网格点坐标.

I've read about perspective transform, but I don't need to transform an image, I just need to get the grid points coordinates.

推荐答案

我已经采用几何方法解决了这一问题:从角落识别网格消失点,并从平移的地平线进行插值.我已经为此GridPerspective创建了一个类.

I've solved it taking a geometric approach: identifying grid vanishing points from corners, and interpolating from the translated horizon line. I've created a class for this GridPerspective.

只有两个要求:

  1. 转角必须为顺时针顺序.

  1. Corners must be in clockwise order.

网格边不能平行(消失点为无限).

处理代码:

GridPerspective grid;

void setup() {
    size(600, 600, P2D);
    grid = new GridPerspective(10, 10);
}


void draw() {
    background(0);
    grid.draw();
}

void mouseClicked() {
    grid.addCorner(new PVector(mouseX, mouseY));
}

public class GridPerspective {

    int cols, rows;
    PVector[] corners = new PVector[4];
    int selC;
    PVector[][] points;

    public GridPerspective(int cols, int rows) {
        this.cols = cols;
        this.rows = rows;
    }

    public void addCorner(PVector corner) {
        if(selC < 4) {
            corners[selC++] = corner;
            if(selC == 4) update();
        }
    }

    public void update() {
        if(corners[0] == null || corners[1] == null || corners[2] == null || corners[3] == null) return;
        PVector[] vanishing = new PVector[] {
            linesIntersection(corners[0], corners[3], corners[1], corners[2]),
            linesIntersection(corners[0], corners[1], corners[3], corners[2])
        };
        PVector topHorizon = PVector.sub(vanishing[1], vanishing[0]);
        PVector bottomHorizon = PVector.add(corners[3], topHorizon);
        PVector[] bottomLimits = new PVector[] {
            linesIntersection(corners[3], bottomHorizon, vanishing[0], corners[1]),
            linesIntersection(corners[3], bottomHorizon, vanishing[1], corners[1])
    };
        points = new PVector[rows][cols];
        for(int r = 0; r < rows; r++) {
            PVector bpr = PVector.lerp(corners[3], bottomLimits[0], (float)r / (rows-1));
            for(int c = 0; c < cols; c++) {
                PVector bpc = PVector.lerp(corners[3], bottomLimits[1], (float)c / (cols-1));
            points[r][c] = linesIntersection(bpr, vanishing[0], bpc, vanishing[1]);
            }
        }
    }

    public void draw() {
        if(points != null) {    
            fill(255);
            for(int r = 0; r < rows; r++) {
                for(int c = 0; c < cols; c++) {
                    ellipse(points[r][c].x, points[r][c].y, 4, 4);
                }
            }   
        }
    }

    private PVector linesIntersection(PVector p1, PVector p2, PVector p3, PVector p4) {
        float d = (p2.x-p1.x) * (p4.y - p3.y) - (p2.y-p1.y) * (p4.x - p3.x);
        if(d == 0) return null;
        return new PVector(p1.x+(((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d)*(p2.x-p1.x), p1.y+(((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d)*(p2.y-p1.y));
    }

}

这篇关于从4个角透视创建网格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆