Exemple #1
0
    public void MoveRelationsToWays(List <OnlineMapsOSMRelation> relations, Dictionary <string, OnlineMapsOSMWay> ways, Dictionary <string, OnlineMapsOSMNode> nodes)
    {
        List <string> waysInRelation = new List <string>();

        foreach (OnlineMapsOSMRelation relation in relations)
        {
            MoveRelationToWay(relation, ways, waysInRelation, nodes);
        }

        foreach (string id in waysInRelation)
        {
            if (!ways.ContainsKey(id))
            {
                continue;
            }

            OnlineMapsOSMWay way = ways[id];
            way.Dispose();
            ways.Remove(id);
        }

        foreach (KeyValuePair <string, OnlineMapsOSMWay> pair in ways)
        {
            newBuildingsData.Enqueue(new OnlineMapsBuildingsNodeData(pair.Value, nodes));
        }
    }
 private static void AnalizeHouseRoofType(OnlineMapsOSMWay way, ref float baseHeight, ref OnlineMapsBuildingRoofType roofType, ref float roofHeight)
 {
     string roofShape = way.GetTagValue("roof:shape");
     string roofHeightStr = way.GetTagValue("roof:height");
     string minHeightStr = way.GetTagValue("min_height");
     if (!String.IsNullOrEmpty(roofShape))
     {
         if ((roofShape == "dome" || roofShape == "pyramidal") && !String.IsNullOrEmpty(roofHeightStr))
         {
             GetHeightFromString(roofHeightStr, ref roofHeight);
             baseHeight -= roofHeight;
             roofType = OnlineMapsBuildingRoofType.dome;
         }
     }
     else if (!String.IsNullOrEmpty(roofHeightStr))
     {
         GetHeightFromString(roofHeightStr, ref roofHeight);
         baseHeight -= roofHeight;
         roofType = OnlineMapsBuildingRoofType.dome;
     }
     else if (!String.IsNullOrEmpty(minHeightStr))
     {
         float totalHeight = baseHeight;
         GetHeightFromString(minHeightStr, ref baseHeight);
         roofHeight = totalHeight - baseHeight;
         roofType = OnlineMapsBuildingRoofType.dome;
     }
 }
Exemple #3
0
    private static void AnalizeHouseTags(OnlineMapsOSMWay way, ref Material wallMaterial, ref Material roofMaterial, ref float baseHeight)
    {
        string heightStr = way.GetTagValue("height");
        string levelsStr = way.GetTagValue("building:levels");

        GetHeightFromString(heightStr, ref baseHeight);
        if (String.IsNullOrEmpty(heightStr) && !String.IsNullOrEmpty(levelsStr))
        {
            baseHeight = float.Parse(levelsStr) * OnlineMapsBuildings.instance.levelHeight;
        }
        else
        {
            baseHeight = Random.Range(OnlineMapsBuildings.instance.levelsRange.min, OnlineMapsBuildings.instance.levelsRange.max) * OnlineMapsBuildings.instance.levelHeight;
        }

        if (baseHeight < OnlineMapsBuildings.instance.minHeight)
        {
            baseHeight = OnlineMapsBuildings.instance.minHeight;
        }

        string colorStr = way.GetTagValue("building:colour");

        if (!String.IsNullOrEmpty(colorStr))
        {
            wallMaterial.color = roofMaterial.color = StringToColor(colorStr);
        }
    }
