public float AngleWithRoad(GORoadFeature r)
        {
            Vector3 dir1 = Vector3.zero;             //this
            Vector3 dir2 = Vector3.zero;             //other

            if (r.startingPoint.Equals(endingPoint))
            {
                dir1 = convertedGeometry [convertedGeometry.Count - 2] - endingPoint;
                dir2 = r.convertedGeometry[1] - r.startingPoint;
            }
            else if (r.endingPoint.Equals(startingPoint))
            {
                dir2 = r.convertedGeometry [r.convertedGeometry.Count - 2] - r.endingPoint;
                dir1 = convertedGeometry[1] - startingPoint;
            }
            else if (r.startingPoint.Equals(startingPoint))
            {
                dir1 = convertedGeometry[1] - startingPoint;
                dir2 = r.convertedGeometry[1] - r.startingPoint;
            }
            else if (r.endingPoint.Equals(endingPoint))
            {
                dir1 = convertedGeometry [convertedGeometry.Count - 2] - endingPoint;
                dir2 = r.convertedGeometry [r.convertedGeometry.Count - 2] - r.endingPoint;
            }

            float angle = Vector3.Angle(dir1, dir2);

            return(angle);
        }
        public GORoadFeature(GORoadFeature f)
        {
            name          = f.name;
            featureIndex  = f.featureIndex;
            goFeatureType = f.goFeatureType;
            properties    = f.properties;
            attributes    = f.attributes;
            layer         = f.layer;
            goTile        = f.goTile;

            //After editing the feature in layer subclasses.

            //		public string kind;
            kind             = f.kind;
            renderingOptions = f.renderingOptions;
            detail           = f.detail;
            sort             = f.sort;
            y            = f.y;
            height       = f.height;
            featureIndex = f.featureIndex;
            layerIndex   = f.layerIndex;
            featureCount = f.featureCount;

            isBridge = f.isBridge;
            isTunnel = f.isTunnel;
            isLink   = f.isLink;
        }
Exemple #3
0
        public static IList MergeRoad(IList roads, GORoadFeature r)
        {
            if (r.convertedGeometry == null || r.convertedGeometry.Count == 0)
            {
                return(roads);
            }


            r.startingPoint = r.convertedGeometry [0];
            r.endingPoint   = r.convertedGeometry [r.convertedGeometry.Count - 1];

            List <GORoadFeature> m = r.FindRoadsMatching(roads);

            if (m.Count == 0)
            {
                r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData(r);
                roads.Add(r);
                return(roads);
            }

            List <GORoadFeature> toRemove = r.Merge(m);


//			roadsCasted = roadsCasted.Except (toRemove).ToList();
//
//			r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData (r);
//			roads.Add (r);

            return(roads);
        }
