using System;
using System.Collections.Generic;
using UnityEngine;
using XUGL;
namespace XCharts.Runtime
{
///
/// View control component in 3D coordinate system.
/// ||3D视角控制组件。
///
[Since("v3.11.0")]
[Serializable]
public class ViewControl : ChildComponent
{
[SerializeField][Range(-90, 180)] private float m_Alpha = 90f;
[SerializeField][Range(-90, 90)] private float m_Beta = 55f;
///
/// The angle of the view in the x-z plane.
/// ||视角在x-z平面的角度。
///
public float alpha
{
get { return m_Alpha; }
set { if (PropertyUtil.SetStruct(ref m_Alpha, value)) SetVerticesDirty(); }
}
///
/// The angle of the view in the y-z plane.
/// ||视角在y-z平面的角度。
///
public float beta
{
get { return m_Beta; }
set { if (PropertyUtil.SetStruct(ref m_Beta, value)) SetVerticesDirty(); }
}
}
///
/// Grid component.
/// ||Drawing grid in rectangular coordinate. Line chart, bar chart, and scatter chart can be drawn in grid.
/// ||3D网格组件。
/// 3D直角坐标系内绘图网格。可以在网格上绘制3D折线图,3D柱状图,3D散点图。
///
[Serializable]
[ComponentHandler(typeof(GridCoord3DHandler), true)]
public class GridCoord3D : CoordSystem, IUpdateRuntimeData, ISerieContainer
{
[SerializeField] private bool m_Show = true;
[SerializeField] private float m_Left = 0.15f;
[SerializeField] private float m_Right = 0.2f;
[SerializeField] private float m_Top = 0.3f;
[SerializeField] private float m_Bottom = 0.15f;
[SerializeField] private bool m_ShowBorder = false;
[SerializeField] private float m_BoxWidth = 0.55f;
[SerializeField] private float m_BoxHeight = 0.4f;
[SerializeField] private float m_BoxDepth = 0.2f;
[SerializeField] private bool m_XYExchanged = false;
[SerializeField] private ViewControl m_ViewControl = new ViewControl();
public GridCoord3DContext context = new GridCoord3DContext();
///
/// Whether to show the grid in rectangular coordinate.
/// ||是否显示直角坐标系网格。
///
public bool show
{
get { return m_Show; }
set { if (PropertyUtil.SetStruct(ref m_Show, value)) SetVerticesDirty(); }
}
///
/// Distance between grid component and the left side of the container.
/// ||grid 组件离容器左侧的距离。
///
public float left
{
get { return m_Left; }
set { if (PropertyUtil.SetStruct(ref m_Left, value)) SetAllDirty(); }
}
///
/// Distance between grid component and the right side of the container.
/// ||grid 组件离容器右侧的距离。
///
public float right
{
get { return m_Right; }
set { if (PropertyUtil.SetStruct(ref m_Right, value)) SetAllDirty(); }
}
///
/// Distance between grid component and the top side of the container.
/// ||grid 组件离容器上侧的距离。
///
public float top
{
get { return m_Top; }
set { if (PropertyUtil.SetStruct(ref m_Top, value)) SetAllDirty(); }
}
///
/// Distance between grid component and the bottom side of the container.
/// ||grid 组件离容器下侧的距离。
///
public float bottom
{
get { return m_Bottom; }
set { if (PropertyUtil.SetStruct(ref m_Bottom, value)) SetAllDirty(); }
}
///
/// Whether to show the grid border.
/// ||是否显示网格边框。
///
public bool showBorder
{
get { return m_ShowBorder; }
set { if (PropertyUtil.SetStruct(ref m_ShowBorder, value)) SetVerticesDirty(); }
}
///
/// The width of the box in the coordinate system.
/// ||坐标系的宽度。
///
public float boxWidth
{
get { return m_BoxWidth; }
set { if (PropertyUtil.SetStruct(ref m_BoxWidth, value)) SetVerticesDirty(); }
}
///
/// The height of the box in the coordinate system.
/// ||坐标系的高度。
///
public float boxHeight
{
get { return m_BoxHeight; }
set { if (PropertyUtil.SetStruct(ref m_BoxHeight, value)) SetVerticesDirty(); }
}
///
/// The depth of the box in the coordinate system.
/// ||坐标系的深度。
///
public float boxDepth
{
get { return m_BoxDepth; }
set { if (PropertyUtil.SetStruct(ref m_BoxDepth, value)) SetVerticesDirty(); }
}
///
/// Whether to exchange the x and y axes.
/// ||是否交换x和y轴。
///
public bool xyExchanged
{
get { return m_XYExchanged; }
set { if (PropertyUtil.SetStruct(ref m_XYExchanged, value)) SetVerticesDirty(); }
}
///
/// View control component in 3D coordinate system.
/// ||3D视角控制组件。
///
public ViewControl viewControl
{
get { return m_ViewControl; }
//set { if (PropertyUtil.SetClass(ref m_ViewControl, value)) SetVerticesDirty(); }
}
public void UpdateRuntimeData(BaseChart chart)
{
var chartX = chart.chartX;
var chartY = chart.chartY;
var chartWidth = chart.chartWidth;
var chartHeight = chart.chartHeight;
var actualLeft = left <= 1 ? left * chartWidth : left;
var actualBottom = bottom <= 1 ? bottom * chartHeight : bottom;
var actualBoxWidth = m_BoxWidth <= 1 ? m_BoxWidth * chartWidth : m_BoxWidth;
var actualBoxHeight = m_BoxHeight <= 1 ? m_BoxHeight * chartHeight : m_BoxHeight;
var actualBoxDepth = m_BoxDepth <= 1 ? m_BoxDepth * chartWidth : m_BoxDepth;
context.x = chartX + actualLeft;
context.y = chartY + actualBottom;
context.pointA.x = context.x;
context.pointA.y = context.y;
var angle = m_ViewControl.alpha * Mathf.Deg2Rad;
context.pointD.x = context.x + actualBoxWidth * Mathf.Sin(angle);
context.pointD.y = context.y - actualBoxWidth * Mathf.Cos(angle);
angle = (90 - m_ViewControl.beta) * Mathf.Deg2Rad;
context.pointB.x = context.x + actualBoxDepth * Mathf.Cos(angle);
context.pointB.y = context.y + actualBoxDepth * Mathf.Sin(angle);
context.pointC = context.pointB + (context.pointD - context.pointA);
context.pointE.x = context.pointA.x;
context.pointE.y = context.pointA.y + actualBoxHeight;
var diff = context.pointE - context.pointA;
context.pointF = context.pointB + diff;
context.pointG = context.pointC + diff;
context.pointH = context.pointD + diff;
var minX = Mathf.Min(context.pointA.x, context.pointB.x, context.pointC.x, context.pointD.x, context.pointE.x, context.pointF.x, context.pointG.x, context.pointH.x);
var minY = Mathf.Min(context.pointA.y, context.pointB.y, context.pointC.y, context.pointD.y, context.pointE.y, context.pointF.y, context.pointG.y, context.pointH.y);
var maxX = Mathf.Max(context.pointA.x, context.pointB.x, context.pointC.x, context.pointD.x, context.pointE.x, context.pointF.x, context.pointG.x, context.pointH.x);
var maxY = Mathf.Max(context.pointA.y, context.pointB.y, context.pointC.y, context.pointD.y, context.pointE.y, context.pointF.y, context.pointG.y, context.pointH.y);
context.maxRect.x = minX;
context.maxRect.y = minY;
context.maxRect.width = maxX - minX;
context.maxRect.height = maxY - minY;
}
///
/// The opening of the coordinate system faces to the left.
/// 坐标系开口朝向左边。
///
///
public bool IsLeft()
{
return context.pointB.x < context.pointA.x;
}
///
/// Whether the pointer is in the grid.
/// ||指针是否在网格内。
///
///
public bool IsPointerEnter()
{
return context.isPointerEnter;
}
///
/// Whether the given position is in the grid.
/// ||给定的位置是否在网格内。
///
///
///
public bool Contains(Vector3 pos)
{
if (!context.maxRect.Contains(pos)) return false;
if (UGLHelper.IsPointInPolygon(pos, context.pointA, context.pointB, context.pointC, context.pointD)) return true;
if (UGLHelper.IsPointInPolygon(pos, context.pointB, context.pointF, context.pointG, context.pointC)) return true;
if (IsLeft())
if (UGLHelper.IsPointInPolygon(pos, context.pointC, context.pointG, context.pointH, context.pointD)) return true;
else
if (UGLHelper.IsPointInPolygon(pos, context.pointA, context.pointE, context.pointF, context.pointB)) return true;
return false;
}
///
/// Clamp the position of pos to the grid.
/// ||将位置限制在网格内。
///
///
public void Clamp(ref Vector3 pos)
{
//TODO:
}
///
/// Determines whether a given line segment will not intersect the Grid boundary at all.
/// ||判断给定的线段是否与Grid边界是否完全不会相交。
///
///
///
///
public bool NotAnyIntersect(Vector3 sp, Vector3 ep)
{
//TODO:
return false;
}
}
}