我想将图像中表示的 3D 点绘制到 3D 矩形中。知道如何在 x、y 和 z 轴上表示这些
此处投影类型为正交。
谢谢
最佳答案
好的。让我们看一个简单的示例,说明您要实现的目标,以及为什么这是一个如此复杂的问题。
首先,让我们看一些投影函数。您需要一种方法来从数学上描述如何将 3D(或更高维)点转换为 2D 空间(您的显示器)或投影。
最容易理解的是一个非常简单的二轴投影。像这样的东西:
x' = x + z/2;
y' = y + z/4;
这是什么意思?嗯,x'
是你的 x 坐标二维投影:对于你在空间中向后移动的每个单位,投影会将那个点向右边移动一半的单位。 y'
代表您的 y 坐标的相同投影:对于您在空间中向后 移动的每个单位,投影 都会将该点移动四分之一单位起来。
因此 [0,0,0]
处的点将投影到 [0,0]
的二维点。 [0,0,4]
处的点将投影到 [2,1]
的二维点。
用 JavaScript 实现,它看起来像这样:
// Dimetric projection functions
var dimetricTx = function(x,y,z) { return x + z/2; };
var dimetricTy = function(x,y,z) { return y + z/4; };
一旦您拥有这些投影功能(或将 3D 空间转换为 2D 空间的方法),您就可以使用它们开始绘制图像。使用 js Canvas 的一个简单示例。首先,一些上下文内容:
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
现在,让我们制作一个绘制 3D 点的小助手:
var drawPoint = (function(ctx,tx,ty, size) {
return function(p) {
size = size || 3;
// Draw "point"
ctx.save();
ctx.fillStyle="#f00";
ctx.translate(tx.apply(undefined, p), ty.apply(undefined,p));
ctx.beginPath();
ctx.arc(0,0,size,0,Math.PI*2);
ctx.fill();
ctx.restore();
};
})(ctx,dimetricTx,dimetricTy);
这是一个非常简单的函数,我们将 Canvas 上下文注入(inject)为 ctx
,以及我们的 tx
和 ty
函数,它们在这种情况是我们之前看到的二元函数。
现在是一个多边形抽屉:
var drawPoly = (function(ctx,tx,ty) {
return function() {
var args = Array.prototype.slice.call(arguments, 0);
// Begin the path
ctx.beginPath();
// Move to the first point
var p = args.pop();
if(p) {
ctx.moveTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
// Draw to the next point
while((p = args.pop()) !== undefined) {
ctx.lineTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
ctx.closePath();
ctx.stroke();
};
})(ctx, dimetricTx, dimetricTy);
使用这两个函数,您可以有效地绘制您正在寻找的那种图形。例如:
// The array of points
var points = [
// [x,y,z]
[20,30,40],
[100,70,110],
[30,30,75]
];
(function(width, height, depth, points) {
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
// Set some context
ctx.save();
ctx.scale(1,-1);
ctx.translate(0,-c.height);
ctx.save();
// Move our graph
ctx.translate(100,20);
// Draw the "container"
ctx.strokeStyle="#999";
drawPoly([0,0,depth],[0,height,depth],[width,height,depth],[width,0,depth]);
drawPoly([0,0,0],[0,0,depth],[0,height,depth],[0,height,0]);
drawPoly([width,0,0],[width,0,depth],[width,height,depth],[width,height,0]);
drawPoly([0,0,0],[0,height,0],[width,height,0],[width,0,0]);
ctx.stroke();
// Draw the points
for(var i=0;i<points.length;i++) {
drawPoint(points[i]);
}
})(150,100,150,points);
但是,您现在应该能够开始看到实际问题的一些复杂性。也就是说,您询问了旋转,在这个例子中,我们使用了一个非常简单的投影(我们的二元投影),除了深度及其对 x,y 位置的影响之间的过于简化的关系之外,它不需要太多。随着投影变得越来越复杂,您需要更多地了解您在 3D 空间中的关系/方向,以便创建合理的 2D 投影。
上述代码的一个工作示例可以是 found here .该示例还包括等轴投影函数,可以将其换成二轴投影函数,以查看它如何改变图形的外观。它还会执行一些我未在此处包含的不同可视化内容,例如绘制“阴影”以帮助“可视化”实际方向——3D 到 2D 投影的局限性。
这很复杂,即使是肤浅的讨论也超出了这个 stackoverflow 的范围。我建议您阅读更多关于 3D 背后的数学知识,有大量在线资源和打印形式的资源。一旦您对数学工作原理有了更深入的了解,如果您有具体的实现问题,请返回此处。
关于javascript - 如何根据 x、y 和 z 在 3D 矩形中画线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12267839/