unity 用LineRender画四边形并测面积
作为一个菜鸡,这个高中数学题差不多废了我两个上午。。。好了,废话不多说,直接上代码。。。
using System.Collections.Generic;
using UnityEngine; public class DrawAreaLine : MonoBehaviour
{
public bool IsAreaLineOn = false;
private LineRenderer AreaLine;
private List<Vector3> PosList = new List<Vector3>();
private RaycastHit hit;
private Ray ray;
private int num = ;
// Use this for initialization
void Start()
{
AreaLine = transform.Find("Area").GetComponent<LineRenderer>();
AreaLine.material = new Material(Shader.Find("Sprites/Default"));
AreaLine.startColor = Color.blue;
AreaLine.endColor = Color.blue;
AreaLine.startWidth = 0.05f;
AreaLine.endWidth = 0.05f;
AreaLine.numCornerVertices = ;
AreaLine.numCapVertices = ; } // Update is called once per frame
void Update()
{
BeginAreaLine();
} void BeginAreaLine()
{
if (IsAreaLineOn)
{
if (Input.GetMouseButtonDown())
{
if (AreaLine.enabled == false)
{
AreaLine.enabled = true;
}
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Vector3 pos = new Vector3(hit.point.x, hit.point.y, hit.point.z) + new Vector3(, 0.1f, );
//判断是否有相同位置的点
for (int i=; i<PosList.Count;i++)
{
if (PosList[i]==pos)
{
return;
}
}
if (AreaLine.positionCount >= )
{
return;
}
if (AreaLine.positionCount == )
{
//判断第四个点位置,判断能否组成四边形
//判断顺时针还是逆时针
if (IsClockWise() == false)//ABC为逆时针方向
{
//逆时针判断能否画四边形
if (IfCanAntiClock(pos) == false)
{
return;
}
}
if (IsClockWise() == true) //ABC为顺时针方向
{
//顺时针能否画四边形
if(IfCanClick(pos)==false)
{
return;
}
} }
if (hit.collider.name == "PanelCube")
{
num++;
AreaLine.positionCount = num;
AreaLine.SetPosition(num - , pos);
PosList.Add(pos);
if (PosList.Count == )
{
//计算三角形面积
// AreaTriabgle();
print(AreaTriabgle());
}
if (PosList.Count == )
{
//计算四边形面积
//AreaQuadrangle();
print(AreaQuadrangle());
}
}
//print(AreaLine.positionCount);
}
}
else if (Input.GetKeyDown(KeyCode.Delete))
{
DelectLine();
}
return;
}
} /// <summary>
/// 判断逆时针能不能画成四边形
/// </summary>
/// <param name="PosD"></param>
/// <returns>cyt</returns>
bool IfCanAntiClock(Vector3 PosD)
{
//直线一般式表达:(y2-y1)x-(x2-x1)y-x1y2+x2y1=0
bool can = false;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
Vector2 D = new Vector2(PosD.x, PosD.z);
//D在直线AB、AC下方且在BC上方
if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y > )
&& (((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y > ))
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y < ))
{ can = false;
}
//D在AB上方且在BC、AC下方
else if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y < )
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y > )
&& (C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y > )
{ can = false;
}
else
{
print("keyi");
can = true;
}
return can;
} /// <summary>
/// 顺时针能否画成四边形
/// </summary>
/// <param name="posD"></param>
/// <returns>cyt</returns>
bool IfCanClick(Vector3 PosD)
{
//直线一般式表达:(y2-y1)x-(x2-x1)y-x1y2+x2y1=0
bool CanClick = false;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
Vector2 D = new Vector2(PosD.x, PosD.z);
//在AB、AC上方、BC下方,以ac为底边观察的
if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y < )
&& (((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y <))
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y >)
)
{
CanClick = false;
}
//在AC、BC上方,在AB下方
else if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y > )
&& (((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y < ))
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y < )
)
{
CanClick = false;
}
else
{
CanClick = true;
}
return CanClick;
}
/// <summary>
/// 计算三角形面积
/// </summary>
float AreaTriabgle()
{
//点到直线距离d=Mathf.Abs( (A*x0+B*y0+C)/Mathf.Sqrt(A*A+B*B) );
float area;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
//AC长度(底边长)
float AC = Vector2.Distance(A, C);
//B到AC的距离(AC边的高)
float h = Mathf.Abs(((C.y - A.y) * B.x - (C.x - A.x) * B.y - A.x * C.y + C.x * A.y) / Mathf.Sqrt((C.y - A.y) * (C.y - A.y) + (C.x - A.x) * (C.x - A.x)));
area = AC * h / ;
return area;
}
/// <summary>
/// 计算四边形面积
/// </summary>
float AreaQuadrangle()
{
float area;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
Vector2 D = new Vector2(PosList[].x, PosList[].z);
//AC长度(底边长)
float AC = Vector2.Distance(A, C);
//B到AC的距离(AC边的高)
float hB = Mathf.Abs(((C.y - A.y) * B.x - (C.x - A.x) * B.y - A.x * C.y + C.x * A.y) / Mathf.Sqrt((C.y - A.y) * (C.y - A.y) + (C.x - A.x) * (C.x - A.x)));
float hD = Mathf.Abs(((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y) / Mathf.Sqrt((C.y - A.y) * (C.y - A.y) + (C.x - A.x) * (C.x - A.x)));
//判断是否是凹四边形
if (IsConcaveQuadrilateral() == true)
{
area = AC * Mathf.Abs((hB - hD)) / ;
}
else
area = AC * (hB + hD) / ;
return area;
}
/// <summary>
/// 删除线
/// </summary>
void DelectLine()
{
num = ;
//lineRenderer.SetVertexCount(LengthOfLineRenderer);
AreaLine.positionCount = num;
PosList.Clear();
AreaLine.enabled = false;
} /// <summary>
/// 判断是否是凹四边形
/// </summary>
/// <returns>cyt</returns>
bool IsConcaveQuadrilateral()
{
bool Concave = false;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
Vector2 D = new Vector2(PosList[].x, PosList[].z);
//逆时针状况
//两种情况,一种是D在三角形ABC内部,另一种是D在直线AB跟BC下方(以ab为底边观察)
if (IsClockWise()==false)
{
if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y < )
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y < )
&& ((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y > ))
{
Concave = true;
}
else if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y > )
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y > ))
{
Concave = true;
}
else
{
Concave = false;
}
}
//顺时针
//两种情况,在三角形abc内部和在AB上、AC下
if (IsClockWise()==true)
{
if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y > )
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y > )
&& ((C.y - A.y) * D.x - (C.x - A.x) * D.y - A.x * C.y + C.x * A.y < )
)
{
Concave = true;
}
else if (((B.y - A.y) * D.x - (B.x - A.x) * D.y - A.x * B.y + B.x * A.y < )
&& ((C.y - B.y) * D.x - (C.x - B.x) * D.y - B.x * C.y + C.x * B.y <
))
{
Concave = true;
}
else
{
Concave = false;
}
}
return Concave;
}
/// <summary>
/// 判断是否为顺时针,以ac为底边观察
/// </summary>
/// <param>cyt</param>
/// <returns></returns>
bool IsClockWise()
{
bool IsClock = false;
Vector2 A = new Vector2(PosList[].x, PosList[].z);
Vector2 B = new Vector2(PosList[].x, PosList[].z);
Vector2 C = new Vector2(PosList[].x, PosList[].z);
//如果B在A的右边,C在AB上方为逆时针
if (B.x>=A.x)
{
if ((B.y - A.y) * C.x - (B.x - A.x) * C.y - A.x * B.y + B.x * A.y < )
{
IsClock = false;
}
else
{
IsClock = true;
}
}
//如果B在A的左边,C在AB下方为逆时针
if (B.x<A.x)
{
if ((B.y - A.y) * C.x - (B.x - A.x) * C.y - A.x * B.y + B.x * A.y < )
{
IsClock = false;
}
else
{
IsClock = true;
}
}
return IsClock;
}
}
注释还算比较清楚,各种情况都判断了,也是想过用向量来判断能否实现,发现不好使....
AreaLine = transform.Find("Area").GetComponent<LineRenderer>();这个跟
if (hit.collider.name == "PanelCube")这两句需要自己在场景中设置一下,然后运行的时候把脚本的
IsAreaLineOn变量设为true就能画了...按下delect可以删除画的四边形,然后在点击就可以继续画了。
实现思路的话首先将所有的点加入一个集合中(每次输入都排除了重复的点),然后根据集合里的的前三个点判断画的三角形是顺时针画的三角形还是逆时针画的三角形,
然后在根据是顺时针和逆时针分别判断第四个点的位置,判断第四个点在三角形三条边所在直线的位置判断能否画成四边形。
计算面积的话是先判断了顺时针话还是逆时针画,然后分别判断画的是凸四边形还是凹四边形,然后在计算面积。
哎。。。生无可恋。。。。
希望能帮到人,若需转载请标明出处,谢谢....
unity 用LineRender画四边形并测面积的更多相关文章
- Delphi下OpenGL2d绘图(04)-画四边形
一.前言 画四边形基本上与前几遍文字代码是相同.区别在于glBegin()的参数“GL_QUADS”.绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 ...
- 百度地图API画多边型,测面积
效果: 脚本: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- Unity之屏幕画线
using UnityEngine;using System.Collections; public class DrawRectangle : MonoBehaviour { public Colo ...
- Unity中用Mesh画一个圆环
Probuider 前几天在做一个小项目的时候,用到了Unity自带的一个包ProBuilder其中的Arch生成1/4圆. 挺好玩的,可以在直接Unity中根据需要用Mesh定制生成图形,而不用建模 ...
- html5画四边形
<canvas id='test02'></canvas> <script> var canvas = document.getElementById('test0 ...
- Unity使用GL画线
脚本需挂在相机上,如果你的脚本,编辑器报错了,Matrix stack full depth reached,加上这个方法试试GL.LoadPixelMatrix(); using System.Co ...
- Unity中用Mesh画一个圆环(二)
中目标-生成完整面 在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了. 我们把之前生成的面当作顶面,接着我们来生成底面. 还记得前面说过\(\color{#1E90FF}{D ...
- ArcGIS JS 学习笔记1 用ArcGIS JS 实现仿百度地图的距离量测和面积量测
一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不 ...
- ArcGIS Engine开发之量测功能
1.距离测量 距离测量时,片段长度通过两点之间距离计算得到,全部长度通过片段长度的和计算得到.主要用到INewLineFeedback和IScreenDisplay两个接口. 1)INewLineFe ...
随机推荐
- g-api notes
目录 Q: What is GOrigin? What the meaning of parameters GMat(const GNode &n, std::size_t out) Q: h ...
- jetty源码下载
jetty下载地址:https://www.eclipse.org/jetty/download.html Release 9.4.20.v20190813 .zip .tgz api ...
- RocketMQ、Kafka、RabbitMQ的对比
RocketMQ 相比于 RabbitMQ.Kafka 具有主要优势特性有: 支持事务型消息(消息发送和DB操作保持两方的最终一致性,RabbitMQ 和Kafka 不支持) 支持结合 RocketM ...
- 深入解读阿里云Redis开发规范
Key命名设计:可读性.可管理性.简介性 规范建议使用冒号即:进行分割拼接,因为很多Redis客户端是根据冒号分类的.比如有几个Key:apps:app:1.apps:app:2和apps:app:3 ...
- ShenZhenXiaoLengHuanYou Technology Co.,Ltd 技术支持网站
本网页为ShenZhenXiaoLengHuanYou Technology Co.,Ltd 团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:2535510006 邮箱: ...
- word中的总页数不包括封面、目录
删除分隔符:选项-显示-显示所有格式标记
- NuxtJS实战,一个博客系统
前言 这个项目诞生于17年5月,距今已有两年多了,在这两年期间经历了很多变更,从简单到复杂,又从复杂到简单,并且以后一直会保持这种简单状态.最近迎来了一次更新,因此特意分享一下.虽然只有我一个人使用( ...
- Angular2 输入完成后触发函数
(blur)="keySearch($event)" ,鼠标点击其他地方触发 keySearch(e): void { var dom = $(e.target); var key ...
- MySQL ALTER TABLE语法
先看一下定义(密密麻麻) ALTER TABLE tbl_name [alter_specification [, alter_specification] ...] [partition_optio ...
- RWMutex:共享/专有的递归互斥锁
具有共享/独占访问权限,且具有升级/降级功能的互斥锁 介绍 我的目标是创建可以充当读/写锁定机制的对象.任何线程都可以锁定它以进行读取,但是只有一个线程可以锁定它以进行写入.在写入线程释放它之前,所有 ...