拉斐尔三角形的中心
center of Raphael triangle
假设我需要在三角形区域的中间放置一个文本。
我可以使用 getBBox():
计算三角形中心的坐标
var triangle = "M0,0 L100,0 100,50 z";
var BBox = paper.path(triangle).getBBox();
var middle;
middle.x = BBox.x + BBox.width/2;
middle.y = BBox.y + BBox.height/2;
这导致坐标 (50, 25) 始终位于三角形的长边。
我怎样才能确保计算出的 "middle" 在 内部 三角形?
正确的坐标应该大约是:(75, 25).
代码当然应该独立于这个特定的例子,它应该适用于任何形状。
此代码段将通过平均顶点计算任何多边形的中心。
var paper = Raphael(0,0, 320, 200);
var triangle = "M0,0 L100,0 100,50 z";
var tri = paper.path(triangle);
tri.attr('fill', 'blue');
var center = raphaelPathCenter( tri );
var circle = paper.circle( center.x, center.y, 5);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
function raphaelPathCenter( path ) {
path.getBBox(); // forces path to be traced so realPath is not null.
var vertices = parseSVGVertices( path.realPath );
var center = vertices.reduce( function(prev,cur) {
return { x: prev.x + cur.x, y: prev.y + cur.y }
}, {x:0, y:0} );
center.x /= vertices.length;
center.y /= vertices.length;
return center;
}
function parseSVGVertices( svgPath )
{
var vertices = [];
for ( var i = 0; i < svgPath.length; i ++ )
{
var vertex = svgPath[i];
if ( "ML".indexOf( vertex[0] ) > -1 ) // check SVG command
vertices.push( { x: vertex[1], y: vertex[2] } );
}
return vertices;
}
<script src="https://raw.githubusercontent.com/DmitryBaranovskiy/raphael/master/raphael-min.js"></script>
<canvas id='canvas'></canvas>
<pre id='output'></pre>
不过有a few more triangle centers可以选择。
我对该主题进行了更多研究,并根据另一个列表中的建议来到这里:
https://en.wikipedia.org/wiki/Centroid
那里有一个计算不规则多边形质心的算法,我把它翻译成了这个代码:
function getCentroid(path) {
var x = new Array(11);
var y = new Array(11);
var asum = 0, cxsum = 0, cysum = 0;
var totlength = path.getTotalLength();
for (var i = 0; i < 11; i++) {
var location = path.getPointAtLength(i*totlength/10);
x[i] = location.x;
y[i] = location.y;
if (i > 0) {
asum += x[i - 1]*y[i] - x[i]*y[i - 1];
cxsum += (x[i - 1] + x[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
cysum += (y[i - 1] + y[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
}
}
return({x: (1/(3*asum))*cxsum, y: (1/(3*asum))*cysum});
}
基本上是任意路径的10个点的近似(第11个等于起点),函数returns,对于那个三角形,坐标:
Object {x: 65.32077336966377, y: 16.33111549955705}
我用很多其他形状测试过它,效果很好。
希望对大家有所帮助。
假设我需要在三角形区域的中间放置一个文本。 我可以使用 getBBox():
计算三角形中心的坐标var triangle = "M0,0 L100,0 100,50 z";
var BBox = paper.path(triangle).getBBox();
var middle;
middle.x = BBox.x + BBox.width/2;
middle.y = BBox.y + BBox.height/2;
这导致坐标 (50, 25) 始终位于三角形的长边。 我怎样才能确保计算出的 "middle" 在 内部 三角形?
正确的坐标应该大约是:(75, 25).
代码当然应该独立于这个特定的例子,它应该适用于任何形状。
此代码段将通过平均顶点计算任何多边形的中心。
var paper = Raphael(0,0, 320, 200);
var triangle = "M0,0 L100,0 100,50 z";
var tri = paper.path(triangle);
tri.attr('fill', 'blue');
var center = raphaelPathCenter( tri );
var circle = paper.circle( center.x, center.y, 5);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
function raphaelPathCenter( path ) {
path.getBBox(); // forces path to be traced so realPath is not null.
var vertices = parseSVGVertices( path.realPath );
var center = vertices.reduce( function(prev,cur) {
return { x: prev.x + cur.x, y: prev.y + cur.y }
}, {x:0, y:0} );
center.x /= vertices.length;
center.y /= vertices.length;
return center;
}
function parseSVGVertices( svgPath )
{
var vertices = [];
for ( var i = 0; i < svgPath.length; i ++ )
{
var vertex = svgPath[i];
if ( "ML".indexOf( vertex[0] ) > -1 ) // check SVG command
vertices.push( { x: vertex[1], y: vertex[2] } );
}
return vertices;
}
<script src="https://raw.githubusercontent.com/DmitryBaranovskiy/raphael/master/raphael-min.js"></script>
<canvas id='canvas'></canvas>
<pre id='output'></pre>
不过有a few more triangle centers可以选择。
我对该主题进行了更多研究,并根据另一个列表中的建议来到这里: https://en.wikipedia.org/wiki/Centroid
那里有一个计算不规则多边形质心的算法,我把它翻译成了这个代码:
function getCentroid(path) {
var x = new Array(11);
var y = new Array(11);
var asum = 0, cxsum = 0, cysum = 0;
var totlength = path.getTotalLength();
for (var i = 0; i < 11; i++) {
var location = path.getPointAtLength(i*totlength/10);
x[i] = location.x;
y[i] = location.y;
if (i > 0) {
asum += x[i - 1]*y[i] - x[i]*y[i - 1];
cxsum += (x[i - 1] + x[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
cysum += (y[i - 1] + y[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
}
}
return({x: (1/(3*asum))*cxsum, y: (1/(3*asum))*cysum});
}
基本上是任意路径的10个点的近似(第11个等于起点),函数returns,对于那个三角形,坐标:
Object {x: 65.32077336966377, y: 16.33111549955705}
我用很多其他形状测试过它,效果很好。
希望对大家有所帮助。