162 lines
5.6 KiB
C#
162 lines
5.6 KiB
C#
using CesiumForUnity;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class PolygonMeasureGroup : MeasureGroup
|
|
{
|
|
private PolygonMeasureGroupInfoPopup polygonMeasureGroupInfoPopup;
|
|
private float baseCloseDistance = 10f;
|
|
|
|
public override void AddPoint(Vector3 pos)
|
|
{
|
|
if (!polygonMeasureGroupInfoPopup)
|
|
{
|
|
polygonMeasureGroupInfoPopup = Instantiate(polygonInfoPopupPrefab).GetComponent<PolygonMeasureGroupInfoPopup>();
|
|
polygonMeasureGroupInfoPopup.InitUI(infoPopupRoot);
|
|
polygonMeasureGroupInfoPopup.transform.position = pos + new Vector3(20, 0, 20);
|
|
}
|
|
|
|
if (points.Count >= 3 && Vector3.Distance(points[0], pos) < baseCloseDistance)
|
|
{
|
|
ClosePolygon();
|
|
return;
|
|
}
|
|
|
|
points.Add(pos);
|
|
line.positionCount = points.Count;
|
|
line.SetPosition(points.Count - 1, pos);
|
|
|
|
GameObject label = Instantiate(labelPrefab, pos, Quaternion.identity, labelRoot);
|
|
labels.Add(label);
|
|
|
|
if (points.Count >= 2)
|
|
{
|
|
Vector3 a = points[points.Count - 2];
|
|
Vector3 b = points[points.Count - 1];
|
|
|
|
double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, a);
|
|
double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, b);
|
|
|
|
double dist = GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);
|
|
totalDistance += dist;
|
|
}
|
|
|
|
UpdateInfo();
|
|
}
|
|
|
|
private void ClosePolygon()
|
|
{
|
|
line.positionCount = points.Count + 1;
|
|
for (int i = 0; i < points.Count; i++)
|
|
line.SetPosition(i, points[i]);
|
|
line.SetPosition(points.Count, points[0]);
|
|
|
|
double3[] llhs = new double3[points.Count];
|
|
for (int i = 0; i < points.Count; i++)
|
|
llhs[i] = GeoUtils.GetLonLatHeight(cesiumGeoreference, points[i]);
|
|
|
|
double totalDistance = 0;
|
|
for (int i = 0; i < points.Count; i++)
|
|
{
|
|
int j = (i + 1) % points.Count;
|
|
double dist = GeoUtils.Haversine(llhs[i].x, llhs[i].y, llhs[j].x, llhs[j].y);
|
|
totalDistance += dist;
|
|
|
|
Vector3 mid = (points[i] + points[j]) * 0.5f;
|
|
labels[i].transform.position = mid;
|
|
labels[i].GetComponentInChildren<TextMeshProUGUI>().text = $"{dist:F1} m";
|
|
}
|
|
|
|
double area = GetPolygonArea();
|
|
polygonMeasureGroupInfoPopup.UpdateInfo("(¾øÀ½)", llhs[0].x, llhs[0].y, totalDistance, area);
|
|
|
|
deleteButton = Instantiate(deleteButtonPrefab, points[0], Quaternion.identity, infoPopupRoot);
|
|
deleteButton.GetComponentInChildren<Button>().onClick.AddListener(() => DestroyAll());
|
|
deleteButton.transform.position = points[0] + new Vector3(-20, 0, 20);
|
|
|
|
FindAnyObjectByType<MeasureManager>().isMeasuring = false;
|
|
}
|
|
|
|
private void UpdateInfo()
|
|
{
|
|
if (polygonMeasureGroupInfoPopup == null) return;
|
|
|
|
double totalDistance = 0;
|
|
for (int i = 0; i < points.Count - 1; i++)
|
|
{
|
|
double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, points[i]);
|
|
double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, points[i + 1]);
|
|
totalDistance += GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);
|
|
}
|
|
|
|
double3 llh_last = GeoUtils.GetLonLatHeight(cesiumGeoreference, points[points.Count - 1]);
|
|
polygonMeasureGroupInfoPopup.UpdateInfo("(¾øÀ½)", llh_last.x, llh_last.y, totalDistance, 0);
|
|
}
|
|
|
|
public override void EndMeasure()
|
|
{
|
|
if (line == null) return;
|
|
DestroyAll();
|
|
}
|
|
|
|
public override void DestroyAll()
|
|
{
|
|
base.DestroyAll();
|
|
if (polygonMeasureGroupInfoPopup)
|
|
Destroy(polygonMeasureGroupInfoPopup.gameObject);
|
|
Destroy(this);
|
|
}
|
|
|
|
public override void LateUpdate()
|
|
{
|
|
base.LateUpdate();
|
|
|
|
if (polygonMeasureGroupInfoPopup)
|
|
{
|
|
polygonMeasureGroupInfoPopup.transform.LookAt(polygonMeasureGroupInfoPopup.transform.position + cam.transform.forward);
|
|
float heightDiff = Mathf.Abs(cam.transform.position.y - polygonMeasureGroupInfoPopup.transform.position.y);
|
|
polygonMeasureGroupInfoPopup.transform.localScale = Vector3.one * (heightDiff * lineScaleMultiplier);
|
|
}
|
|
}
|
|
|
|
public override void UpdatePreviewLine(Vector3 mousePos)
|
|
{
|
|
if (points.Count == 0 || line == null) return;
|
|
|
|
if (line.positionCount == points.Count)
|
|
line.positionCount++;
|
|
|
|
line.SetPosition(line.positionCount - 1, mousePos);
|
|
|
|
Vector3 last = points[points.Count - 1];
|
|
Vector3 mid = (last + mousePos) * 0.5f;
|
|
labels[labels.Count - 1].transform.position = mid;
|
|
|
|
double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, last);
|
|
double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, mousePos);
|
|
double dist = GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);
|
|
|
|
labels[labels.Count - 1].GetComponentInChildren<TextMeshProUGUI>().text = $"{dist:F1} m";
|
|
|
|
double previewTotal = totalDistance + dist;
|
|
polygonMeasureGroupInfoPopup?.UpdateInfo("(¾øÀ½)", llh_b.x, llh_b.y, previewTotal, 0);
|
|
}
|
|
|
|
private double GetPolygonArea()
|
|
{
|
|
double sum1 = 0, sum2 = 0;
|
|
for (int i = 0; i < points.Count - 1; i++)
|
|
{
|
|
sum1 += points[i].x * points[i + 1].z;
|
|
sum2 += points[i + 1].x * points[i].z;
|
|
}
|
|
sum1 += points[points.Count - 1].x * points[0].z;
|
|
sum2 += points[0].x * points[points.Count - 1].z;
|
|
return Math.Abs((sum1 - sum2) / 2.0);
|
|
}
|
|
}
|