• Unity制作3D图表组件------扇形图


    上篇有柱状图于折线图的实现。

    这篇主要实现一下柱状图。

    实现方式:把圆环体拆分成一个一个的小长方体,如图(顶视图)绿色部分

    还是继承ChartBase.cs

    上代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 扇形统计图
    /// </summary>
    public class SectorChart : ChartBase
    {
        List<float> tempPointY = new List<float>();
        /// <summary>
        /// 展示动画
        /// </summary>
        public override void ShowAnim()
        {
            for (int i = 0; i < pointsInfos.Count; i++)
            {
                for (int j = 0; j < pointsInfos[i].itemSectorPercent.Length; j++)
                {
                    int tempI = i;
                    int tempJ = j;
    
                    StartCoroutine(DoFloatValue(0, pointsInfos[i].itemSectorPercent[j], 1, (value) =>
                    {
                        pointsInfos[tempI].itemSectorPercent[tempJ] = value;
                    }));
                }
            }
        }
    
    
        public override void CreateMesh()
        {
    
            for (int i = 0; i < pointsInfos.Count; i++)
            {
                if (pointsInfos[i].itemSectorPercent.Length != meshs.Count)
                {
                    DeleteAllItemObjs();
                    GameObject tempParent = new GameObject();
                    tempParent.name = meshName;
                    tempParent.transform.position = Vector3.zero;
                    allChartParentObj.Add(tempParent);
                    for (int j = 0; j < pointsInfos[i].itemSectorPercent.Length; j++)
                    {
                        GameObject itemObj = new GameObject();
                        itemObj.name = meshName + "_Child_" + j.ToString();
                        itemObj.transform.parent = tempParent.transform;
                        Mesh mesh = new Mesh();
                        meshs.Add(mesh);
                        itemObj.AddComponent<MeshFilter>().mesh = mesh;
                        itemObj.AddComponent<MeshRenderer>();
                        itemObj.GetComponent<MeshRenderer>().material = mat;
                        allChartItemObj.Add(itemObj);
                    }
                }
            }
        }
        /// <summary>
        /// 当前这个扇形的起始角度
        /// </summary>
        float pieceAngle = 0;
        /// <summary>
        /// 当前这个扇形的结束角度
        /// </summary>
        float nextAngle = 0;
    
        public override void SetMeshInfo()
        {
            triangles.Clear();
            verticesAddOffset.Clear();
    
            pieceAngle = 0;
            nextAngle = 0;
    
            for (int j = 0; j < pointsInfos[0].itemSectorPercent.Length; j++)
            {
                Vector3[] vertices = GetPointsVector3s(pointsInfos[0], j);
                verticesAddOffset.Add(new PointsInfo(SetVerticesOffset(vertices, pointsInfos[0]), Vector3.one));
                triangles.Add(GetTrianglesVector3s(vertices));
            }
        }
    
    
        /// <summary>
        /// 根据顶点和位移差获取最终位置
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public override Vector3[] SetVerticesOffset(Vector3[] vertices, PointsInfo _points)
        {
    
            Vector3[] tempV3 = new Vector3[vertices.Length];
    
            for (int i = 0; i < vertices.Length; i++)
            {
                tempV3[i] = vertices[i];
    
                tempV3[i] += _points.points[0];
    
            }
    
            return tempV3;
        }
    
    
        /// <summary>
        /// 获取正方体的每个面顶点坐标   (先绘出顶面第一个长方形,再绘制底面第一个长方形,依次连接长方体的面)
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        protected Vector3[] GetPointsVector3s(PointsInfo _points, int index)
        {
    
            List<Vector3> tempPoints = new List<Vector3>();
    
            //立方体初始的点,取内圆心   上表面的一个点
            Vector3 firstUpPoint = new Vector3(_points.size.x * _points.inCirclePercent, -_points.size.y / 2f, 0);
            ///上表面的中心点
            Vector3 centerUp = center + new Vector3(0, _points.size.y / 2f, 0);
    
            if (index == 0)
            {
                pieceAngle = 0;
            }
            else
            {
                pieceAngle += _points.itemSectorPercent[index - 1] * 360f;
            }
    
            nextAngle += _points.itemSectorPercent[index] * 360f;
            float offsetAngle = nextAngle - pieceAngle;
            for (int i = 0; i < _points.sertorCount; i++)
            {
                //立方体上表面多边形点
                List<Vector3> tempUpPoints = new List<Vector3>();
                //立方体下表面多边形点
                List<Vector3> tempDownPoints = new List<Vector3>();
    
                float tempAngle = pieceAngle + (float)(i) / (float)_points.sertorCount * (nextAngle - pieceAngle);
                float tempNextAngle = pieceAngle + (float)(i + 1) / (float)_points.sertorCount * (nextAngle - pieceAngle);
                if (i == 0)
                {
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x * _points.inCirclePercent, tempAngle, offsetAngle * _points.insertValue));
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x, tempAngle, offsetAngle * _points.insertValue));
                }
                else
                {
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x * _points.inCirclePercent, tempAngle));
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x, tempAngle));
                }
                if (i == _points.sertorCount - 1)
                {
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x, tempNextAngle, -offsetAngle * _points.insertValue));
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x * _points.inCirclePercent, tempNextAngle, -offsetAngle * _points.insertValue));
                }
                else
                {
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x, tempNextAngle));
                    tempUpPoints.Add(RotateAroundByPointByDistance(firstUpPoint, centerUp, Vector3.up, _points.size.x * _points.inCirclePercent, tempNextAngle));
                }
    
    
                for (int j = 0; j < tempUpPoints.Count; j++)
                {
                    tempDownPoints.Add(tempUpPoints[j] - new Vector3(0, _points.size.y, 0));
                }
                tempPoints.AddRange(GetAllTrianglesPoint(tempUpPoints, tempDownPoints));
    
            }
    
            return tempPoints.ToArray();
        }
        /// <summary>
        /// 根据上表面下表面的八个顶点确定立方体的所有点位(顺时针排序)
        /// </summary>
        /// <param name="inputUpV3s">上表面的四个点</param>
        /// <param name="inputDownV3s">下表面的四个点</param>
        /// <returns></returns>
        Vector3[] GetAllTrianglesPoint(List<Vector3> inputUpV3s, List<Vector3> inputDownV3s, string ceMian = "Both")
        {
            Vector3[] outPutPoints = new Vector3[24];
    
            //顶面
            for (int i = 0; i < inputUpV3s.Count; i++)
            {
                outPutPoints[i] = inputUpV3s[i];
            }
            //内侧
            outPutPoints[4] = inputUpV3s[0];
            outPutPoints[5] = inputUpV3s[3];
            outPutPoints[6] = inputDownV3s[3];
            outPutPoints[7] = inputDownV3s[0];
    
            //右面
            if (ceMian == "Both" || ceMian == "Right")
            {
                outPutPoints[8] = inputUpV3s[3];
                outPutPoints[9] = inputUpV3s[2];
                outPutPoints[10] = inputDownV3s[2];
                outPutPoints[11] = inputDownV3s[3];
            }
            //外侧
            outPutPoints[12] = inputUpV3s[2];
            outPutPoints[13] = inputUpV3s[1];
            outPutPoints[14] = inputDownV3s[1];
            outPutPoints[15] = inputDownV3s[2];
    
            //左面
            if (ceMian == "Both" || ceMian == "Left")
            {
                outPutPoints[16] = inputUpV3s[1];
                outPutPoints[17] = inputUpV3s[0];
                outPutPoints[18] = inputDownV3s[0];
                outPutPoints[19] = inputDownV3s[1];
            }
    
            //底面
            outPutPoints[20] = inputDownV3s[3];
            outPutPoints[21] = inputDownV3s[2];
            outPutPoints[22] = inputDownV3s[1];
            outPutPoints[23] = inputDownV3s[0];
    
            return outPutPoints;
        }
    
    
        public Vector3 RotateAroundByPointByDistance(Vector3 selfPoint, Vector3 rotatePoint, Vector3 axis, float distance, float angle, float offsetAngle = 0)
        {
            Quaternion q = Quaternion.AngleAxis(angle + offsetAngle, axis);
            Vector3 distanceOffset = Vector3.ProjectOnPlane(Vector3.Normalize(new Vector3((1 - axis.x) * selfPoint.x, (1 - axis.y) * selfPoint.y, (1 - axis.z) * selfPoint.z) - new Vector3((1 - axis.x) * rotatePoint.x, (1 - axis.y) * rotatePoint.y, (1 - axis.z) * rotatePoint.z)), axis) * distance;
            return q * distanceOffset;
        }
    
    }
    
    
    
    public partial class PointsInfo
    {
        /// <summary>
        /// 内圈比例
        /// </summary>
        public float inCirclePercent;
        /// <summary>
        /// 扇形之间的间隔
        /// </summary>
        public float insertValue;
        /// <summary>
        /// 多边形边数
        /// </summary>
        public int sertorCount;
    
        /// <summary>
        /// 每个扇形的百分比
        /// </summary>
        public float[] itemSectorPercent;
        public PointsInfo(Vector3[] _points, Vector3 _size, float _percent, float _insertValue, int _sertorCount, float[] _itemSectorPercent)
        {
            points = _points;
            size = _size;
            inCirclePercent = _percent;
            insertValue = _insertValue;
            sertorCount = _sertorCount;
            itemSectorPercent = _itemSectorPercent;
        }
    }

    工程链接:https://github.com/wtb521thl/ChartTest

  • 相关阅读:
    由asp的一个错误,看语言的不同:asp & java
    chrome 显示图片遇到的问题,与 淘宝图片服务器 缓存 有关系
    asp 调用 vb(activex dll) ,参数传递(传引用)需要注意
    asp <----> vb(com,dll) <---> c 来回的调用,生命在于折腾
    HTTP/1.1 100 Continue
    java 线程栈 & java.lang.StackOverflowError
    硬盘分区的意义
    硬盘性能 & 文件碎片的一些思考
    Java并发——ReentrantLock类源码阅读
    使用Windows的NAT功能
  • 原文地址:https://www.cnblogs.com/yzxhz/p/13039362.html
Copyright © 2020-2023  润新知