Exemple #4
0
        public IEnumerator BuildLayer(GOParsedLayer parsedLayer, bool delayedLoad)
        {
            GOLayer goLayer = parsedLayer.goLayer;

            Profiler.BeginSample("[GoMap] [BuildLayer] game object");
            GameObject parent = null;

            parent                  = new GameObject();
            parent.name             = parsedLayer.name;
            parent.transform.parent = this.transform;
            if (parsedLayer.goLayer != null)
            {
                parent.SetActive(!goLayer.startInactive);
            }
            else
            {
                parent.SetActive(!map.pois.startInactive);
            }

            Profiler.EndSample();

            int featureCount = parsedLayer.goFeatures.Count;

            if (featureCount == 0)
            {
                yield break;
            }

            IList iList = new List <GOFeature> ();

            for (int i = 0; i < featureCount; i++)
            {
                GOFeature goFeature = (GOFeature)parsedLayer.goFeatures [i];

                if (goFeature.goFeatureType == GOFeatureType.Undefined || goFeature.goFeatureType == GOFeatureType.MultiPoint)
                {
                    continue;
                }

                if (goFeature.goFeatureType == GOFeatureType.Point || goFeature.goFeatureType == GOFeatureType.Label)                  //POIS
                {
                    goFeature.parent = parent;
                    iList.Add(goFeature);
                    continue;
                }

                if (goLayer.useOnly.Length > 0 && !goLayer.useOnly.Contains(goFeature.kind))
                {
                    continue;
                }
                if (goLayer.avoid.Length > 0 && goLayer.avoid.Contains(goFeature.kind))
                {
                    continue;
                }

                if (goLayer.layerType == GOLayer.GOLayerType.Roads)
                {
                    if (goFeature.goFeatureType != GOFeatureType.Line && goFeature.goFeatureType != GOFeatureType.MultiLine)
                    {
                        continue;
                    }

                    GORoadFeature grf = (GORoadFeature)goFeature;
                    if ((grf.isBridge && !goLayer.useBridges) || (grf.isTunnel && !goLayer.useTunnels) || (grf.isLink && !goLayer.useBridges))
                    {
                        continue;
                    }
                }

                goFeature.parent = parent;

                iList.Add(goFeature);
            }

//			Profiler.BeginSample("[GoMap] [BuildLayer] merge roads");
//			if (goLayer.layerType == GOLayer.GOLayerType.Roads) {
//				iList = GORoadFeature.MergeRoads (iList);
//			}
//			Profiler.EndSample ();

            int n = 100;

            for (int i = 0; i < iList.Count; i += n)
            {
                for (int k = 0; k < n; k++)
                {
                    if (i + k >= iList.Count)
                    {
//						yield return null;
                        break;
                    }

                    GOFeature   r       = (GOFeature)iList [i + k];
                    IEnumerator routine = r.BuildFeature(this, delayedLoad);

                    if (routine != null)
                    {
                        if (Application.isPlaying)
                        {
                            StartCoroutine(routine);
                        }
                        else
                        {
                            GORoutine.start(routine, this);
                        }
                    }
                }
//				yield return null;
            }
//
//			yield return null;
        }
        public override GOFeature EditFeatureData(GOFeature feature)
        {
            feature.name = (string)feature.properties ["name"];
            if (feature.goFeatureType == GOFeatureType.Point)
            {
                return(feature);
            }

            if (feature.GetType() == typeof(GORoadFeature))
            {
                GORoadFeature grf = (GORoadFeature)feature;

                grf.kind = GOEnumUtils.MapzenToKind((string)grf.properties ["kind"]);
                if (grf.properties.Contains("kind_detail"))                   //Mapzen
                {
                    grf.detail = (string)grf.properties ["kind_detail"];
                }

                grf.isBridge = grf.properties.Contains("is_bridge") && Convert.ToBoolean(grf.properties ["is_bridge"]);
                grf.isTunnel = grf.properties.Contains("is_tunnel") && Convert.ToBoolean(grf.properties ["is_tunnel"]);
                grf.isLink   = grf.properties.Contains("is_link") && Convert.ToBoolean(grf.properties ["is_link"]);
            }
            else
            {
                feature.kind = GOEnumUtils.MapzenToKind((string)feature.properties ["kind"]);
                if (feature.properties.Contains("kind_detail"))                   //Mapzen
                {
                    feature.kind = GOEnumUtils.MapzenToKind((string)feature.properties ["kind_detail"]);
                }
            }

            //			goFeature.name = Convert.ToString( properties ["id"]);

            feature.setRenderingOptions();

            Int64 sort = 0;

            if (feature.properties.Contains("sort_rank"))
            {
                sort = Convert.ToInt64(feature.properties ["sort_rank"]);
            }
            else if (feature.properties.Contains("sort_key"))
            {
                sort = Convert.ToInt64(feature.properties ["sort_key"]);
            }
            feature.y    = sort / 1000.0f;
            feature.sort = sort;

            feature.height = feature.renderingOptions.polygonHeight;

            if (feature.layer.useRealHeight && feature.properties.Contains("height"))
            {
                double h = Convert.ToDouble(feature.properties["height"]);
                feature.height = (float)h;
            }

            if (feature.layer.useRealHeight && feature.properties.Contains("min_height"))
            {
                double hm = Convert.ToDouble(feature.properties["min_height"]);
                feature.y = (float)hm;
                if (feature.height >= hm)
                {
                    feature.y      = (float)hm;
                    feature.height = (float)feature.height - (float)hm;
                }
            }


            return(feature);
        }
