public Building(Way _way, BuildingConfigurations config, Material mat, int materialID, float texWidth)
        {
            type = buildingType.standard;
            way = _way;

            id = way.id;

            buildingConfig = config;
            buildingHeight = getBuildingHeight(way.tags);
            equalizedBuildingHeight = assingBuildingTopLevel(way);

            defaultMaterial = mat;
            defaultMaterialID = materialID;
            defaultTextureWidth = texWidth;
            facadeSkins = new List<FacadeSkin>();

            isClockwise = getWayOrientation(way);

            building = new GameObject("building" + id);
            building.transform.position = new Vector3(0.0f, 0.0f, 0.0f);

            GOtransform = new Vector3(0, 0, 0);
            GOrotate = new Vector3(0, 0, 0);
            GOscale = new Vector3(1, 1, 1);
        }
        public Barrier(Way w, List<BarrierConfigurations> config)
        {
            id = w.id;
            type = getBarrierType(w.tags);
            barrierConfig = getBarrierConfiguration(config,type);

            height = barrierConfig.height;
            thickness = barrierConfig.width;
            barrierMaterial = (Material)Resources.Load(barrierConfig.Path);

            BarrierContainer = new GameObject("Barrier" + w.id);
            BarrierContainer.transform.position = new Vector3(0, 0, 0);
            BarrierElements = new List<GameObject>();
            barrierWay = w;
            generateBarrier(w);
        }
        //Seperate WayType of OSM into our City Engine object types
        public static wayType getWayTpe(Way way)
        {
            if (way.tags == null)
                return wayType.none;

            foreach (Tag t in way.tags)
            {
                if (t.k == "building")
                    return wayType.building;
                else if (t.k == "barrier")
                    return wayType.barrier;
                else if (t.k == "highway" || t.k == "railway")
                {
                    if (t.v == "footway")
                        return wayType.none;

                    return wayType.highway;
                }
                else if (t.k == "landuse" || t.k == "leisure")
                    return wayType.area;
                else if (t.k == "amenity")
                {
                    for (int k = 0; k < way.tags.Count; k++)
                    {
                        if (way.tags[k].k == "building")
                            return wayType.building;
                    }
                    return wayType.area;
                }
                else if (t.k == "waterway" && t.v == "river")
                    return wayType.highway; //return wayType.river;

                else if (t.k == "historic" && t.v == "monument")
                    return wayType.area;
                else if (t.k == "historic" && (t.v == "citywalls" || t.v == "city_gate"))
                    return wayType.barrier;

            }

            return wayType.none;
        }
        //Highway Constructor
        public Highway(Way w, List<HighwayConfigurations> config, myTerrain _terrain)
        {
            id = w.id;
            way = w;
            type = getHighwayType(w.tags);
            name = getHighwayName(w.tags);

            if (type == highwayType.HighwayFootway)
                return;

            getConfiguration(config);
            bbox = _terrain.scenebbox;

            streetLampList = new List<Object3D>();
            generateInitial3Dway(_terrain);
            //colliderMesh = generateColliderMesh();

            highwayGameObject = new GameObject("Highway" + way.id, typeof(MeshRenderer), typeof(MeshFilter), typeof(MeshCollider));
            highwayGameObject.transform.localScale = new Vector3(1, 1, 1);

            if(type != highwayType.River)
                highwayGameObject.tag = "Highway";
        }
        /// <summary>
        /// Divide the way into 2 given intersection node
        /// </summary>
        private void divideWay(string wayID, int intersectionIndex)
        {
            int wayIndex = getWayIndex(wayID);

            Way w1 =  new Way(wayList[wayIndex]);
            w1.id = w1.id + "i1";
            w1.nodes = w1.nodes.GetRange(0, intersectionIndex+1);

            Way w2 = new Way(wayList[wayIndex]);
            try
            {
                w2.id = w2.id + "i2";
                w2.nodes = w2.nodes.GetRange(intersectionIndex, w2.nodes.Count - intersectionIndex);
            }
            catch(ArgumentOutOfRangeException)
            {
                //Debug.Log("<color=red>" + wayID + "</color>");
                return;
            }

            wayList.RemoveAt(wayIndex);
            wayList.Add(w1);
            wayList.Add(w2);

            //UPDATE REST OF INTERSECTIONS
            for(int i = 0 ; i < intersections.Count ; i++)
            {
                if(intersections[i].wayIds.Exists(item => item == wayID))
                {
                    IntersectionNode node = intersections[i];

                    for(int k = 0 ; k < node.wayIds.Count ; k++)
                    {
                        if(node.wayIds[k] == wayID)
                        {
                            if (node.intersectionIndex[k] < intersectionIndex)
                                node.wayIds[k] = w1.id;
                            else
                            {
                                node.wayIds[k] = w2.id;
                                node.intersectionIndex[k] -= intersectionIndex;
                            }
                        }
                    }

                }
            }
        }
        private void generateWall(Way way)
        {
            for (int i = 0; i < way.nodes.Count-1; i++)
            {

                GameObject Wall = new GameObject("WallBlock", typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));
                Wall.transform.parent = BarrierContainer.transform;
                Wall.AddComponent<BarrierMouseHandler>();
                Vector3 up = new Vector3(0, 1, 0);
                Vector3 forward = way.nodes[i+1].meterPosition - way.nodes[i].meterPosition;
                forward.y = 0.0f;
                Vector3 right = Vector3.Cross(forward, up);
                right = right.normalized;
                Vector3 left = -1.0f * right;

                Vector3[] vertices = new Vector3[] { way.nodes[i].meterPosition   + left * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition + left * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition + new Vector3(0.0f, height, 0.0f) + left * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + left * thickness/2.0f,

                                                     way.nodes[i].meterPosition   + right * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition + right * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,

                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + left * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition   + new Vector3(0.0f, height, 0.0f) + left * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition   + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,

                                                     way.nodes[i].meterPosition   + left  * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + right * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,
                                                     way.nodes[i].meterPosition   + new Vector3(0.0f, height, 0.0f) + left  * thickness/2.0f,

                                                     way.nodes[i+1].meterPosition   + left  * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition   + right * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition   + new Vector3(0.0f, height, 0.0f) + right * thickness/2.0f,
                                                     way.nodes[i+1].meterPosition   + new Vector3(0.0f, height, 0.0f) + left  * thickness/2.0f,

                                                   };

                int[] triangles = new int[] {0,3,2,2,1,0, //Front Plane
                                             4,5,6,6,7,4, //Back Plane
                                             8,11,10,10,9,8, //Top Plane
                                             12,13,14,14,15,12, //Left Plane
                                             16,19,18,18,17,16  //Right Right
                                             };
                float magnitude = (way.nodes[i+1].meterPosition - way.nodes[i].meterPosition).magnitude;

                Vector2[] UVcoords = new Vector2[] {new Vector2(0.0f,0.0f), new Vector2(magnitude/20.0f,0.0f), new Vector2(magnitude/20.0f,1.0f), new Vector2(0.0f,1.0f),
                                                    new Vector2(0.0f,0.0f), new Vector2(magnitude/20.0f,0.0f), new Vector2(magnitude/20.0f,1.0f), new Vector2(0.0f,1.0f),
                                                    new Vector2(0.0f,0.0f), new Vector2(magnitude/20.0f,0.0f), new Vector2(magnitude/20.0f,0.1f), new Vector2(0.0f,0.1f),
                                                    new Vector2(0.0f,0.0f), new Vector2(0.1f,0.0f), new Vector2(0.1f,1.0f), new Vector2(0.0f,1.0f),
                                                    new Vector2(0.0f,0.0f), new Vector2(0.1f,0.0f), new Vector2(0.1f,1.0f), new Vector2(0.0f,1.0f),
                                                   };

                Mesh mesh = new Mesh();
                mesh.vertices = vertices;
                mesh.triangles = triangles;
                mesh.uv = UVcoords;

                MeshFilter meshFilter = Wall.GetComponent<MeshFilter>();
                meshFilter.mesh = mesh;

                MeshCollider meshCollider = Wall.GetComponent<MeshCollider>();
                meshCollider.sharedMesh = mesh;

                MeshRenderer meshRenderer = Wall.GetComponent<MeshRenderer>();
                meshRenderer.material = barrierMaterial;
                BarrierElements.Add(Wall);
            }
        }
        private void generateFence(Way way)
        {
            for (int i = 0; i < way.nodes.Count-1; i++)
            {

                Vector3 differVec = way.nodes[i+1].meterPosition - way.nodes[i].meterPosition;
                float fenceWidth = differVec.magnitude;
                int poleCount = (int)Math.Round(fenceWidth / 5.0f) -1;
                float delta = fenceWidth / (float)(poleCount +1);
                for(int k = 1 ; k <= poleCount ; k++)
                {
                    GameObject obj = (GameObject)MonoBehaviour.Instantiate(Resources.Load("Prefabs/Barrier/Fence/FencePole"));
                    obj.transform.parent = BarrierContainer.transform;
                    obj.transform.position = way.nodes[i].meterPosition + differVec * ((k *delta)/fenceWidth) + new Vector3(0.0f, 1.0f, 0.0f);
                    BarrierElements.Add(obj);
                }

                GameObject fencePlane = new GameObject("Plane", typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));
                fencePlane.AddComponent<BarrierMouseHandler>();
                fencePlane.transform.parent = BarrierContainer.transform;

                Vector3[] vertices = new Vector3[] { way.nodes[i].meterPosition,
                                                     way.nodes[i+1].meterPosition,
                                                     way.nodes[i+1].meterPosition + new Vector3(0.0f,height,0.0f),
                                                     way.nodes[i].meterPosition + new Vector3(0.0f, height, 0.0f)};
                int[] triangles = new int[] { 0,1,2,2,3,0,0,3,2,2,1,0};
                Vector2[] UVcoords = new Vector2[] {new Vector2(0.0f,0.0f), new Vector2(fenceWidth,0.0f),
                                                  new Vector2(fenceWidth,2.0f), new Vector2(0.0f,2.0f)};

                Mesh mesh = new Mesh();
                mesh.vertices = vertices;
                mesh.triangles = triangles;
                mesh.uv = UVcoords;

                MeshFilter meshFilter = fencePlane.GetComponent<MeshFilter>();
                meshFilter.mesh = mesh;

                MeshCollider meshCollider = fencePlane.GetComponent<MeshCollider>();
                meshCollider.sharedMesh = mesh;

                MeshRenderer meshRenderer = fencePlane.GetComponent<MeshRenderer>();
                meshRenderer.material = barrierMaterial;
                BarrierElements.Add(fencePlane);
            }

            for (int i = 0 ; i < way.nodes.Count; i++)
            {
                GameObject obj = (GameObject)MonoBehaviour.Instantiate(Resources.Load("Prefabs/Barrier/Fence/FencePole"));
                obj.name = "FencePole";
                obj.transform.parent = BarrierContainer.transform;
                obj.transform.position = way.nodes[i].meterPosition + new Vector3(0.0f, height/2.0f, 0.0f);
                BarrierElements.Add(obj);
            }
        }
 private void generateBarrier(Way way)
 {
     switch (type)
     {
         case BarrierType.fence:
             generateFence(way);
             break;
         case BarrierType.cityWall:
         case BarrierType.retaining_wall:
         case BarrierType.wall:
             generateWall(way);
             break;
         default :
             generateWall(way);
             break;
     }
 }
        private Way readWay(XmlNode way)
        {
            Way w = new Way();
            w.isArea = false;
            w.id = way.Attributes[0].Value;
            w.nodes = new List<Node>();
            w.tags = new List<Tag>();

            foreach(XmlNode child in way.ChildNodes)
            {
            if(child.Name == "nd")
            {
                string refid = child.Attributes[0].Value;
                w.nodes.Add(nodeList.Find(item => item.id == refid));
            }
            else if (child.Name == "tag")
            {
                w.tags.Add(readTag(child));
                if (w.tags[w.tags.Count-1].k == "area")
                    w.isArea = true;
            }
            }

            w.type = ItemEnumerator.getWayTpe(w);

            return w;
        }
 public Way(Way w)
 {
     this.type = w.type;
     this.id = w.id;
     this.isArea = w.isArea;
     this.tags = new List<Tag>(w.tags);
     this.nodes = new List<Node>(w.nodes);
 }
        private bool getWayOrientation(Way way)
        {
            float result = 0.0f;

            for(int k = 0 ; k < way.nodes.Count-1 ; k++)
            {
                result += (way.nodes[k + 1].lon - way.nodes[k].lon) * (way.nodes[k + 1].lat + way.nodes[k].lat);
            }
            return (result < 0.0f);
        }
        private void createRoof(Way way,GameObject roof)
        {
            Vector2[] vertices2D = new Vector2[way.nodes.Count-1];

            for(int k=0 ; k < way.nodes.Count-1; k++)
                vertices2D[k] = new Vector2(way.nodes[k].meterPosition.x, way.nodes[k].meterPosition.z);

            // Use the triangulator to get indices for creating triangles
            Triangulator tr = new Triangulator(vertices2D);
            int[] indices = tr.Triangulate();

            //Create the Vector3 vertices
            Vector3[] vertices = new Vector3[vertices2D.Length];
            for (int i = 0; i < vertices.Length; i++)
                vertices[i] = new Vector3(vertices2D[i].x,equalizedBuildingHeight,vertices2D[i].y);

            Vector3[] normals = new Vector3[vertices2D.Length];
            for (int i = 0; i < normals.Length; i++)
                normals[i] = new Vector3(0.0f, 1.0f, 0.0f);

            Mesh msh = new Mesh();
            msh.vertices = vertices;
            msh.triangles = indices;
            msh.normals = normals;
            MeshFilter meshFilter = roof.GetComponent<MeshFilter>();
            meshFilter.mesh = msh;

            MeshRenderer meshRenderer = roof.GetComponent<MeshRenderer>();
            meshRenderer.material = (Material)Resources.Load("Materials/Building/Mat_Roof", typeof(Material));
        }
        private float assingBuildingTopLevel(Way way)
        {
            float equalized = 100000.0f;

            for(int i=0 ; i < way.nodes.Count;i++)
            {
                if (way.nodes[i].meterPosition.y < equalized)
                    equalized = way.nodes[i].meterPosition.y;
            }

            return equalized + buildingHeight;
        }