Exemple #4
0
    private static void AnalizeHouseRoofType(OnlineMapsOSMWay way, ref float baseHeight, ref RoofType roofType, ref float roofHeight)
    {
        string roofShape     = way.GetTagValue("roof:shape");
        string roofHeightStr = way.GetTagValue("roof:height");
        string minHeightStr  = way.GetTagValue("min_height");

        if (!String.IsNullOrEmpty(roofShape))
        {
            if ((roofShape == "dome" || roofShape == "pyramidal") && !String.IsNullOrEmpty(roofHeightStr))
            {
                GetHeightFromString(roofHeightStr, ref roofHeight);
                baseHeight -= roofHeight;
                roofType    = RoofType.dome;
            }
        }
        else if (!String.IsNullOrEmpty(roofHeightStr))
        {
            GetHeightFromString(roofHeightStr, ref roofHeight);
            baseHeight -= roofHeight;
            roofType    = RoofType.dome;
        }
        else if (!String.IsNullOrEmpty(minHeightStr))
        {
            float totalHeight = baseHeight;
            GetHeightFromString(minHeightStr, ref baseHeight);
            roofHeight = totalHeight - baseHeight;
            roofType   = RoofType.dome;
        }
    }
    /// <summary>
    /// Fast way to get data from the response Open Street Map Overpass API.
    /// </summary>
    /// <param name="response">Response from Overpass API</param>
    /// <param name="nodes">Dictionary of nodes</param>
    /// <param name="ways">List of ways</param>
    /// <param name="relations">List of relations</param>
    public static void ParseOSMResponseFast(string response, out Dictionary <string, OnlineMapsOSMNode> nodes, out Dictionary <string, OnlineMapsOSMWay> ways, out List <OnlineMapsOSMRelation> relations)
    {
        int        i        = 0;
        OSMXMLNode rootNode = new OSMXMLNode(response, ref i);

        if (rootNode.childs == null)
        {
            nodes     = new Dictionary <string, OnlineMapsOSMNode>();
            ways      = new Dictionary <string, OnlineMapsOSMWay>();
            relations = new List <OnlineMapsOSMRelation>();
            return;
        }

        int countNodes     = 0;
        int countWays      = 0;
        int countRelations = 0;

        for (int j = 0; j < rootNode.childs.Count; j++)
        {
            OSMXMLNode node = rootNode.childs[j];
            if (node.name == "node")
            {
                countNodes++;
            }
            else if (node.name == "way")
            {
                countWays++;
            }
            else if (node.name == "relation")
            {
                countRelations++;
            }
        }

        nodes     = new Dictionary <string, OnlineMapsOSMNode>(countNodes);
        ways      = new Dictionary <string, OnlineMapsOSMWay>(countWays);
        relations = new List <OnlineMapsOSMRelation>(countRelations);

        for (int j = 0; j < rootNode.childs.Count; j++)
        {
            OSMXMLNode node = rootNode.childs[j];
            if (node.name == "node")
            {
                nodes.Add(node.GetAttribute("id"), new OnlineMapsOSMNode(node));
            }
            else if (node.name == "way")
            {
                OnlineMapsOSMWay way = new OnlineMapsOSMWay(node);
                if (!ways.ContainsKey(way.id))
                {
                    ways.Add(way.id, way);
                }
            }
            else if (node.name == "relation")
            {
                relations.Add(new OnlineMapsOSMRelation(node));
            }
        }
    }