Exemple #6
0
        private void ParseGOLayerToList(List <GOParsedLayer> list, VectorTile vt, GOLayer layer)
        {
            string[] lyrs = tile.GetLayersStrings(layer).Split(',');

            foreach (string l in lyrs)
            {
                VectorTileLayer lyr = vt.GetLayer(l);
                if (lyr != null)
                {
                    int featureCount = lyr.FeatureCount();

                    if (featureCount == 0)
                    {
                        continue;
                    }

                    GOParsedLayer pl = new GOParsedLayer();
                    pl.name       = lyr.Name;
                    pl.goLayer    = layer;
                    pl.goFeatures = new List <GOFeature> ();

                    int indexOfLayer = vt.LayerNames().IndexOf(lyr.Name);

                    for (int i = 0; i < featureCount; i++)
                    {
                        VectorTileFeature vtf = lyr.GetFeature(i);

                        List <List <LatLng> > geomWgs = vtf.GeometryAsWgs84((ulong)goTile.zoomLevel, (ulong)goTile.tileCoordinates.x, (ulong)goTile.tileCoordinates.y, 0);

                        GOFeature gf;
                        if (layer.layerType == GOLayer.GOLayerType.Roads)
                        {
                            gf = new GORoadFeature();
                        }
                        else
                        {
                            gf = new GOFeature();
                        }

                        gf.properties    = vtf.GetProperties();
                        gf.attributes    = GOFeature.PropertiesToAttributes(gf.properties);
                        gf.goFeatureType = vtf.GOFeatureType(geomWgs);
                        gf.layer         = layer;
                        gf.featureIndex  = (Int64)i;
                        gf.layerIndex    = indexOfLayer;
                        gf.featureCount  = featureCount;
                        gf        = tile.EditFeatureData(gf);
                        gf.goTile = goTile;
//							gf.setRenderingOptions ();
                        gf.ConvertAttributes();

                        if (geomWgs.Count > 0)
                        {
                            switch (gf.goFeatureType)
                            {
                            case GOFeatureType.Line:
                                gf.geometry = geomWgs [0];
                                gf.ConvertGeometries();
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.Polygon:
                                gf.geometry = geomWgs[0];
                                gf.ConvertGeometries();
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.MultiLine:
                                foreach (IList geometry in geomWgs)
                                {
                                    float     indexMulti = (((float)geomWgs.IndexOf((List <LatLng>)geometry) + 1) * (i + 1) / geomWgs.Count);
                                    GOFeature gfm;
                                    if (layer.layerType == GOLayer.GOLayerType.Roads)
                                    {
                                        gfm = new GORoadFeature((GORoadFeature)gf);
                                    }
                                    else
                                    {
                                        gfm = new GOFeature(gf);
                                    }

//									gfm.index = indexMulti;
                                    gfm.geometry = geometry;
                                    gfm.ConvertGeometries();
                                    AddFatureToList(gfm, pl.goFeatures);
                                }
                                break;

                            case GOFeatureType.MultiPolygon:
                                foreach (IList geometry in geomWgs)
                                {
                                    List <Vector3>         convertedSubject = null;
                                    List <List <Vector3> > convertedClips   = new List <List <Vector3> >();

                                    for (int j = 0; j < geomWgs.Count; j++)                                     //Clip ascending

                                    {
                                        IList          p          = geomWgs [j];
                                        List <Vector3> convertedP = GOFeature.CoordsToVerts(p, layer.layerType == GOLayer.GOLayerType.Buildings);
                                        if (GOFeature.IsClockwise(convertedP))
                                        {
                                            convertedSubject = convertedP;
                                        }
                                        else
                                        {
                                            //Add clip
                                            convertedClips.Add(convertedP);
                                        }
                                        //Last one
                                        if (j == geomWgs.Count - 1 || (j < geomWgs.Count - 1 && GOFeature.IsGeoPolygonClockwise(geomWgs [j + 1]) && convertedSubject != null))
                                        {
                                            GOFeature gfm = new GOFeature(gf);
//											gfm.index = (i +1)*j;
                                            gfm.convertedGeometry = convertedSubject;
                                            gfm.clips             = convertedClips;
                                            AddFatureToList(gfm, pl.goFeatures);

                                            convertedSubject = null;
                                            convertedClips   = new List <List <Vector3> >();
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }

                    if (goTile.combineFeatures)
                    {
                        pl = GOCombineFeatures.Combine(pl);
                    }

                    list.Add(pl);
                }
            }
        }
        public List <GORoadFeature> Merge(IList roads)
        {
            List <GORoadFeature> merged = new List <GORoadFeature>();

            for (int i = 0; i < roads.Count; i++)
            {
                GORoadFeature r = (GORoadFeature)roads [i];

                if (r.startingPoint.Equals(endingPoint))
                {
                    endingPoint = r.endingPoint;
                    r.convertedGeometry.RemoveAt(0);
                    convertedGeometry.AddRange(r.convertedGeometry);
                    r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData(r);
                    preloadedMeshData   = GOFeatureMeshBuilder.PreloadFeatureData(this);

                    merged.Add(r);
                }
                else if (r.endingPoint.Equals(startingPoint))
                {
                    startingPoint = r.startingPoint;
                    convertedGeometry.RemoveAt(0);
                    r.convertedGeometry.AddRange(convertedGeometry);
                    convertedGeometry   = r.convertedGeometry;
                    r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData(r);
                    preloadedMeshData   = GOFeatureMeshBuilder.PreloadFeatureData(this);

                    merged.Add(r);
                }
                else if (r.startingPoint.Equals(startingPoint))
                {
                    startingPoint = r.endingPoint;
                    r.convertedGeometry.Reverse();
                    convertedGeometry.RemoveAt(0);
                    r.convertedGeometry.AddRange(convertedGeometry);
                    convertedGeometry   = r.convertedGeometry;
                    r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData(r);
                    preloadedMeshData   = GOFeatureMeshBuilder.PreloadFeatureData(this);

                    merged.Add(r);
                }
                else if (r.endingPoint.Equals(endingPoint))
                {
                    endingPoint = r.startingPoint;
                    r.convertedGeometry.Reverse();
                    r.convertedGeometry.RemoveAt(0);
                    convertedGeometry.AddRange(r.convertedGeometry);
                    r.preloadedMeshData = GOFeatureMeshBuilder.PreloadFeatureData(r);
                    preloadedMeshData   = GOFeatureMeshBuilder.PreloadFeatureData(this);

                    merged.Add(r);
                }

                if (name == "" && r.name != "")
                {
                    name = r.name;
                }
            }


            return(merged);
        }
Exemple #8
0
        public IEnumerator BuildLayer(VectorTileLayer layerData, GOLayer layer, bool delayedLoad)
        {
            Profiler.BeginSample("[GoMap] [BuildLayer] game object");
            GameObject parent = null;

            if (transform.Find(layer.name) == null)
            {
                parent                  = new GameObject();
                parent.name             = layer.name;
                parent.transform.parent = this.transform;
                parent.SetActive(!layer.startInactive);
            }
            else
            {
                parent = transform.Find(layer.name).gameObject;
            }
            Profiler.EndSample();

            int featureCount = layerData.FeatureCount();

            if (featureCount == 0)
            {
                yield break;
            }

            List <GOFeature> stack = new List <GOFeature> ();

            //Caching variables..
            VectorTileFeature           feature;
            List <List <LatLng> >       geomWgs84;    //= new List<List<LatLng>>();
            GOFeature                   goFeature;
            Dictionary <string, object> properties        = null;
            List <KeyValue>             attributes        = null;
            List <Vector3>              convertedGeometry = null;


            for (int i = 0; i < featureCount; i++)
            {
                feature    = layerData.GetFeature(i);
                properties = feature.GetProperties();
                geomWgs84  = feature.GeometryAsWgs84((ulong)map.zoomLevel, (ulong)tileCoordinates.x, (ulong)tileCoordinates.y, 0);
                attributes = GOFeature.PropertiesToAttributes(properties);
                if (geomWgs84.Count > 0)
                {
                    convertedGeometry = GOFeature.CoordsToVerts(geomWgs84[0], false);
                }

                //get the feature (here is the actual protobuf conversion)
                goFeature = ParseFeatureData(feature, properties, layer, -1, -1);

                //8-11mb
                if (layer.useOnly.Length > 0 && !layer.useOnly.Contains(goFeature.kind))
                {
                    continue;
                }
                if (layer.avoid.Length > 0 && layer.avoid.Contains(goFeature.kind))
                {
                    continue;
                }

                if (layer.layerType == GOLayer.GOLayerType.Roads)
                {
                    GORoadFeature grf = (GORoadFeature)goFeature;
                    if ((grf.isBridge && !layer.useBridges) || (grf.isTunnel && !layer.useTunnels) || (grf.isLink && !layer.useBridges))
                    {
                        continue;
                    }
                }

                GOFeatureType gotype = feature.GOFeatureType(geomWgs84);

                if (gotype == GOFeatureType.Undefined || feature.GeometryType == GeomType.POINT)
                {
                    continue;
                }
                if (feature.GeometryType == GeomType.POLYGON && layer.layerType == GOLayer.GOLayerType.Roads)
                {
                    continue;
                }

                Int64 index = vt.LayerNames().IndexOf(layerData.Name) + 1;

                GOFeature gf;
                Profiler.BeginSample("[GoMap] [BuildLayer] IF");


                if (gotype == GOFeatureType.MultiLine || (gotype == GOFeatureType.Polygon && !layer.isPolygon))
                {
                    Profiler.BeginSample("[GoMap] [BuildLayer] multi line");
                    foreach (IList geometry in geomWgs84)
                    {
                        float indexMulti = ((float)geomWgs84.IndexOf((List <LatLng>)geometry) / geomWgs84.Count);
                        gf            = ParseFeatureData(feature, properties, layer, Convert.ToInt64(i) + indexMulti, index);
                        gf.geometry   = geometry;
                        gf.layer      = layer;
                        gf.parent     = parent;
                        gf.properties = properties;
                        gf.ConvertGeometries();
                        gf.attributes    = attributes;
                        gf.goFeatureType = GOFeatureType.MultiLine;
                        stack.Add(gf);
                    }
                    Profiler.EndSample();
                }

                else if (gotype == GOFeatureType.Line)
                {
                    Profiler.BeginSample("[GoMap] [BuildLayer] line");

                    gf                   = ParseFeatureData(feature, properties, layer, Convert.ToInt64(i), index);
                    gf.geometry          = geomWgs84 [0];
                    gf.layer             = layer;
                    gf.parent            = parent;
                    gf.properties        = properties;
                    gf.convertedGeometry = convertedGeometry;
                    gf.attributes        = attributes;
                    gf.index             = (Int64)i + vt.LayerNames().IndexOf(layerData.Name);
                    gf.goFeatureType     = GOFeatureType.Line;
                    if (geomWgs84.Count == 0)
                    {
                        continue;
                    }

                    stack.Add(gf);

                    Profiler.EndSample();
                }

                else if (gotype == GOFeatureType.Polygon)
                {
                    Profiler.BeginSample("[GoMap] [BuildLayer] polygon");

                    gf                   = ParseFeatureData(feature, properties, layer, Convert.ToInt64(i), index);
                    gf.geometry          = geomWgs84 [0];
                    gf.layer             = layer;
                    gf.parent            = parent;
                    gf.properties        = properties;
                    gf.convertedGeometry = convertedGeometry;
                    gf.attributes        = attributes;
                    gf.index             = (Int64)i + vt.LayerNames().IndexOf(layerData.Name);
                    gf.goFeatureType     = GOFeatureType.Polygon;

                    stack.Add(gf);

                    Profiler.EndSample();
                }

                else if (gotype == GOFeatureType.MultiPolygon)
                {
                    Profiler.BeginSample("[GoMap] [BuildLayer] multi polygon");

//					GameObject multi = new GameObject ("MultiPolygon");
//					multi.transform.parent = parent.transform;

                    IList subject = null;
                    IList clips   = new List <List <LatLng> >();

                    for (int j = 0; j < geomWgs84.Count; j++)                     //Clip ascending

                    {
                        IList p = geomWgs84 [j];
                        if (GOFeature.IsGeoPolygonClockwise(p))
                        {
                            subject = p;
                        }
                        else
                        {
                            //Add clip
                            clips.Add(p);
                        }
                        //Last one
                        if (j == geomWgs84.Count - 1 || (j < geomWgs84.Count - 1 && GOFeature.IsGeoPolygonClockwise(geomWgs84 [j + 1]) && subject != null))
                        {
                            gf            = ParseFeatureData(feature, properties, layer, Convert.ToInt64(i), index);
                            gf.geometry   = subject;
                            gf.clips      = clips;
                            gf.layer      = layer;
                            gf.parent     = parent;
                            gf.properties = properties;
                            gf.ConvertGeometries();
                            gf.attributes    = attributes;
                            gf.index         = (Int64)i + vt.LayerNames().IndexOf(layerData.Name);
                            gf.goFeatureType = GOFeatureType.MultiPolygon;

                            stack.Add(gf);

                            subject = null;
                            clips   = new List <List <LatLng> >();
                        }
                    }
                    Profiler.EndSample();
                }
                Profiler.EndSample();
            }

            Profiler.BeginSample("[GoMap] [BuildLayer] merge roads");
            IList iStack = (IList)stack;

            if (layer.layerType == GOLayer.GOLayerType.Roads)
            {
                iStack = GORoadFeature.MergeRoads(iStack);
//				Debug.Log ("Roads: "+stack.Count+" Merged: "+iStack.Count);
            }
            Profiler.EndSample();

            int n = 25;

            for (int i = 0; i < iStack.Count; i += n)
            {
                for (int k = 0; k < n; k++)
                {
                    if (i + k >= iStack.Count)
                    {
                        yield return(null);

                        break;
                    }

                    GOFeature   r       = (GOFeature)iStack [i + k];
                    IEnumerator routine = r.BuildFeature(this, delayedLoad);
                    if (routine != null)
                    {
                        if (Application.isPlaying)
                        {
                            StartCoroutine(routine);
                        }
                        else
                        {
                            GORoutine.start(routine, this);
                        }
                    }
                }
                yield return(null);
            }

            Resources.UnloadUnusedAssets();

            yield return(null);
        }
Exemple #9
0
        public GOFeature ParseFeatureData(IDictionary properties, GOLayer layer)
        {
            GOFeature goFeature;

            if (layer.layerType == GOLayer.GOLayerType.Roads)
            {
                goFeature = new GORoadFeature();

                goFeature.kind = GOEnumUtils.MapzenToKind((string)properties ["kind"]);
                if (properties.Contains("kind_detail"))                   //Mapzen
                {
                    goFeature.detail = (string)properties ["kind_detail"];
                }

                ((GORoadFeature)goFeature).isBridge = properties.Contains("is_bridge") && properties ["is_bridge"].ToString() == "True";
                ((GORoadFeature)goFeature).isTunnel = properties.Contains("is_tunnel") && properties ["is_tunnel"].ToString() == "True";
                ((GORoadFeature)goFeature).isLink   = properties.Contains("is_link") && properties ["is_link"].ToString() == "True";
            }
            else
            {
                goFeature      = new GOFeature();
                goFeature.kind = GOEnumUtils.MapzenToKind((string)properties ["kind"]);
                if (properties.Contains("kind_detail"))                   //Mapzen
                {
                    goFeature.kind = GOEnumUtils.MapzenToKind((string)properties ["kind_detail"]);
                }
            }

            goFeature.name = (string)properties ["name"];

            Int64 sort = 0;

            if (properties.Contains("sort_rank"))
            {
                sort = (Int64)properties ["sort_rank"];
            }
            else if (properties.Contains("sort_key"))
            {
                sort = (Int64)properties ["sort_key"];
            }
            goFeature.y    = sort / 1000.0f;
            goFeature.sort = sort;

            goFeature.height = layer.defaultRendering.polygonHeight;

            if (layer.useRealHeight && properties.Contains("height"))
            {
                double h = Convert.ToDouble(properties["height"]);
                goFeature.height = (float)h;
            }

            if (layer.useRealHeight && properties.Contains("min_height"))
            {
                double hm = Convert.ToDouble(properties["min_height"]);
                goFeature.y = (float)hm;
                if (goFeature.height >= hm)
                {
                    goFeature.y      = (float)hm;
                    goFeature.height = (float)goFeature.height - (float)hm;
                }
            }


            return(goFeature);
        }