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 ...
随机推荐
- i系列标准-互联网周刊
原文:http://www.enet.com.cn/article/2019/0429/A20190429062899.html 传统意义上的规模.现代意义上的工具时代感.永远不会改变的最高意义上的使 ...
- Egg.js运行环境配置场景
没有NODE_ENV和EGG_SERVER_ENV环境变量的场景 执行npm run dev,默认读取config.default.js. 执行npm run start,默认读取config.pro ...
- 【HBase】HBase 单机版安装及使用
HBase介绍 HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”.就像Bigtable利用了 ...
- 在Windows平台下使用Gitblit搭建Git服务器图文解说
Windows平台下Git服务器搭建 一.java环境变量的设置 下载jdk并配置jdk的环境变量,JAVA_HOME,CLASSPATH以及PATH,最后在DOS窗口输入java -version检 ...
- Manytasking optimization MATP
Manytasking Jmetal代码反向解析1_MATP测试函数集 觉得有用的话,欢迎一起讨论相互学习~Follow Me 这是我在写Manytask optimization时的笔记,代码地址可 ...
- Transaction-Mybatis源码
github地址:https://github.com/dchack/Mybatis-source-code-learn (欢迎star) TransactionFactory 官方文档: 在 MyB ...
- C++ 右值引用与move
C++ 右值引用与move 右值引用 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的持久化对象,右值是指表达式结束时就不再存在的临时对象. 所有的具名变量或者对象都是左值 ...
- dubbo 报错问题记录:may be version or group mismatch
凌晨时候钉钉告警群里一直大量报错: 接口异常报警:项目:mp-rest,域名:inside-mp.01zhuanche.com,IP:10.30.3.60,接口地址:/api/v3/driverLog ...
- 如何在jupyter中使用Python2和Python3
首先通过 pip2 install ipython notebook pip3 install ipython notebook 分别安装ipython notebook,安装命令还是推荐使用国内的豆 ...
- npm 创建vue项目(指定目录进行创建)
1.先安装node,js和npm 检验mpm 和node的方式是 npm -v / node -v 2.安装最新版本 npm install @vue/cli -g 意外安装老版本的是代码 npm ...