画圆SVG正交投影 [英] Draw circle svg orthogonal projections

查看:87
本文介绍了画圆SVG正交投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要获取在正交空间中投影的圆的svg路径. 示例

I need to get the svg path of a circle projected in a orthogonal space. Example

我想做的是创建一个具有以下参数的函数(在js中):

What I want to do is create a function(in js) that has the following parameters:

  1. 圆的位置

  1. the position of the circle

半径

以及与之平行的圆是什么面板

and what panel is the circle parallel to

轴倾角

这是我用来创建简单圆(无透视图)的功能

This is the function I use to create a simple circle (without perspective)

function getPath(cx,cy,r){
  return "M" + cx + "," + cy + "m" + (-r) + ",0a" + r + "," + r + " 0 1,0 " + (r * 2) + ",0a" + r + "," + r + " 0 1,0 " + (-r * 2) + ",0";
}

我不想近似创建数千个点并将其全部投影的圆,我想拥有一条能够准确描述投影圆的路径

I don't want to approximate the circle creating thousands of points and projecting them all, I want to have a path the accurately describes the projected circle

我该怎么办?

推荐答案

我正在从一个未发布的项目中提取一些东西,希望对您有意义.

I'm pulling something from an unpublished project and hope it makes sense for you.

假设您有两个点组成的三个点的tuple,分别描述了两个三角形,然后找到两个点之间的变换矩阵. -他们可以描述包含圆的正方形,如下所示:

Suppose you have two tupples of three points, describing two triangles, find the transform matrix between the two. - They could describe the square enclosing a circle, like this:

从两个点列表生成转换矩阵:

Generate the transformation matrix from two point lists:

var source = [s0, s1, s2]; // each point as coordinates {x, y}
var target = [t0, t1, t2];

function generate (source, target) {
    var transform = [
        {
            a: 1, b: 0, c: 0, d: 1,
            e: target[2].x,
            f: target[2].y
        },
        {
            a: 1, b: 0, c: 0, d: 1,
            e: -source[2].x,
            f: -source[2].y
        }
    ];
    source.forEach(point => {x: point.x - source[2].x, y:  point.y - source[2].y});
    target.forEach(point => {x: point.x - source[2].x, y:  point.y - source[2].y});

    var div = source[0].x * source[1].y - source[1].x * source[0].y;
    var matrix = {
        a: (target[0].x * source[1].y - target[1].x * source[0].y) / div,
        b: (target[0].y * source[1].y - target[1].y * source[0].y) / div,
        c: (target[1].x * source[0].x - target[0].x * source[1].x) / div,
        d: (target[1].y * source[0].x - target[0].y * source[1].x) / div,
        e: 0,
        f: 0
    };
    transform.splice(1, 0, matrix);

    return transform.reduce(function (m1, m2) {
        return {
            a: m1.a * m2.a + m1.c * m2.b,
            b: m1.b * m2.a + m1.d * m2.b,
            c: m1.a * m2.c + m1.c * m2.d,
            d: m1.b * m2.c + m1.d * m2.d,
            e: m1.a * m2.e + m1.c * m2.f + m1.e,
            f: m1.b * m2.e + m1.d * m2.f + m1.f
        }
    }, { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
}

现在,如果您有一个描述为对象arc

Now, if you have an absolute arc command described as an object arc

{ rx, ry, rotation, large, sweep, x, y }

可以像这样应用转换:

function arc_transform (transform, arc) {
    var co = Math.cos(arc.rotation/180*Math.PI),
        si = Math.sin(arc.rotation/180*Math.PI);
    var m = [
        arc.rx * (transform.a * co + transform.c * si),
        arc.rx * (transform.b * co + transform.d * si),
        arc.ry * (transform.c * co - transform.a * si),
        arc.ry * (transform.d * co - transform.b * si),
    ];
    var A = (m[0] * m[0]) + (m[2] * m[2]),
        B = 2 * (m[0] * m[1] + m[2] * m[3]),
        C = (m[1] * m[1]) + (m[3] * m[3]),
        K = Math.sqrt((A - C) * (A - C) + B * B);

    if ((transform.a * transform.d) - (transform.b * transform.c) < 0) {
        arc.sweep = !arc.sweep;
    }

    return {
        rx:  Math.sqrt(0.5 * (A + C + K)),
        ry:  Math.sqrt(0.5 * Math.max(0, A + C - K)),
        rotation: Math.abs((A - C) / B) < 1e-6 ? 90 : Math.atan2(B, A - C)*90/Math.PI,
        large: arc.large,
        sweep: arc.sweep,
        x: transform.a * arc.x + transform.c * arc.y + transform.e,
        y: transform.b * arc.x + transform.d * arc.y + transform.f
    };
};

这篇关于画圆SVG正交投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