Exemple #6
0
    private static void AnalizeHouseTags(OnlineMapsBuildings container, OnlineMapsOSMWay way, ref Material wallMaterial, ref Material roofMaterial, ref float baseHeight)
    {
        string heightStr = container.useHeightTag? way.GetTagValue("height"): null;
        bool   hasHeight = false;

        if (!string.IsNullOrEmpty(heightStr))
        {
            hasHeight = GetHeightFromString(heightStr, ref baseHeight);
        }

        if (!hasHeight && container.useHeightTag)
        {
            string levelsStr = way.GetTagValue("building:levels");
            if (!String.IsNullOrEmpty(levelsStr))
            {
                float countLevels;
                if (float.TryParse(levelsStr, NumberStyles.AllowDecimalPoint, OnlineMapsUtils.numberFormat, out countLevels))
                {
                    baseHeight = countLevels * OnlineMapsBuildings.instance.levelHeight;
                    hasHeight  = true;
                }
            }
        }

        if (!hasHeight)
        {
            if (OnlineMapsBuildings.instance.OnGenerateBuildingHeight != null)
            {
                baseHeight = OnlineMapsBuildings.instance.OnGenerateBuildingHeight(way);
            }
            else
            {
                string minHeightStr = container.useHeightTag? way.GetTagValue("min_height"): null;
                if (!string.IsNullOrEmpty(minHeightStr))
                {
                    GetHeightFromString(minHeightStr, ref baseHeight);
                }
                else
                {
                    baseHeight = Random.Range(OnlineMapsBuildings.instance.levelsRange.min, OnlineMapsBuildings.instance.levelsRange.max) * OnlineMapsBuildings.instance.levelHeight;
                }
            }
        }

        if (baseHeight < OnlineMapsBuildings.instance.minHeight)
        {
            baseHeight = OnlineMapsBuildings.instance.minHeight;
        }

        if (container.useColorTag)
        {
            string colorStr = way.GetTagValue("building:colour");
            if (!String.IsNullOrEmpty(colorStr))
            {
                wallMaterial.color = roofMaterial.color = StringToColor(colorStr);
            }
        }
    }
    protected static bool CheckIgnoredBuildings(OnlineMapsOSMWay way)
    {
        if (way.GetTagValue("building") == "bridge") return true;

        string layer = way.GetTagValue("layer");
        if (!String.IsNullOrEmpty(layer) && Int32.Parse(layer) < 0) return true;

        return false;
    }
    private static void AnalizeHouseTags(OnlineMapsOSMWay way, ref Material wallMaterial, ref Material roofMaterial, ref float baseHeight)
    {
        string heightStr = way.GetTagValue("height");
        string levelsStr = way.GetTagValue("building:levels");
        GetHeightFromString(heightStr, ref baseHeight);
        if (String.IsNullOrEmpty(heightStr) && !String.IsNullOrEmpty(levelsStr))
            baseHeight = float.Parse(levelsStr) * OnlineMapsBuildings.instance.levelHeight;
        else baseHeight = Random.Range(OnlineMapsBuildings.instance.levelsRange.min, OnlineMapsBuildings.instance.levelsRange.max) * OnlineMapsBuildings.instance.levelHeight;

        if (baseHeight < OnlineMapsBuildings.instance.minHeight) baseHeight = OnlineMapsBuildings.instance.minHeight;

        string colorStr = way.GetTagValue("building:colour");
        if (!String.IsNullOrEmpty(colorStr)) wallMaterial.color = roofMaterial.color = StringToColor(colorStr);
    }
Exemple #9
0
    private static void AnalizeHouseTags(OnlineMapsOSMWay way, ref Material wallMaterial, ref Material roofMaterial, ref float baseHeight)
    {
        string heightStr = way.GetTagValue("height");
        bool   hasHeight = false;

        if (!string.IsNullOrEmpty(heightStr))
        {
            hasHeight = GetHeightFromString(heightStr, ref baseHeight);
        }

        if (!hasHeight)
        {
            string levelsStr = way.GetTagValue("building:levels");
            if (!String.IsNullOrEmpty(levelsStr))
            {
                float countLevels;
                if (float.TryParse(levelsStr, out countLevels))
                {
                    baseHeight = countLevels * OnlineMapsBuildings.instance.levelHeight;
                    hasHeight  = true;
                }
            }
        }

        if (!hasHeight)
        {
            if (OnlineMapsBuildings.instance.OnGenerateBuildingHeight != null)
            {
                baseHeight = OnlineMapsBuildings.instance.OnGenerateBuildingHeight(way);
            }
            else
            {
                baseHeight = Random.Range(OnlineMapsBuildings.instance.levelsRange.min, OnlineMapsBuildings.instance.levelsRange.max) * OnlineMapsBuildings.instance.levelHeight;
            }
        }

        if (baseHeight < OnlineMapsBuildings.instance.minHeight)
        {
            baseHeight = OnlineMapsBuildings.instance.minHeight;
        }

        string colorStr = way.GetTagValue("building:colour");

        if (!String.IsNullOrEmpty(colorStr))
        {
            wallMaterial.color = roofMaterial.color = StringToColor(colorStr);
        }
    }
Exemple #10
0
    /// <summary>
    /// Checks ignore the building.
    /// </summary>
    /// <param name="way">Building way.</param>
    /// <returns>TRUE - ignore building, FALSE - generate building.</returns>
    protected static bool CheckIgnoredBuildings(OnlineMapsOSMWay way)
    {
        if (way.GetTagValue("building") == "bridge")
        {
            return(true);
        }

        string layer = way.GetTagValue("layer");

        if (!String.IsNullOrEmpty(layer) && Int32.Parse(layer) < 0)
        {
            return(true);
        }

        return(false);
    }
