/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Linq;
using UnityEngine;
namespace InfinityCode.RealWorldTerrain
{
///
/// This class is added to the resulting container.\n
/// It contains all information about terrains.
///
[Serializable]
[AddComponentMenu("")]
public class RealWorldTerrainContainer : RealWorldTerrainMonoBase
{
///
/// Billboard start.
///
public float billboardStart = 50;
///
/// Detail density.
///
public float detailDensity = 1;
///
/// Detail distance.
///
public float detailDistance = 80;
///
/// The folder in the project where located terrains.
///
public string folder;
///
/// Count of terrains.
///
public RealWorldTerrainVector2i terrainCount;
///
/// Title
///
public string title;
///
/// Tree distance.
///
public float treeDistance = 2000;
///
/// The array of elements that belong to the current process of generation.
///
public RealWorldTerrainItem[] terrains;
///
/// Gets all instances of RealWorldTerrainContainer.
///
/// Instances of RealWorldTerrainContainer
public static RealWorldTerrainContainer[] GetInstances()
{
return FindObjectsOfType().ToArray();
}
public override RealWorldTerrainItem GetItemByWorldPosition(Vector3 worldPosition)
{
for (int i = 0; i < terrains.Length; i++)
{
RealWorldTerrainItem item = terrains[i];
if (item == null) continue;
Bounds b = new Bounds(item.bounds.center + transform.position, item.bounds.size);
if (b.min.x <= worldPosition.x && b.min.z <= worldPosition.z && b.max.x >= worldPosition.x && b.max.z >= worldPosition.z)
{
return item;
}
}
return null;
}
public override bool GetWorldPosition(double lng, double lat, out Vector3 worldPosition)
{
worldPosition = new Vector3();
if (!Contains(lng, lat))
{
Debug.Log("Wrong coordinates");
return false;
}
if (terrains == null || terrains.Length == 0) return false;
double mx, my;
RealWorldTerrainUtils.LatLongToMercat(lng, lat, out mx, out my);
double lX = RealWorldTerrainUtils.Clamp((mx - leftMercator) / (rightMercator - leftMercator), 0, 1);
double lZ = RealWorldTerrainUtils.Clamp(1 - (my - topMercator) / (bottomMercator - topMercator), 0, 1);
Bounds cb = new Bounds(bounds.center + transform.position, bounds.size);
double x = cb.size.x * lX + cb.min.x;
double z = cb.size.z * lZ + cb.min.z;
if (prefs.resultType == RealWorldTerrainResultType.terrain)
{
Terrain terrain = null;
for (int i = 0; i < terrains.Length; i++)
{
RealWorldTerrainItem item = terrains[i];
Bounds b = new Bounds(item.bounds.center + transform.position, item.bounds.size);
if (b.min.x <= x && b.min.z <= z && b.max.x >= x && b.max.z >= z)
{
terrain = item.terrain;
break;
}
}
if (terrain == null) return false;
double ix = (x - terrain.gameObject.transform.position.x) / terrain.terrainData.size.x;
double iz = (z - terrain.gameObject.transform.position.z) / terrain.terrainData.size.z;
double y = terrain.terrainData.GetInterpolatedHeight((float)ix, (float)iz) + terrain.gameObject.transform.position.y;
worldPosition.x = (float)x;
worldPosition.y = (float)y;
worldPosition.z = (float)z;
}
else if (prefs.resultType == RealWorldTerrainResultType.mesh)
{
bool success = false;
for (int i = 0; i < terrains.Length; i++)
{
RealWorldTerrainItem item = terrains[i];
Bounds b = new Bounds(item.bounds.center + transform.position, item.bounds.size);
if (b.min.x <= x && b.min.z <= z && b.max.x >= x && b.max.z >= z)
{
float y = 0;
RaycastHit[] hits = Physics.RaycastAll(new Vector3((float)x, item.bounds.max.y + 10, (float)z), Vector3.down, float.MaxValue);
foreach (RaycastHit hit in hits)
{
if (hit.transform.gameObject.GetComponentInParent() != null)
{
y = hit.point.y;
break;
}
}
worldPosition.x = (float)x;
worldPosition.y = y;
worldPosition.z = (float)z;
success = true;
break;
}
}
if (!success) return false;
}
return true;
}
public override bool GetWorldPosition(Vector2 coordinates, out Vector3 worldPosition)
{
return GetWorldPosition(coordinates.x, coordinates.y, out worldPosition);
}
}
}