Esempio n. 1
0
 public PBCircleNode(PBCircleNode node)
 {
     circle   = node.circle;
     position = node.position;
     tangent  = node.tangent;
     angle    = node.angle;
 }
Esempio n. 2
0
    public float deltaAngle(PBCircleNode targetNode)
    {
        float deltaAngle = targetNode.angle - this.angle;

        if (deltaAngle < 0)
        {
            deltaAngle += 360;
        }
        return(deltaAngle);
    }
Esempio n. 3
0
    public void GetBottomMidSample(out Vector3 position, out Vector3 tangent, out Vector3 emit, out float distance)
    {
        //单圆
        if (curveType == PBCircleCurveType.OneCircle)
        {
            PBCircleNode node = nodes.First.Value;
            Vector3      r    = -node.circle.up.normalized;
            position = node.circle.center + r * node.circle.radius;
            tangent  = -node.tangent;
            emit     = r;
            distance = 0.5f * nodes.Last.Value.distance;

            return;
        }

        PBCircleNode node1;
        PBCircleNode node2;

        if (curveType == PBCircleCurveType.Line)
        {
            int half  = (nodes.Count - 1) / 2;
            int index = half + half / 2;
            node1 = nodes.ElementAt(index - 1);
            node2 = nodes.ElementAt(index);
        }
        else
        {
            int half = (nodes.Count - 1) / 2;
            node1 = nodes.ElementAt(half - 1);
            node2 = nodes.ElementAt(half);
        }

        if (node1.ConnectLine(node2))
        {
            position = Vector3.Lerp(node1.position, node2.position, 0.5f);
            tangent  = node1.tangent;
            emit     = (node1.position - node1.circle.center).normalized;
            distance = 0.5f * (node1.distance + node2.distance);
        }
        else
        {
            PBCircle circle = node1.circle;
            float    angle  = node1.angle + 0.5f * node1.deltaAngle(node2);
            Vector3  r      = Quaternion.AngleAxis(angle, circle.forward) * circle.up;
            r.Normalize();
            position = circle.center + r * circle.radius;
            tangent  = Quaternion.AngleAxis(angle, circle.forward) * (-circle.right);
            emit     = r;
            distance = 0.5f * (node1.distance + node2.distance);
        }
    }
    private static PBCircleNode[] CalculateTangentLines(PBCircle c1, PBCircle c2)
    {
        Vector3 o1o2          = c2.center - c1.center;
        float   o1o2_distance = o1o2.magnitude;

        o1o2.Normalize();

        float angle;// 90-圆心连线与公切线的夹角

        if (Mathf.Approximately(c1.radius, c2.radius))
        {
            angle = 90;
        }
        else
        {
            float r1 = Mathf.Max(c1.radius, c2.radius);
            float r2 = Mathf.Min(c1.radius, c2.radius);

            float x = o1o2_distance * r1 / (r1 - r2);
            angle = Mathf.Acos(r1 / x) * Mathf.Rad2Deg;

            if (c1.radius < c2.radius)
            {
                angle = 180 - angle;
            }
        }

        Vector3[] Rs = new[]
        {
            Quaternion.AngleAxis(angle, c1.forward) * o1o2,
            Quaternion.AngleAxis(angle, -c1.forward) * o1o2,
        };

        PBCircleNode[] nodes = new PBCircleNode[4];

        for (int i = 0; i < Rs.Length; i++)
        {
            PBCircleNode n1, n2; //第 i 条公切线的c1、c2上的点

            Vector3 r       = Rs[i];
            Vector3 p       = c1.center + r * c1.radius;
            Vector3 tangent = Quaternion.AngleAxis(90, c1.forward) * r;
            n1 = new PBCircleNode(c1, p, tangent, GetAngle(c1, r));
            p  = c2.center + r * c2.radius;
            n2 = new PBCircleNode(c2, p, tangent, GetAngle(c2, r));

            nodes[i * 2]     = n1;
            nodes[i * 2 + 1] = n2;
        }
        return(nodes);
    }
