2015-06-08 3 views
2

В поисках code пример того, как рассчитать (точно) размеры прямоугольника сверху вниз (90 градусов) под определенным углом.Преобразование 2D-перспективы в JavaScript

, например. У меня есть прямоугольник 1200mm x 2000mm

enter image description here

Как бы я определить новые измерения в перспективе прямоугольника, если она была наклонена вниз 30 degrees на одной стороне. (Из 90o зрителем перспективного, сверху вниз)

enter image description here

Как с этой точки зрения будет выглядеть как нижний край короче, хотя, конечно, это не так. (Псевдо 3D в пути .. но на 2D-формы и в 2D виде)

редактирования: это предназначено в качестве справочного вопроса, пожалуйста, добавьте чередоваться с ответами на вопросы & решения

+0

Вы должны определить координаты точки зрения, так как перспективные искажения зависят от объекта-точки обзора расстояния – MBo

+0

я отправляю очень долго наматывается ответ на этот пост он будет скоро. –

ответ

4

Перспективное преобразование вы описываете называется ракурсом, и я предлагаю не только посмотреть на мой ответ, но и посмотреть на него больше информации, потому что это концепция с различными приложениями и может быть решена различными способами.

Имейте в виду, что Javascript не является моей сильной стороной, поэтому, если я делаю какие-либо синтаксические ошибки, прошу прощения и, пожалуйста, исправьте меня.

Для вашей конкретной формы простое использование похожих треугольников должно давать вам координаты вершин, которые вы могли бы использовать для структурирования вашей фигуры. Вы можете определить координаты вершин как векторы в пространстве.

Начну с определения вашей первоначальной формы в 2d-пространстве как серии из 4 вершин. (В левом нижнем я буду определять как начало.) В Javascript вы должны определить 2d-массив из 4 3-значных массивов. Каждый массив в массиве 2d будет представлять собой вершинную координату формы [x, y, z]. Значение x будет горизонтальным значением вершины, значение y будет значением высоты, а значение z будет тем, насколько далеко оно находится в 3d-пространстве. Значение y можно получить, умножив гипотенузу рампы (в данном случае 2000) на косинус угла наклона (в данном случае 30 градусов). Чтобы выполнить операцию косинуса, мы должны преобразовать угол от градусов к радианам. Преобразование всегда pi = 180, поэтому 30 в радианах - pi/6. Значение x можно получить, умножив гипотенузу на синус того же угла.

var hypotenuse = 2000; 
var theta = Math.PI/6; 
var x = Math.sin(theta)*hypotenuse; 
var y = Math.cos(theta)*hypotenuse; 
var z = 1200; 
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]]; 

Vertex coordinates on an xyz plane.

Перспективные преобразования происходят в связи с точки зрения зрителя по отношению к объекту. Поэтому, чтобы получить фактическое преобразование перспективы, мы должны определить положение зрителя. Я определяю его произвольно в точке (x/2, y + y/2, z/2).

var viewer = [x/2,y+y/2,z/2]; 

Viewer position

Мы тогда выбрать фокусное расстояние, которое будет определять, где определяется наше изображение. Фокусное расстояние - это всего лишь расстояние от зрителя, поэтому оно определяется только как одна точка. Скопируем фокусное расстояние произвольно (viewer_x, (y + y/2)/2, viewer_z), потому что это расстояние (y + y/2)/2 ниже зрителя.Вы должны, однако, удостовериться, что фокальная точка является той же координатой x и z, что и зритель, и что изменяется только ось y. Более подробную информацию о фокусном расстоянии и преобразовании перспективы можно найти на http://en.wikipedia.org/wiki/3D_projection.

var focal_length = [viewer[0],(y+y/2)/2,viewer[2]]; 

Focal Length coordinates

1.Now мы получаем расстояние от каждой вершины прямоугольника к зрителю вдоль оси у (ось, с помощью которого мы применяем перспективное преобразование). 2. Затем мы получаем расстояние от координаты y фокусного расстояния до зрителя. 3. Затем получим соотношение между фокусным расстоянием и расстоянием между вершинами. 4. Затем умножьте координаты x и z вершины на это соотношение, чтобы получить их новые координаты для каждой вершины.

Расстояния находятся путем простого вычитания координат y и получения абсолютного значения результата. Я сделаю все это в цикле for, чтобы получить более эффективный код.

var focal_distance = Math.abs(viewer[1] - focal_length[1]); 
//gets distance between focal point y and viewer y 
var vert_distance; 
for(var i = 0; i< vertices.length-1; i++){ 
    vert_distance = Math.abs(viewer[1]-vertices[i][1]); 
    //access each individual vertex and and get the distance between vertex y and viewer y 
    for (var j = 0; j<vertices[i].length-1; j++){ 
     vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance); 
     //gets the ratio between focal distance and vertex distance and multiplies each vertex by it 
    } 
} 

Наконец, так как мы сделали ракурс вдоль оси у, то у координаты каждой вершины больше нет необходимости, поэтому мы теперь будем брать каждую вершину и сохранить его в новый массив 2d вершин вместо 3d вершина ,

var vertices2d = [[0,0],[0,0],[0,0],[0,0]]; 
//creates a new 2d vertex array of 4 empty 2d vertex coordinates 
for(var i = 0; i<vertices.length-1; i++){ 
    vertices2d[i][0] = vertices[i][0]; 
    //sets the x values of the 2d vertices = to the x values of 3d vertices 
    vertices2d[i][1] = vertices[i][2]; 
    //sets the y values of the 2d vertices = to the z values of the 3d vertices 
} 

Теперь просто поместите эти 2d координаты вершин в любую графическую программу, и вы получите желаемый результат.

Я собираюсь программа распечатать координаты вершин в любом случае:

for (var i = 0; i<vertices2d.length-1; i++){ 
    document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")"); 
} 

Не стесняйтесь возиться с координатами зрителя, фокусное расстояние значения у, длину и ширину плоскости, а угол наклона для получения разных результатов. Улыбайтесь и не стесняйтесь задавать любые вопросы, если вы этого не получите.

Полный код бесперебойно ниже:

var hypotenuse = 2000; 
var theta = Math.PI/6; 
var x = Math.Sin(theta)*hypotenuse; 
var y = Math.Cos(theta)*hypotenuse; 
var z = 1200; 
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]]; 
var viewer = [x/2,y+y/2,z/2]; 
var focal_length = [viewer[0],(y+y/2)/2,viewer[2]]; 
var focal_distance = Math.abs(viewer[1] - focal_length[1]); 
//gets distance between focal point y and viewer y 
var vert_distance; 
for(var i = 0; i< vertices.length-1; i++){ 
    vert_distance = Math.abs(viewer[1]-vertices[i][1]); 
    //access each individual vertex and and get the distance between vertex y and viewer y 
    for (var j = 0; j<vertices[i].length-1; j++){ 
     vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance); 
     //gets the ratio between focal distance and vertex distance and multiplies each vertex by it 
    } 
} 
var vertices2d = [[0,0],[0,0],[0,0],[0,0]]; 
//creates a new 2d vertex array of 4 empty 2d vertex coordinates 
for(var i = 0; i<vertices.length-1; i++){ 
    vertices2d[i][0] = vertices[i][0]; 
    //sets the x values of the 2d vertices = to the x values of 3d vertices 
    vertices2d[i][1] = vertices[i][2]; 
    //sets the y values of the 2d vertices = to the z values of the 3d vertices 
} 
for (var i = 0; i<vertices2d.length-1; i++){ 
    document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")"); 
} 
+0

ps этот ответ ... невероятный ... – AndrewMcLagan