Exemple #11
0
    /// <summary>
    /// Checks ignore the building.
    /// </summary>
    /// <param name="way">Building way.</param>
    /// <returns>TRUE - ignore building, FALSE - generate building.</returns>
    protected static bool CheckIgnoredBuildings(OnlineMapsOSMWay way)
    {
        string buildingType = way.GetTagValue("building");

        if (buildingType == "bridge" || buildingType == "roof")
        {
            return(true);
        }

        string layer = way.GetTagValue("layer");

        if (!string.IsNullOrEmpty(layer) && int.Parse(layer) < 0)
        {
            return(true);
        }

        return(false);
    }
Exemple #12
0
    private void MoveRelationToWay(OnlineMapsOSMRelation relation, Dictionary <string, OnlineMapsOSMWay> ways, List <string> waysInRelation, Dictionary <string, OnlineMapsOSMNode> nodes)
    {
        if (relation.members.Count == 0)
        {
            return;
        }

        OnlineMapsOSMWay way      = new OnlineMapsOSMWay();
        List <string>    nodeRefs = new List <string>();

        List <OnlineMapsOSMRelationMember> members = relation.members.Where(m => m.type == "way" && m.role == "outer").ToList();

        if (members.Count == 0)
        {
            return;
        }

        OnlineMapsOSMWay relationWay;

        if (!ways.TryGetValue(members[0].reference, out relationWay) || relationWay == null)
        {
            return;
        }

        nodeRefs.AddRange(relationWay.nodeRefs);
        members.RemoveAt(0);

        while (members.Count > 0)
        {
            if (!MoveRelationMemberToWay(nodeRefs, members, ways))
            {
                break;
            }
        }

        waysInRelation.AddRange(relation.members.Select(m => m.reference));
        way.nodeRefs = nodeRefs;
        way.id       = relation.id;
        way.tags     = relation.tags;
        newBuildingsData.Enqueue(new OnlineMapsBuildingsNodeData(way, nodes));
    }
Exemple #13
0
    private static bool MoveRelationMemberToWay(List <string> nodeRefs, List <OnlineMapsOSMRelationMember> members, Dictionary <string, OnlineMapsOSMWay> ways)
    {
        string lastRef = nodeRefs[nodeRefs.Count - 1];

        int memberIndex = -1;

        for (int i = 0; i < members.Count; i++)
        {
            OnlineMapsOSMRelationMember member = members[i];
            OnlineMapsOSMWay            w      = ways[member.reference];
            if (w.nodeRefs[0] == lastRef)
            {
                nodeRefs.AddRange(w.nodeRefs.Skip(1));
                memberIndex = i;
                break;
            }
            if (w.nodeRefs[w.nodeRefs.Count - 1] == lastRef)
            {
                List <string> refs = w.nodeRefs;
                refs.Reverse();
                nodeRefs.AddRange(refs.Skip(1));
                memberIndex = i;
                break;
            }
        }

        if (memberIndex != -1)
        {
            members.RemoveAt(memberIndex);
        }
        else
        {
            return(false);
        }
        return(true);
    }
