using sam; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class HeightVariableVisualizer : MonoBehaviour { public MeshFilter meshFilter; public MeshFilter meshFilter2D; public float planeElevation = 5000.0f; public float scaleFactor = 1000.0f; public float scaleFactor2D = 100.0f; public Camera cam2d; public HeightVariableScrollRect scrollrect; Satellite satellite; float curzoom = float.MinValue; HeightVariableSubsession hvs; ProductData data; List latStopList, lonStopList, altBottomList, altTopList; List durationList; [HideInInspector] public List verts; [HideInInspector] public List verts2d; [HideInInspector] public List[] vertsPar; [HideInInspector] public bool useExtrusion = false; GameObject parGO; float maxt; void Awake() { hvs = GetComponentInParent(); scrollrect.onValueChanged.AddListener(OnScrollRectValueChanged); var cfg = exprivia.GlobalDictionary.GetValue("SatelliteDataTypeConfig") as SatelliteHeightDataConfig; Debug.Log($"tle history filename = '{cfg.tleHistoryFilename}' - satellite id = '{cfg.satelliteId}'"); satellite = new Satellite(cfg.tleHistoryFilename, cfg.satelliteId); } public void OnProductSelected(ProductData pd) { data = pd; ProductUserData ud = data.profile.GetUserData("LatStop"); latStopList = (data.userData[ud.fieldIndex] as List); ud = data.profile.GetUserData("LonStop"); lonStopList = (data.userData[ud.fieldIndex] as List); ud = data.profile.GetUserData("AltBottom"); altBottomList = (data.userData[ud.fieldIndex] as List); ud = data.profile.GetUserData("AltTop"); altTopList = (data.userData[ud.fieldIndex] as List); ud = data.profile.GetUserData("DeltaSeconds"); durationList = (data.userData[ud.fieldIndex] as List); } public void OnVariableSelected(int vi) { GenerateMeshes(); } public void OnExtrusionToggleValueChanged(bool newUseExtrusion) { if (newUseExtrusion != useExtrusion) { useExtrusion = newUseExtrusion; Debug.Log($"EXTRUSION TOGGLE VALUE NOW {useExtrusion}"); GenerateMeshes(); } } void GenerateMeshes() { if (parGO != null) GameObject.Destroy(parGO); if (useExtrusion) GenerateExtrudedMeshes(); else GenerateCanonicalMeshes(); } void FixDataPointZeroWidth() { float minTime = 2.25f; foreach (var dp1 in data.dataPoints) { if (latStopList[dp1.dataPointIndex] == dp1.latitude || lonStopList[dp1.dataPointIndex] == dp1.longitude) { Vector3 lonLatHgt1 = Mathf.Rad2Deg * satellite.GetPositionGeoCoordinates(dp1.time); Vector3 lonLatHgt2 = Mathf.Rad2Deg * satellite.GetPositionGeoCoordinates(dp1.time.AddSeconds(minTime)); Vector3 dLonLatHgt = lonLatHgt2 - lonLatHgt1; lonStopList[dp1.dataPointIndex] = dLonLatHgt.x + dp1.longitude; latStopList[dp1.dataPointIndex] = dLonLatHgt.y + dp1.latitude; } } } void GenerateCanonicalMeshes() { Debug.Log("GenerateCanonicalMeshes"); var mesh = new Mesh(); mesh.name = hvs.prodvar.name + "(3d)"; var mesh2d = new Mesh(); mesh2d.name = hvs.prodvar.name + "(2d)"; verts = new List(); verts2d = new List(); List colors = new List(); List inds = new List(); float minAlt = float.MaxValue; float maxAlt = float.MinValue; FixDataPointZeroWidth(); foreach (var dp in data.dataPoints) { float lonStart = dp.longitude; float latStart = dp.latitude; float lonEnd = lonStopList[dp.dataPointIndex]; float latEnd = latStopList[dp.dataPointIndex]; //if (latEnd == latStart) //{ // latEnd = latStart; // lonEnd = lonStart; //} float altBot = altBottomList[dp.dataPointIndex]; float altTop = altTopList[dp.dataPointIndex]; if (altBot < minAlt) minAlt = altBot; if (altTop > maxAlt) maxAlt = altTop; altBot *= scaleFactor; altTop *= scaleFactor; Vector3 bl = new Vector3(lonStart, latStart, planeElevation + altBot); Vector3 br = new Vector3(lonEnd, latEnd, planeElevation + altBot); Vector3 tl = new Vector3(lonStart, latStart, planeElevation + altTop); Vector3 tr = new Vector3(lonEnd, latEnd, planeElevation + altTop); bl = Utils.DegLonLatHgtToXYZ(bl, true); br = Utils.DegLonLatHgtToXYZ(br, true); tl = Utils.DegLonLatHgtToXYZ(tl, true); tr = Utils.DegLonLatHgtToXYZ(tr, true); Color col = hvs.GetDataPointColor(dp); int vi = verts.Count; verts.Add(tl); verts.Add(tr); verts.Add(bl); verts.Add(br); colors.Add(col); colors.Add(col); colors.Add(col); colors.Add(col); inds.Add(vi); inds.Add(vi + 1); inds.Add(vi + 2); inds.Add(vi + 2); inds.Add(vi + 1); inds.Add(vi + 3); } float altRange = (maxAlt - minAlt); float altScalar = altRange / scaleFactor2D; int n = data.dataPoints.Count; DateTime firstTime = (n > 0) ? data.dataPoints[0].time : DateTime.Now; maxt = float.MinValue; for (int i = 0; i < n; i++) { ProductDataPoint dp = data.dataPoints[i]; float l = (float)(dp.time - firstTime).TotalSeconds; float r = l + durationList[i]; float b = altBottomList[dp.dataPointIndex]; float t = altTopList[dp.dataPointIndex]; if (r > maxt) maxt = r; b = (b - minAlt) / altScalar; t = (t - minAlt) / altScalar; Vector3 bl = new Vector3(l, b, 0.0f); Vector3 br = new Vector3(r, b, 0.0f); Vector3 tl = new Vector3(l, t, 0.0f); Vector3 tr = new Vector3(r, t, 0.0f); verts2d.Add(tl); verts2d.Add(tr); verts2d.Add(bl); verts2d.Add(br); } float numsecs = (float)(data.nominalEndTime - data.nominalStartTime).TotalSeconds; Debug.Log($"MAX TIME: {maxt} nominal duration: {numsecs}"); scrollrect.ResizeContent(maxt, scaleFactor2D); mesh.vertices = verts.ToArray(); mesh.colors = colors.ToArray(); mesh.SetIndices(inds.ToArray(), MeshTopology.Triangles, 0, true); meshFilter.sharedMesh = mesh; mesh2d.vertices = verts2d.ToArray(); mesh2d.colors = colors.ToArray(); mesh2d.SetIndices(inds.ToArray(), MeshTopology.Triangles, 0, true); meshFilter2D.sharedMesh = mesh2d; meshFilter2D.gameObject.AddComponent(); } void GenerateExtrudedMeshes() { Debug.Log("GenerateExtrudedMeshes"); var mesh = new Mesh(); mesh.name = hvs.prodvar.name + "(3d)"; //var meshArrows = new Mesh(); //meshArrows.name = hvs.prodvar.name + "(arrows 3d)"; Mesh[] meshPar = { new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh() }; for (int jjj = 0; jjj < 6; jjj++) meshPar[jjj].name = hvs.prodvar.name + jjj.ToString() + "(Par 3d)"; var mesh2d = new Mesh(); mesh2d.name = hvs.prodvar.name + "(2d)"; verts = new List(); //List vertsArrows = new List(); vertsPar = new List[] { new List(), new List(), new List(), new List(), new List(), new List() }; verts2d = new List(); List colors = new List(); //List colorsArrows = new List(); List[] colorsPar = { new List(), new List(), new List(), new List(), new List(), new List() }; List inds = new List(); //List indsArrows = new List(); List[] indsPar = { new List(), new List(), new List(), new List(), new List(), new List() }; List inds2d = new List(); float minAlt = float.MaxValue; float maxAlt = float.MinValue; foreach (var dp in data.dataPoints) { float lonStart = dp.longitude; float latStart = dp.latitude; float lonEnd = lonStopList[dp.dataPointIndex]; float latEnd = latStopList[dp.dataPointIndex]; //if (latEnd == latStart) //{ // latEnd = latStart; // lonEnd = lonStart; //} float altBot = altBottomList[dp.dataPointIndex]; float altTop = altTopList[dp.dataPointIndex]; if (altBot < minAlt) minAlt = altBot; if (altTop > maxAlt) maxAlt = altTop; altBot *= scaleFactor; altTop *= scaleFactor; Vector3 bl = new Vector3(lonStart, latStart, planeElevation + altBot); Vector3 br = new Vector3(lonEnd, latEnd, planeElevation + altBot); Vector3 tl = new Vector3(lonStart, latStart, planeElevation + altTop); Vector3 tr = new Vector3(lonEnd, latEnd, planeElevation + altTop); bl = Utils.DegLonLatHgtToXYZ(bl, true); br = Utils.DegLonLatHgtToXYZ(br, true); tl = Utils.DegLonLatHgtToXYZ(tl, true); tr = Utils.DegLonLatHgtToXYZ(tr, true); Color col = hvs.GetDataPointColor(dp); int vi = verts.Count; //int viArrows = vertsArrows.Count; int[] viPar = { vertsPar[0].Count, vertsPar[1].Count, vertsPar[2].Count, vertsPar[3].Count, vertsPar[4].Count, vertsPar[5].Count }; float val = 0; if (dp.varValid[hvs.variableIndex]) { val = dp.variables[hvs.variableIndex]; } float fff = 0.1f; Vector3 arrowTail = (bl + tr) * 0.5f; //Vector3 normal = -Vector3.Cross(br - bl, tl - bl).normalized; Vector3 normal = -Vector3.Cross((br - bl).normalized, (tl - bl).normalized).normalized; Vector3 nnn = normal * val / (2 * hvs.lutRange); Vector3 arrowVersus = nnn * fff; Vector3 arrowHead = arrowTail + arrowVersus; //vertsArrows.Add(arrowTail); //vertsArrows.Add(arrowHead); //float sss = 0.01f; //if (Mathf.Abs(val / (2 * hvs.LutRange) * fff) - sss < 0) // sss = 0; //Vector3 p000 = bl + arrowVersus - normal * sss; //Vector3 p100 = br + arrowVersus - normal * sss; //Vector3 p110 = tr + arrowVersus - normal * sss; //Vector3 p010 = tl + arrowVersus - normal * sss; Vector3 p000 = bl; Vector3 p100 = br; Vector3 p110 = tr; Vector3 p010 = tl; //Vector3 center = (bl + tr) * 0.5f; //Vector3 p001 = center + arrowVersus; //Vector3 p101 = center + arrowVersus; //Vector3 p111 = center + arrowVersus; //Vector3 p011 = center + arrowVersus; Vector3 p001 = bl + arrowVersus; Vector3 p101 = br + arrowVersus; Vector3 p111 = tr + arrowVersus; Vector3 p011 = tl + arrowVersus; vertsPar[0].Add(p010); vertsPar[1].Add(p011); vertsPar[2].Add(p001); vertsPar[0].Add(p110); vertsPar[1].Add(p111); vertsPar[2].Add(p101); vertsPar[0].Add(p000); vertsPar[1].Add(p001); vertsPar[2].Add(p000); vertsPar[0].Add(p100); vertsPar[1].Add(p101); vertsPar[2].Add(p100); vertsPar[3].Add(p101); vertsPar[4].Add(p111); vertsPar[5].Add(p011); vertsPar[3].Add(p111); vertsPar[4].Add(p011); vertsPar[5].Add(p001); vertsPar[3].Add(p100); vertsPar[4].Add(p110); vertsPar[5].Add(p010); vertsPar[3].Add(p110); vertsPar[4].Add(p010); vertsPar[5].Add(p000); verts.Add(tl); verts.Add(tr); verts.Add(bl); verts.Add(br); //colorsArrows.Add(col); //colorsArrows.Add(col); for (int jjj = 0; jjj < 6; jjj++) { Color col1 = Color.white; Color col2 = col; if (jjj == 0) { colorsPar[jjj].Add(col1); colorsPar[jjj].Add(col1); colorsPar[jjj].Add(col1); colorsPar[jjj].Add(col1); } else if (jjj == 1) { colorsPar[jjj].Add(col2); colorsPar[jjj].Add(col2); colorsPar[jjj].Add(col2); colorsPar[jjj].Add(col2); } else { colorsPar[jjj].Add(col2); colorsPar[jjj].Add(col2); colorsPar[jjj].Add(col1); colorsPar[jjj].Add(col1); } } colors.Add(col); colors.Add(col); colors.Add(col); colors.Add(col); //indsArrows.Add(viArrows); //indsArrows.Add(viArrows + 1); for (int jjj = 1; jjj < 6; jjj++) { indsPar[jjj].Add(viPar[jjj]); indsPar[jjj].Add(viPar[jjj] + 1); indsPar[jjj].Add(viPar[jjj] + 2); indsPar[jjj].Add(viPar[jjj] + 2); indsPar[jjj].Add(viPar[jjj] + 1); indsPar[jjj].Add(viPar[jjj] + 3); } inds.Add(vi); inds.Add(vi + 1); inds.Add(vi + 2); inds.Add(vi + 2); inds.Add(vi + 1); inds.Add(vi + 3); inds2d.Add(vi); inds2d.Add(vi + 1); inds2d.Add(vi + 2); inds2d.Add(vi + 2); inds2d.Add(vi + 1); inds2d.Add(vi + 3); } float altRange = (maxAlt - minAlt); float altScalar = altRange / scaleFactor2D; int n = data.dataPoints.Count; //DateTime firstTime = data.dataPoints[0].time; DateTime firstTime = (n > 0) ? data.dataPoints[0].time : DateTime.Now; maxt = float.MinValue; for (int i = 0; i < n; i++) { ProductDataPoint dp = data.dataPoints[i]; float l = (float)(dp.time - firstTime).TotalSeconds; float r = l + durationList[i]; float b = altBottomList[dp.dataPointIndex]; float t = altTopList[dp.dataPointIndex]; if (r > maxt) maxt = r; b = (b - minAlt) / altScalar; t = (t - minAlt) / altScalar; Vector3 bl = new Vector3(l, b, 0.0f); Vector3 br = new Vector3(r, b, 0.0f); Vector3 tl = new Vector3(l, t, 0.0f); Vector3 tr = new Vector3(r, t, 0.0f); verts2d.Add(tl); verts2d.Add(tr); verts2d.Add(bl); verts2d.Add(br); } float numsecs = (float)(data.nominalEndTime - data.nominalStartTime).TotalSeconds; Debug.Log($"MAX TIME: {maxt} nominal duration: {numsecs}"); scrollrect.ResizeContent(maxt, scaleFactor2D); mesh.vertices = verts.ToArray(); mesh.colors = colors.ToArray(); mesh.SetIndices(inds.ToArray(), MeshTopology.Triangles, 0, true); meshFilter.sharedMesh = mesh; //meshArrows.vertices = vertsArrows.ToArray(); //meshArrows.colors = colorsArrows.ToArray(); //meshArrows.SetIndices(indsArrows.ToArray(), MeshTopology.Lines, 0, true); //GameObject arrowsGO = new GameObject(hvs.prodvar.name + "Arrows"); //arrowsGO.transform.SetParent(meshFilter.transform.parent); //MeshFilter meshArrowsFilter = arrowsGO.AddComponent(); //meshArrowsFilter.sharedMesh = meshArrows; //arrowsGO.AddComponent().material = meshFilter.gameObject.GetComponent().material; parGO = new GameObject(hvs.prodvar.name + "Par"); parGO.transform.SetParent(meshFilter.transform.parent); for (int jjj = 0; jjj < 6; jjj++) { GameObject parChildGO = new GameObject(hvs.prodvar.name + "Par"); parChildGO.transform.SetParent(parGO.transform); meshPar[jjj].vertices = vertsPar[jjj].ToArray(); meshPar[jjj].colors = colorsPar[jjj].ToArray(); meshPar[jjj].SetIndices(indsPar[jjj].ToArray(), MeshTopology.Triangles, 0, true); MeshFilter meshParFilter = parChildGO.AddComponent(); meshParFilter.sharedMesh = meshPar[jjj]; parChildGO.AddComponent().material = meshFilter.gameObject.GetComponent().material; } mesh2d.vertices = verts2d.ToArray(); mesh2d.colors = colors.ToArray(); mesh2d.SetIndices(inds2d.ToArray(), MeshTopology.Triangles, 0, true); meshFilter2D.sharedMesh = mesh2d; meshFilter2D.gameObject.AddComponent(); } public void OnScrollRectValueChanged(Vector2 v) { if (data == null) return; Vector3 cp = cam2d.transform.position; cp.x = v.x * maxt; cp.y = v.y * scaleFactor2D; cam2d.transform.position = cp; //cam2d.orthographicSize = 500.0f / scrollrect.CurrentZoom; } private void Update() { if (curzoom != scrollrect.CurrentZoom) { curzoom = scrollrect.CurrentZoom; Debug.Log($"CurrentZoom = {curzoom}"); cam2d.orthographicSize = 500.0f / curzoom; } if (data == null) return; Vector3 c = new Vector3(0.5f * Screen.width, 0.225f * Screen.height, 0.0f); Ray ray = cam2d.ScreenPointToRay(/*Input.mousePosition*/c); /* RaycastHit hit; if (Physics.Raycast(ray, out hit)) { Debug.Log($"RAYCAST HIT {hit.collider.name} triangle {hit.triangleIndex} "); } else { Debug.Log("RAYCAST HIT NOTHING"); } */ RaycastHit[] hits = Physics.RaycastAll(ray); if (hits.Length == 0) { //Debug.Log("RAYCAST HIT NOTHING"); hvs.SelectDataPoint(null, 0, 0); } else { RaycastHit hit0 = hits[0]; int dpIndex = hit0.triangleIndex >> 1; ProductDataPoint dp = data.dataPoints[dpIndex]; float l, r, b, t; GetDataPoint2dBounds(dpIndex, out l, out r, out b, out t); float x = cam2d.transform.position.x; float y = cam2d.transform.position.y; float xn = (x - l) / (r - l); float yn = (y - b) / (t - b); //Debug.Log($" x:{xn} y: {yn} "); hvs.SelectDataPoint(dp, xn, yn); /* if (hits.Length == 1) { RaycastHit hit = hits[0]; //Debug.Log($"RAYCAST HIT {hit.collider.name} datpoint {hit.triangleIndex >> 1} "); } else if (hits.Length > 1) { string s = ""; for (int i = 0; i < hits.Length; i++) { RaycastHit hit = hits[i]; if (i == 0) s = $"({hit.triangleIndex >> 1}"; else s += ", {hit.triangleIndex >> 1}"; } s += ")"; //Debug.Log($"RAYCAST MULTIHIT datpoints {s}"); }*/ } } void GetDataPoint2dBounds(int dpIndex, out float l, out float r, out float b, out float t) { int i = dpIndex * 4; l = verts2d[i].x; t = verts2d[i].y; r = verts2d[i + 3].x; b = verts2d[i + 3].y; } }