Esempio n. 5
0
    /// <summary>
    /// 通过距离起点的距离,获取线上的点的坐标、斜率、圆心到坐标的单位向量(垂直于斜率)
    /// </summary>
    public void GetSampleAtDistance(float distance, out Vector3 position, out Vector3 tangent, out Vector3 emit)
    {
        LinkedListNode <PBCircleNode> listNode = nodes.First;
        PBCircleNode startNode = null;
        PBCircleNode endNode   = null;

        while (listNode != null)
        {
            if (distance < listNode.Value.distance)
            {
                startNode = listNode.Previous.Value;
                endNode   = listNode.Value;
                break;
            }
            listNode = listNode.Next;
        }

        if (startNode == null)
        {
            throw new ArgumentException(string.Format("Distance must be less than curve length. Curve length: {0}, distance: {1}",
                                                      nodes.Last.Value.distance, distance));
        }

        float t = (distance - startNode.distance) / (endNode.distance - startNode.distance);

        if (startNode.ConnectLine(endNode))
        {
            //直线
            position = Vector3.Lerp(startNode.position, endNode.position, t);
            tangent  = startNode.tangent;
            emit     = (startNode.position - startNode.circle.center).normalized;
        }
        else
        {
            //圆弧
            PBCircle circle = startNode.circle;
            float    angle  = startNode.angle + t * startNode.deltaAngle(endNode);
            Vector3  r      = Quaternion.AngleAxis(angle, circle.forward) * circle.up;
            r.Normalize();
            position = circle.center + r * circle.radius;

            tangent = Quaternion.AngleAxis(angle, circle.forward) * (-circle.right);

            emit = r;
        }
    }
    public static LinkedList <PBCircleNode> Build(PBCircle[] circles, PBCircleCurveType type)
    {
        LinkedList <PBCircleNode> nodes = null;

        switch (type)
        {
        case PBCircleCurveType.OneCircle:
            nodes = BuildForOne(circles);
            break;

        case PBCircleCurveType.Line:
            nodes = BuildForLine(circles);
            break;

        case PBCircleCurveType.Enclosed:
            nodes = BuildForEnclosed(circles);
            break;
        }

        //compute distance for nodes
        LinkedListNode <PBCircleNode> listNode = nodes.First;

        listNode.Value.distance = 0;
        listNode = listNode.Next;
        while (listNode != null)
        {
            PBCircleNode node    = listNode.Value;
            PBCircleNode preNode = listNode.Previous.Value;
            if (node.ConnectLine(preNode))
            {
                //直线
                node.distance = preNode.distance + Vector3.Distance(node.position, preNode.position);
                //Debug.Log(">>>>>>>1 distance: " + node.distance);
            }
            else
            {
                //圆弧
                float radius = node.circle.radius;
                node.distance = preNode.distance + preNode.deltaAngle(node) * Mathf.Deg2Rad * radius;
                //Debug.Log(">>>>>>>2 distance: " + node.distance);
            }
            listNode = listNode.Next;
        }
        return(nodes);
    }
    private static LinkedList <PBCircleNode> BuildForOne(PBCircle[] circles)
    {
        LinkedList <PBCircleNode> nodes = new LinkedList <PBCircleNode>();
        PBCircle circle = circles[0];

        PBCircleNode node1 = new PBCircleNode(
            circle,
            circle.center + circle.up * circle.radius,
            -circle.right,
            0);

        nodes.AddFirst(node1);

        PBCircleNode node2 = new PBCircleNode(node1);

        node2.angle = 360;
        nodes.AddLast(node2);

        return(nodes);
    }
Esempio n. 8
0
 /// <summary>
 /// 两点间连圆弧
 /// </summary>
 public bool ConnectArc(PBCircleNode nextNode)
 {
     return(nextNode.circle == this.circle);
 }
Esempio n. 9
0
 /// <summary>
 /// 两点间连直线(两圆公切线)
 /// </summary>
 public bool ConnectLine(PBCircleNode nextNode)
 {
     return(nextNode.circle != this.circle);
 }