Exemple #14
0
    /// <summary>
    /// Creates a new building, based on Open Street Map.
    /// </summary>
    /// <param name="container">Reference to OnlineMapsBuildings.</param>
    /// <param name="way">Way of building.</param>
    /// <param name="nodes">Nodes obtained from Open Street Maps.</param>
    /// <returns>Building instance.</returns>
    public static OnlineMapsBuildingBase Create(OnlineMapsBuildings container, OnlineMapsOSMWay way, Dictionary <string, OnlineMapsOSMNode> nodes)
    {
        if (CheckIgnoredBuildings(way))
        {
            return(null);
        }

        if (usedNodes == null)
        {
            usedNodes = new List <OnlineMapsOSMNode>(30);
        }
        else
        {
            usedNodes.Clear();
        }

        way.GetNodes(nodes, usedNodes);
        List <Vector3> points = GetLocalPoints(usedNodes);

        if (points.Count < 3)
        {
            return(null);
        }
        if (points[0] == points[points.Count - 1])
        {
            points.RemoveAt(points.Count - 1);
        }
        if (points.Count < 3)
        {
            return(null);
        }

        for (int i = 0; i < points.Count; i++)
        {
            int prev = i - 1;
            if (prev < 0)
            {
                prev = points.Count - 1;
            }

            int next = i + 1;
            if (next >= points.Count)
            {
                next = 0;
            }

            float a1 = OnlineMapsUtils.Angle2D(points[prev], points[i]);
            float a2 = OnlineMapsUtils.Angle2D(points[i], points[next]);

            if (Mathf.Abs(a1 - a2) < 5)
            {
                points.RemoveAt(i);
                i--;
            }
        }

        if (points.Count < 3)
        {
            return(null);
        }

        Vector4 cp = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);

        for (int i = 0; i < points.Count; i++)
        {
            Vector3 point = points[i];
            if (point.x < cp.x)
            {
                cp.x = point.x;
            }
            if (point.z < cp.y)
            {
                cp.y = point.z;
            }
            if (point.x > cp.z)
            {
                cp.z = point.x;
            }
            if (point.z > cp.w)
            {
                cp.w = point.z;
            }
        }

        Vector3 centerPoint = new Vector3((cp.z + cp.x) / 2, 0, (cp.y + cp.w) / 2);

        for (int i = 0; i < points.Count; i++)
        {
            points[i] -= centerPoint;
        }

        bool generateWall = true;

        if (way.HasTagKey("building"))
        {
            string buildingType = way.GetTagValue("building");
            if (buildingType == "roof")
            {
                generateWall = false;
            }
        }

        float baseHeight = 15;
        float roofHeight = 0;

        OnlineMapsBuildingMaterial material = GetRandomMaterial(container);
        Material wallMaterial;
        Material roofMaterial;
        Vector2  scale = Vector2.one;

        if (defaultShader == null)
        {
            defaultShader = Shader.Find("Diffuse");
        }

        if (material != null)
        {
            if (material.wall != null)
            {
                wallMaterial = Instantiate(material.wall) as Material;
            }
            else
            {
                wallMaterial = new Material(defaultShader);
            }

            if (material.roof != null)
            {
                roofMaterial = Instantiate(material.roof) as Material;
            }
            else
            {
                roofMaterial = new Material(defaultShader);
            }

            scale = material.scale;
        }
        else
        {
            if (defaultWallMaterial == null)
            {
                defaultWallMaterial = new Material(defaultShader);
            }
            if (defaultRoofMaterial == null)
            {
                defaultRoofMaterial = new Material(defaultShader);
            }
            wallMaterial = Instantiate(defaultWallMaterial) as Material;
            roofMaterial = Instantiate(defaultRoofMaterial) as Material;
        }

        RoofType roofType = RoofType.flat;

        AnalizeHouseTags(way, ref wallMaterial, ref roofMaterial, ref baseHeight);
        AnalizeHouseRoofType(way, ref baseHeight, ref roofType, ref roofHeight);

        GameObject   houseGO    = CreateGameObject(way.id);
        MeshRenderer renderer   = houseGO.AddComponent <MeshRenderer>();
        MeshFilter   meshFilter = houseGO.AddComponent <MeshFilter>();

        Mesh mesh = new Mesh {
            name = way.id
        };

        meshFilter.sharedMesh    = mesh;
        renderer.sharedMaterials = new []
        {
            wallMaterial,
            roofMaterial
        };

        OnlineMapsBuildingBuiltIn building = houseGO.AddComponent <OnlineMapsBuildingBuiltIn>();

        building.way   = way;
        building.nodes = usedNodes;
        houseGO.transform.localPosition = centerPoint;
        houseGO.transform.localRotation = Quaternion.Euler(Vector3.zero);
        houseGO.transform.localScale    = Vector3.one;

        Vector2 centerCoords = Vector2.zero;
        float   minCX = float.MaxValue, minCY = float.MaxValue, maxCX = float.MinValue, maxCY = float.MinValue;

        foreach (OnlineMapsOSMNode node in usedNodes)
        {
            Vector2 nodeCoords = node;
            centerCoords += nodeCoords;
            if (nodeCoords.x < minCX)
            {
                minCX = nodeCoords.x;
            }
            if (nodeCoords.y < minCY)
            {
                minCY = nodeCoords.y;
            }
            if (nodeCoords.x > maxCX)
            {
                maxCX = nodeCoords.x;
            }
            if (nodeCoords.y > maxCY)
            {
                maxCY = nodeCoords.y;
            }
        }

        building.id                = way.id;
        building.initialZoom       = OnlineMaps.instance.zoom;
        building.centerCoordinates = new Vector2((maxCX + minCX) / 2, (maxCY + minCY) / 2);
        building.boundsCoords      = new Bounds(building.centerCoordinates, new Vector3(maxCX - minCX, maxCY - minCY));

        int wallVerticesCount = (points.Count + 1) * 2;
        int roofVerticesCount = points.Count;
        int verticesCount     = wallVerticesCount + roofVerticesCount;
        int countTriangles    = wallVerticesCount * 3;

        if (vertices == null)
        {
            vertices = new List <Vector3>(verticesCount);
        }
        else
        {
            vertices.Clear();
        }

        if (uvs == null)
        {
            uvs = new List <Vector2>(verticesCount);
        }
        else
        {
            uvs.Clear();
        }

        if (wallTriangles == null)
        {
            wallTriangles = new List <int>(countTriangles);
        }
        else
        {
            wallTriangles.Clear();
        }

        if (roofTriangles == null)
        {
            roofTriangles = new List <int>();
        }
        else
        {
            roofTriangles.Clear();
        }

        if (generateWall)
        {
            building.CreateHouseWall(points, baseHeight, wallMaterial, scale);
        }
        building.CreateHouseRoof(points, baseHeight, roofHeight, roofType);

        if (building.hasErrors)
        {
            OnlineMapsUtils.DestroyImmediate(building.gameObject);
            return(null);
        }

        mesh.vertices     = vertices.ToArray();
        mesh.uv           = uvs.ToArray();
        mesh.subMeshCount = 2;
        mesh.SetTriangles(wallTriangles.ToArray(), 0);
        mesh.SetTriangles(roofTriangles.ToArray(), 1);

        mesh.RecalculateBounds();
        mesh.RecalculateNormals();

        building.buildingCollider = houseGO.AddComponent <MeshCollider>();
        (building.buildingCollider as MeshCollider).sharedMesh = mesh;

        return(building);
    }
 /// <summary>
 /// Disposes this object.
 /// </summary>
 public void Dispose()
 {
     way   = null;
     nodes = null;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="way">Way of a building contour.</param>
 /// <param name="nodes">Dictionary of nodes.</param>
 public OnlineMapsBuildingsNodeData(OnlineMapsOSMWay way, Dictionary <string, OnlineMapsOSMNode> nodes)
 {
     this.way   = way;
     this.nodes = nodes;
 }
 public void Dispose()
 {
     way = null;
     nodes = null;
 }
 public OnlineMapsBuildingsNodeData(OnlineMapsOSMWay way, Dictionary<string, OnlineMapsOSMNode> nodes)
 {
     this.way = way;
     this.nodes = nodes;
 }
    /// <summary>
    /// Creates a new building, based on Open Street Map.
    /// </summary>
    /// <param name="container">Reference to OnlineMapsBuildings.</param>
    /// <param name="way">Way of building.</param>
    /// <param name="nodes">Nodes obtained from Open Street Maps.</param>
    /// <returns>Building instance.</returns>
    public static OnlineMapsBuildingBase Create(OnlineMapsBuildings container, OnlineMapsOSMWay way, Dictionary<string, OnlineMapsOSMNode> nodes)
    {
        if (CheckIgnoredBuildings(way)) return null;

        List<OnlineMapsOSMNode> usedNodes = way.GetNodes(nodes);
        List<Vector3> points = GetLocalPoints(usedNodes);

        if (points.Count < 3) return null;
        if (points[0] == points[points.Count - 1]) points.RemoveAt(points.Count - 1);
        if (points.Count < 3) return null;

        for (int i = 0; i < points.Count; i++)
        {
            int prev = i - 1;
            if (prev < 0) prev = points.Count - 1;

            int next = i + 1;
            if (next >= points.Count) next = 0;

            float a1 = OnlineMapsUtils.Angle2D(points[prev], points[i]);
            float a2 = OnlineMapsUtils.Angle2D(points[i], points[next]);

            if (Mathf.Abs(a1 - a2) < 5)
            {
                points.RemoveAt(i);
                i--;
            }
        }

        if (points.Count < 3) return null;

        Vector4 cp = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
        foreach (Vector3 point in points)
        {
            if (point.x < cp.x) cp.x = point.x;
            if (point.z < cp.y) cp.y = point.z;
            if (point.x > cp.z) cp.z = point.x;
            if (point.z > cp.w) cp.w = point.z;
        }
        //centerPoint = points.Aggregate(centerPoint, (current, point) => current + point) / points.Count;
        Vector3 centerPoint = new Vector3((cp.z + cp.x) / 2, points.Min(p => p.y), (cp.y + cp.w) / 2);

        bool generateWall = true;

        if (way.HasTagKey("building"))
        {
            string buildingType = way.GetTagValue("building");
            if (buildingType == "roof") generateWall = false;
        }

        float baseHeight = 15;
        float roofHeight = 0;

        OnlineMapsBuildingMaterial material = GetRandomMaterial(container);

        Material defWallMaterial = (material != null)? material.wall: null;
        Material defRoofMaterial = (material != null) ? material.roof : null;
        Vector2 scale = (material != null) ? material.scale : Vector2.one;

        if (defWallMaterial == null) defWallMaterial = new Material(Shader.Find("Diffuse"));
        if (defRoofMaterial == null) defRoofMaterial = new Material(Shader.Find("Diffuse"));

        Material wallMaterial = new Material(defWallMaterial);
        Material roofMaterial = new Material(defRoofMaterial);

        OnlineMapsBuildingRoofType roofType = OnlineMapsBuildingRoofType.flat;
        AnalizeHouseTags(way, ref wallMaterial, ref roofMaterial, ref baseHeight);
        AnalizeHouseRoofType(way, ref baseHeight, ref roofType, ref roofHeight);

        Vector3[] baseVerticles = points.Select(p => p - centerPoint).ToArray();

        GameObject houseGO = CreateGameObject(way.id);
        MeshRenderer renderer = houseGO.AddComponent<MeshRenderer>();
        MeshFilter meshFilter = houseGO.AddComponent<MeshFilter>();

        Mesh mesh = new Mesh {name = way.id};

        meshFilter.sharedMesh = mesh;
        renderer.sharedMaterials = new []
        {
            wallMaterial,
            roofMaterial
        };

        OnlineMapsBuildingBuiltIn building = houseGO.AddComponent<OnlineMapsBuildingBuiltIn>();
        houseGO.transform.localPosition = centerPoint;
        houseGO.transform.localRotation = Quaternion.Euler(Vector3.zero);

        Vector2 centerCoords = Vector2.zero;
        float minCX = float.MaxValue, minCY = float.MaxValue, maxCX = float.MinValue, maxCY = float.MinValue;

        foreach (OnlineMapsOSMNode node in usedNodes)
        {
            Vector2 nodeCoords = node;
            centerCoords += nodeCoords;
            if (nodeCoords.x < minCX) minCX = nodeCoords.x;
            if (nodeCoords.y < minCY) minCY = nodeCoords.y;
            if (nodeCoords.x > maxCX) maxCX = nodeCoords.x;
            if (nodeCoords.y > maxCY) maxCY = nodeCoords.y;
        }

        building.id = way.id;
        building.initialZoom = OnlineMaps.instance.zoom;
        building.centerCoordinates = new Vector2((maxCX + minCX) / 2, (maxCY + minCY) / 2);
        building.boundsCoords = new Bounds(building.centerCoordinates, new Vector3(maxCX - minCX, maxCY - minCY));

        List<Vector3> vertices = new List<Vector3>();
        List<Vector2> uvs = new List<Vector2>();
        List<int> wallTriangles = new List<int>();
        List<int> roofTriangles = new List<int>();

        if (generateWall) building.CreateHouseWall(baseVerticles, baseHeight, wallMaterial, scale, ref vertices, ref uvs, ref wallTriangles);
        building.CreateHouseRoof(baseVerticles, baseHeight, roofHeight, roofType, ref vertices, ref uvs, ref roofTriangles);

        if (building.hasErrors)
        {
            DestroyImmediate(building.gameObject);
            return null;
        }

        mesh.vertices = vertices.ToArray();
        mesh.uv = uvs.ToArray();
        mesh.subMeshCount = 2;
        mesh.SetTriangles(wallTriangles.ToArray(), 0);
        mesh.SetTriangles(roofTriangles.ToArray(), 1);

        mesh.RecalculateBounds();
        mesh.RecalculateNormals();

        building.buildingCollider = houseGO.AddComponent<MeshCollider>();
        (building.buildingCollider as MeshCollider).sharedMesh = mesh;

        return building;
    }
Exemple #20
0
    private void OnBuildingRequestComplete(string response)
    {
        osmRequest = null;

        Action action = () =>
        {
            Dictionary <string, OnlineMapsOSMNode> nodes;
            List <OnlineMapsOSMWay>      ways;
            List <OnlineMapsOSMRelation> relations;

            OnlineMapsOSMAPIQuery.ParseOSMResponseFast(response, out nodes, out ways, out relations);

            lock (newBuildingsData)
            {
                List <string> waysInRelation = new List <string>();
                foreach (OnlineMapsOSMRelation relation in relations)
                {
                    if (relation.members.Count == 0)
                    {
                        continue;
                    }

                    OnlineMapsOSMWay way      = new OnlineMapsOSMWay();
                    List <string>    nodeRefs = new List <string>();

                    List <OnlineMapsOSMRelationMember> members = relation.members.Where(m => m.type == "way" && m.role == "outer").ToList();
                    if (members.Count == 0)
                    {
                        continue;
                    }

                    OnlineMapsOSMWay relationWay = GetWayByID(ways, members[0].reference);
                    if (relationWay == null)
                    {
                        continue;
                    }

                    nodeRefs.AddRange(relationWay.nodeRefs);
                    members.RemoveAt(0);

                    while (members.Count > 0)
                    {
                        string lastRef = nodeRefs[nodeRefs.Count - 1];

                        int memberIndex = -1;
                        for (int i = 0; i < members.Count; i++)
                        {
                            OnlineMapsOSMRelationMember member = members[i];
                            OnlineMapsOSMWay            w      = GetWayByID(ways, member.reference);
                            if (w.nodeRefs[0] == lastRef)
                            {
                                nodeRefs.AddRange(w.nodeRefs.Skip(1));
                                memberIndex = i;
                                break;
                            }
                            if (w.nodeRefs[w.nodeRefs.Count - 1] == lastRef)
                            {
                                List <string> refs = w.nodeRefs;
                                refs.Reverse();
                                nodeRefs.AddRange(refs.Skip(1));
                                memberIndex = i;
                                break;
                            }
                        }

                        if (memberIndex != -1)
                        {
                            members.RemoveAt(memberIndex);
                        }
                        else
                        {
                            break;
                        }
                    }

                    waysInRelation.AddRange(relation.members.Select(m => m.reference));
                    way.nodeRefs = nodeRefs;
                    way.id       = relation.id;
                    way.tags     = relation.tags;
                    newBuildingsData.Enqueue(new OnlineMapsBuildingsNodeData(way, nodes));
                }

                ways.RemoveAll(delegate(OnlineMapsOSMWay w)
                {
                    if (waysInRelation.Contains(w.id))
                    {
                        w.Dispose();
                        return(true);
                    }
                    return(false);
                });

                foreach (OnlineMapsOSMWay way in ways)
                {
                    newBuildingsData.Enqueue(new OnlineMapsBuildingsNodeData(way, nodes));
                }
            }

            sendBuildingsReceived = true;
        };

#if !UNITY_WEBGL
        if (map.renderInThread)
        {
            OnlineMapsThreadManager.AddThreadAction(action);
        }
        else
        {
            action();
        }
#else
        action();
#endif

        if (OnRequestComplete != null)
        {
            OnRequestComplete();
        }
    }