如何计算三角形边框/描边的宽度,已知三角形向量和描边宽度?

3
我有一组三角形坐标,每三个点对应一个向量。在下图中,黄色细三角形表示原始三角形。我需要为该三角形添加一个向内和向外突出的描边或边框,位于原始黄色三角形线的中心。
因此,给定原始的三角形向量坐标和描边/边框宽度,如何计算黑色(描边/边框)三角形外部和内部边缘的向量坐标?
图片中的红点表示我需要计算的点。
三角形可以按宽度或高度缩放,我需要黑色描边/边框始终保持在给定的常数宽度。
尽管我需要单独在C++和javascript中实现这个问题用于WebGL,但我实际上只需要数学公式。
如果我们想象在javascript中可视化的变量,其中原始三角形边界框的左上角点为(0,0),那么我们会得到以下结果:
var width = 300;
var height = 200;
var strokeWidth = 20;
var V1 = {x: 0, y: height};
var V2 = {x: width, y: height};
var V3 = {x: width / 2, y: 0);

我需要计算出这六个红点的位置。非常感谢您的帮助。

enter image description here


2
你可能会发现这个页面很有用 - undefined
1个回答

2
当您将顶点位置定义为相对于中心时,您只需通过归一化它们来获取方向,然后将方向乘以笔画宽度并将结果加/减到您的顶点上,在glsl中应该是这样的:
float strokeWidth = 10.;
vec2 vdir = normalize(vertexPosition);
vec2 outer = vertexPosition + vdir * strokeWidth;
vec2 inner = vertexPosition - vdir * strokeWidth;

在没有任何数学库的情况下,使用JS的代码如下:

function Point(x,y){this.x = x, this.y = y}
var strokeWidth = 20;
var V1 = new Point(-100,50);
var V2 = new Point(100,50);
var V3 = new Point(0, -100);

var ctx = triangle.getContext("2d"), ctxRect = ctx.canvas.getBoundingClientRect();

function drawPoints () {
ctx.clearRect(0,0,ctxRect.width,ctxRect.height);

// draw initial points
ctx.strokeStyle = ctx.fillStyle = "#fa0";
ctx.fillRect(V1.x+ctxRect.width / 2,V1.y+ctxRect.height / 2,5,5);
ctx.fillRect(V2.x+ctxRect.width / 2,V2.y+ctxRect.height / 2,5,5);
ctx.fillRect(V3.x+ctxRect.width / 2,V3.y+ctxRect.height / 2,5,5);
// draw triangle lines
ctx.beginPath();
ctx.moveTo(V1.x+ctxRect.width / 2+2,V1.y+ctxRect.height / 2+2);
ctx.lineTo(V2.x+ctxRect.width / 2+2,V2.y+ctxRect.height / 2+2);
ctx.lineTo(V3.x+ctxRect.width / 2+2,V3.y+ctxRect.height / 2+2);
ctx.lineTo(V1.x+ctxRect.width / 2+2,V1.y+ctxRect.height / 2+2);
ctx.closePath();
ctx.stroke();

// get direction
var len = Math.sqrt(V1.x*V1.x+V1.y*V1.y);
var dx = V1.x / len, dy = V1.y / len;
var V1outer = new Point(V1.x + dx * strokeWidth, V1.y + dy * strokeWidth);
var V1inner = new Point(V1.x - dx * strokeWidth, V1.y - dy * strokeWidth);
console.log(V1outer);
len = Math.sqrt(V2.x*V2.x+V2.y*V2.y);
dx = V2.x / len, dy = V2.y / len;
var V2outer = new Point(V2.x + dx * strokeWidth, V2.y + dy * strokeWidth);
var V2inner = new Point(V2.x - dx * strokeWidth, V2.y - dy * strokeWidth);

len = Math.sqrt(V3.x*V3.x+V3.y*V3.y);
dx = V3.x / len, dy = V3.y / len;
var V3outer = new Point(V3.x + dx * strokeWidth, V3.y + dy * strokeWidth);
var V3inner = new Point(V3.x - dx * strokeWidth, V3.y - dy * strokeWidth);

ctx.strokeStyle = ctx.fillStyle = "#F00";
ctx.fillRect(V1outer.x+ctxRect.width / 2, V1outer.y+ctxRect.height / 2, 5,5);
ctx.fillRect(V2outer.x+ctxRect.width / 2, V2outer.y+ctxRect.height / 2, 5,5);
ctx.fillRect(V3outer.x+ctxRect.width / 2, V3outer.y+ctxRect.height / 2, 5,5);

// draw triangle lines
ctx.beginPath();
ctx.moveTo(V1outer.x+ctxRect.width / 2+2,V1outer.y+ctxRect.height / 2+2);
ctx.lineTo(V2outer.x+ctxRect.width / 2+2,V2outer.y+ctxRect.height / 2+2);
ctx.lineTo(V3outer.x+ctxRect.width / 2+2,V3outer.y+ctxRect.height / 2+2);
ctx.lineTo(V1outer.x+ctxRect.width / 2+2,V1outer.y+ctxRect.height / 2+2);
ctx.closePath();
ctx.stroke();
  
ctx.strokeStyle = ctx.fillStyle = "#0F0";
ctx.fillRect(V1inner.x+ctxRect.width / 2, V1inner.y+ctxRect.height / 2, 5,5);
ctx.fillRect(V2inner.x+ctxRect.width / 2, V2inner.y+ctxRect.height / 2, 5,5);
ctx.fillRect(V3inner.x+ctxRect.width / 2, V3inner.y+ctxRect.height / 2, 5,5);

ctx.beginPath();
ctx.moveTo(V1inner.x+ctxRect.width / 2+2,V1inner.y+ctxRect.height / 2+2);
ctx.lineTo(V2inner.x+ctxRect.width / 2+2,V2inner.y+ctxRect.height / 2+2);
ctx.lineTo(V3inner.x+ctxRect.width / 2+2,V3inner.y+ctxRect.height / 2+2);
ctx.lineTo(V1inner.x+ctxRect.width / 2+2,V1inner.y+ctxRect.height / 2+2);
ctx.closePath();
ctx.stroke();

}
drawPoints();
strokeInput.oninput = function () {strokeWidth = this.value; drawPoints()}
#triangle { border: 1px dashed black; }
<label>Stroke Width: <input id="strokeInput" type="range" min="0" max="50" value="20"/></label><br/>
<canvas id="triangle" width="400" height="400"></canvas>


那个例子实际上不起作用。尝试将V1.x设置为-10,将V2.x设置为10,你就会明白了。我猜你想要使用每条线的法线来生成一条新线,并与每条连接线相交吧? - undefined
一个非常出色和详尽的回答,但是gman是正确的。很接近了,可惜还差一点。不过还是谢谢你写得这么好的回答。 - undefined
@gordyr 你好,你找到解决方案了吗?我正在从零开始开发软件渲染器,但现在遇到了三角形边界的问题,能帮个忙吗?谢谢!:) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接