我有一套三角形坐标。每三个点一个 vector 。在下面的图像中,该三角形是thin yellow
一个。我需要向此三角形添加一个stroke
或border
,该三角形向内和向外突出,并以原始黄色三角形线为中心。
因此,给定原始的三个三角形vector
坐标和笔触/边界width
,如何计算vector
(描边/边界)三角形的外部和内部边缘的black
坐标?
图像中的red
点表示我需要计算的点。
三角形可以按宽度或高度缩放,我需要黑色笔触/边框始终保持恒定的给定宽度。
尽管我需要在C++
和javascript
中分别为WebGL
实现此功能,但这实际上只是我需要的数学公式。
如果我们想象我已经用variables
可视化了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);
由此,我需要计算所有六个红点。在此先感谢您的帮助。
最佳答案
当您定义顶点相对于中心的位置时,您可以通过将其标准化来获得方向,然后将方向乘以笔划宽度并将结果加/减到顶点,以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>
关于javascript - 给定三 Angular 形 vector 和笔触宽度,如何计算添加到三 Angular 形的边框/笔触?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36191147/