Beispiel #1
0
        /// <summary>
        /// Initializes the Singleton instance
        /// </summary>
        internal void Initialize()
        {
            //StyleDeclaration style = StyleManager.Instance.GetStyleDeclaration("global");
            //if (null == style)
            //{
            //    style = new StyleDeclaration();
                
            //    var dict = new Dictionary<string, object> { { "foo", "bar" } };
            //    style.Factory = new StyleTableValuesFactory(dict); // ?? DefaultValues ???????

            //    StyleManager.Instance.SetStyleDeclaration("global", style, false);
            //}

            var styleManager = StyleManager.Instance;
            var selector = new Selector("global", null, null);
            var mergedStyle = styleManager.GetMergedStyleDeclaration("global");
            var style = new StyleDeclaration(selector, mergedStyle == null);

            if (style.Set1 == null)
            {
                //Debug.Log("Creating DefaultValues for " + selector);
                var dict = new StyleTable(); // { { "foo", "bar" } };
                style.Set1 = new StyleTableValuesFactory(dict);
            }

            if (null != mergedStyle && 
                (null == mergedStyle.Set1 ||
                style.Set1.Produce().Equals(mergedStyle.Set1.Produce())))
            {
                styleManager.SetStyleDeclaration(style.SelectorString, style, false);
            }

            //Debug.Log("Global style initialized: " + styleManager.GetStyleDeclaration("global"));
        }
 /// <summary>
 /// Reads the serialized declaration and extracts key/value pairs
 /// </summary>
 /// <returns></returns>
 public StyleTable Produce()
 {
     StyleTable table = new StyleTable();
     foreach (KeyValuePair<string, object> pair in _table)
     {
         table.Add(pair.Key, pair.Value);
     }
     return table;
 }
 /// <summary>
 /// Returns the dictionary of name/value pairs<br/>
 /// Used by component traversers
 /// </summary>
 /// <returns></returns>
 public StyleTable ToStyleTable()
 {
     StyleTable styleTable = new StyleTable();
     foreach (StyleProperty property in Properties)
     {
         styleTable.Add(property.Name, property.Value);
     }
     return styleTable;
 } 
        /// <summary>
        /// Returns the dictionary of name/value pairs<br/>
        /// Used by component traversers
        /// </summary>
        /// <returns></returns>
        public StyleTable ToStyleTable()
        {
            StyleTable styleTable = new StyleTable();

            foreach (StyleProperty property in Properties)
            {
                styleTable.Add(property.Name, property.Value);
            }
            return(styleTable);
        }
Beispiel #5
0
 internal override StyleTable AddStyleToProtoChain(StyleTable chain, object target)
 {
     // If we have a local _style, then add only it to the chain. It will
     // take are of adding its parent to the chain.
     // If then is no _style, but a _parentStyle, then add the parent Style
     // to the chain.
     if (null != _style)
     {
         return(_style.AddStyleToProtoChain(chain, target /*, filterMap*/));
     }
     //if (null != _parentStyle)
     //    return _parentStyle.AddStyleToProtoChain(chain, target/*, filterMap*/);
     return(chain);
 }
        /// <summary>
        /// Reads the component metadata and extracts key/value pairs
        /// </summary>
        /// <returns></returns>
        public StyleTable Produce()
        {
            //Debug.Log(string.Format("DefaultValuesFactory->Produce [{0}]", _componentType));

            if (null == _cached)
            {
                _cached = new StyleTable();

                var attributes = StyleReflector.GetStyleAttributes(_componentType);

#if DEBUG
                if (null != StyleProtoChain.TYPE_TO_MONITOR)
                {
                    if (_componentType == StyleProtoChain.TYPE_TO_MONITOR)
                    {
                        StringBuilder sb = new StringBuilder();
                        foreach (StyleAttribute attribute in attributes)
                        {
                            sb.AppendLine(string.Format("[{0}, {1}]", attribute.Name, attribute.GetDefault()));
                        }
                        Debug.Log(string.Format(@"DefaultValuesFactory->Produced [{0}]
{1}", _componentType, sb));
                    }
                }
#endif

                foreach (StyleAttribute attribute in attributes)
                {
                    /**
                     * 1. Validate proxy
                     * */
                    ValidateAttribute(attribute);

                    /**
                     * 2. Extract possible value
                     * */
                    var def = attribute.GetDefault(); // ovdje je bio bug kod boja - nije se koristilo GetDefault(), već samo Default
                    if (null != def)
                        _cached.Add(attribute.Name, def);
                }
            }

            return (StyleTable) _cached.Clone();
        }
        /// <summary>
        /// Reads the serialized declaration and extracts key/value pairs
        /// </summary>
        /// <returns></returns>
        public StyleTable Produce()
        {
            if (null == _cached)
            {
                _cached = new StyleTable();

//#if DEBUG
//                        StringBuilder sb = new StringBuilder();
//                        foreach (StyleProperty property in _styleSheetDeclaration.Properties)
//                        {
//                            sb.AppendLine(string.Format("[{0}, {1}]", property.Name, property.Value));
//                        }
//                        Debug.Log(string.Format(@"StyleSheetValuesFactory->Produced
//{0}", sb));
//#endif

                foreach (StyleProperty property in _styleSheetDeclaration.Properties)
                {
                    _cached.Add(property.Name, property.Value);
                }
            }

            return (StyleTable)_cached.Clone();
        }
		/**
		 *  
		 */
		private void ClearStyleAttr(string styleProp)
		{
			// Put "undefined" into our overrides Array
			if (null == _overrides)
				_overrides = new StyleTable();

			_overrides[styleProp] = UNDEFINED;
			
			// Remove the property from all our clones
			foreach (var clone in _clones)
			{
				clone.Remove(styleProp);
			}
		}
// ReSharper restore UnassignedField.Global
#endif

		///<summary>
		///</summary>
		///<param name="chain">Replikativni Dictionary</param>
		///<param name="target"></param>
		///<returns></returns>
		internal virtual StyleTable AddStyleToProtoChain(StyleTable chain, object target/*, object filterMap*/)
		{
			//Debug.Log("AddStyleToProtoChain: chain: " + chain + "; target: " + target);

			bool nodeAddedToChain = false;
			//var originalChain = chain;

			//if (filterMap)
			//{
			//    chain = {};
			//}

#if DEBUG
			if (!string.IsNullOrEmpty(DebugId))
			{
				Debug.Log(DebugId + " 0. " + chain);
			}
#endif

			// If there's a defaultFactory for this style sheet,
			// then add the object it produces to the chain.
			if (null != Set1)
			{
				chain = chain.CloneAndOverrideWith(Set1.Produce());
				nodeAddedToChain = true;
			}

#if DEBUG
			if (!string.IsNullOrEmpty(DebugId))
			{
				Debug.Log(DebugId + " 1. " + chain);
			}
#endif

			// If there's a factory for this style sheet,
			// then add the object it produces to the chain.
			if (null != Set2)
			{
				chain = chain.CloneAndOverrideWith(Set2.Produce());
				nodeAddedToChain = true;
			}

#if DEBUG
			if (!string.IsNullOrEmpty(DebugId))
			{
				Debug.Log(DebugId + " 2. " + chain);
			}
#endif

			//Debug.Log("-- chain: " + chain);

			// If someone has called setStyle() on this StyleDeclaration,
			// then some of the values returned from the factory are
			// out-of-date. Overwrite them with the up-to-date values.
			if (null != _overrides)
			{
				// Before we add our overrides to the object at the head of
				// the chain, make sure that we added an object at the head
				// of the chain.
				if (null == Set1 && null == Set2)
				{
					chain = (StyleTable)chain.Clone();
					nodeAddedToChain = true;
				}

				foreach (string p in _overrides.Keys)
				{
					if (!UNDEFINED.Equals(_overrides[p]))
						chain[p] = _overrides[p];
					/*if (UNDEFINED.Equals(_overrides[p]))
						chain.Remove(p);
					else
						chain[p] = _overrides[p];*/
				}
			}

#if DEBUG
			if (!string.IsNullOrEmpty(DebugId))
			{
				Debug.Log(DebugId + " 3. " + chain);
			}
#endif

			#region _complex

			////if (filterMap)
			////{
			//    if (nodeAddedToChain)
			//    {
			//        //Debug.Log("nodeAddedToChain");
			//        //var filteredChain = new Dictionary<string, object>();
			//        //for (string i in chain)
			//        //{
			//        //    if (filterMap[i] != null)
			//        //    {
			//        //        filteredChain[filterMap[i]] = chain[i];
			//        //    }
			//        //} 

			//        //var f = new StyleTableValuesFactory(originalChain);

			//        chain = (StyleTable) originalChain.Clone();

			//        //chain = originalChain;

			//        //chain = filteredChain;
			//        //chain = f.Produce();

			//        //chain[FILTERMAP_PROP] = filterMap;
			//    }
			//    else
			//    {
			//        chain = originalChain;
			//    }
			////}

			#endregion

			if (nodeAddedToChain)
				_clones.Add(chain);

			return chain;
		}
Beispiel #10
0
		/**
		 *  
		 */
		internal StyleTable CreateProtoChainRoot(bool registerClone = true)
		{
			StyleTable root = new StyleTable();

			// If there's a defaultFactory for this style sheet,
			// then add the object it produces to the root.
			if (null != Set1)
			{
				root = root.CloneAndOverrideWith(Set1.Produce());
			}

			// If there's a factory for this style sheet,
			// then add the object it produces to the root.
			if (null != Set2)
			{
				root = root.CloneAndOverrideWith(Set2.Produce());
			}

			if (registerClone)
				_clones.Add(root);
			
			return root;
		}
Beispiel #11
0
		/// <summary>
		/// Private
		/// </summary>
		/// <param name="styleProp"></param>
		/// <param name="value"></param>
		internal void SetLocalStyle(string styleProp, object value)
		{
			//object oldValue = GetStyle(styleProp);

			if (UNDEFINED.Equals(value))
			{
				ClearStyleAttr(styleProp);
				return;
			}

			StyleTable o;

			if (null != Set1)
			{
				o = Set1.Produce();
				if (!o.ContainsKey(styleProp) || o[styleProp] != value) // Defaultni factory nema taj stil ili ga ima ali s različitom vrijednošću
				{
					/**
					 * Defaultni factory ima različitu vrijednost ovog stila, znači radi se o overrideu
					 * Kreirajmo overrides tablicu i u njoj setirajmo stil
					 * */
					if (null == _overrides)
						_overrides = new StyleTable();

					_overrides[styleProp] = value;
				}
				else if (null != _overrides && _overrides.ContainsKey(styleProp)) // Defaultni factory ima taj stil i to sa istom vrijednošću
				{
					/**
					 * Obrišimo ga u overrides tabeli
					 * */
					_overrides.Remove(styleProp);
				}
			}

			if (null != Set2)
			{
				o = Set2.Produce();
				if (!o.ContainsKey(styleProp) || o[styleProp] != value)
				{
					if (null == _overrides)
						_overrides = new StyleTable();

					_overrides[styleProp] = value;
				}
				else if (null != _overrides && _overrides.ContainsKey(styleProp))
				{
					_overrides.Remove(styleProp);
				}
			}

			if (null == Set1 && null == Set2) // Ne postoji niti jedan factory (ni metadata, ni stylesheet)
			{
				if (null == _overrides)
					_overrides = new StyleTable();
				_overrides[styleProp] = value;
			}

			UpdateClones(styleProp, value);
		}
// ReSharper restore UnassignedField.Global
#endif
        /// <summary>
        /// Loads style declarations<br/>
        /// We are actually doing a full process from scratch on each screen resize<br/>
        /// The things that are cached are default styles (reflected) and eDriven stylesheet styles<br/>
        /// Each style declaration is being tested against its media queries<br/>
        /// Only declarations passing the media query are turned into actual CSSStyleDeclarations and are further processed<br/>
        /// </summary>
        internal static void Process()
        {
            var styleManager = StyleManager.Instance;

#if DEBUG
            if (DebugMode)
            {
                Debug.Log("##### Loading style sheets #####");
            }
#endif

            /**
             * 1. Reloading the cache (the cache itself will do a full reload if needed)
             * */
            StyleDeclarationCache.Instance.Load();

            /**
             * 2. Getting ALL the style declarations from the cache
             * */
            List<Serialization.StyleDeclaration> declarations = StyleDeclarationCache.Instance.GetDeclarations();

            if (null == declarations)
                return; // nothing to do here

            int count = 0;
            var list = new List<string>();

            /**
             * 4. Merging (A)
             * We need to group the same declarations together
             * That's because we need - at this stage - to merge declarations for the same component
             * In the StyleDeclaration system, there are no duplicated declarations
             * */
            Dictionary<string, List<Serialization.StyleDeclaration>> groups = new Dictionary<string, List<Serialization.StyleDeclaration>>();
            foreach (Serialization.StyleDeclaration declaration in declarations)
            {
                var mediaQueryPasses = true;
                if (null != declaration.MediaQueries)
                {
                    foreach (MediaQuery query in declaration.MediaQueries)
                    {
                        /* if a single query doesn't pass, do not process this style declaration */
                        try
                        {
#if DEBUG
                            if (DebugMode)
                            {
                                Debug.Log("Query: " + query);
                            }
#endif
                            mediaQueryPasses = MediaQueryManager.Instance.EvaluateQuery(query.Name, query.Value);
#if DEBUG
                            if (DebugMode)
                            {
                                if (!mediaQueryPasses)
                                    Debug.Log("    " + query + " doesn't pass");
                            }
#endif
                            /**
                             * When a single query doesn't pass, break the loop!
                             * (this is the AND operation!)
                             * */
                            if (!mediaQueryPasses)
                                break;

                        }
                        catch (Exception ex)
                        {
                            Debug.LogError(ex.Message);
                        }
                    }
                }
                if (!mediaQueryPasses)
                    continue; // skip

                //declarationsPassingMediaQueries.Add(declaration);
                Selector selector = Selector.BuildSelector(declaration.Type, declaration.Class, declaration.Id);
                var selString = selector.ToString();
                if (!groups.ContainsKey(selString))
                {
                    groups[selString] = new List<Serialization.StyleDeclaration>();
                }
                groups[selString].Add(declaration);

                /**
                    * If we are here, it means the style declaration passes its own media queries
                    * */

                count++;
            }

            /**
             * 5. Merging (B)
             * Mearge declarations from each group together
             * */
            foreach (var key in groups.Keys)
            {
                // check if the group contains declarations (it should, at least one)
                var decls = groups[key];
                if (decls.Count == 0)
                    continue;

                // take the first declaration
                var declaration = decls[0];

                // create selector (same for all the declarations in the group)
                Selector selector = Selector.BuildSelector(declaration.Type, declaration.Class, declaration.Id);

                list.Add(selector.ToString());

                // get the existing or create new declaration
                //StyleDeclaration mergedStyle = styleManager.GetMergedStyleDeclaration(selector.ToString());

                StyleDeclaration style = styleManager.GetStyleDeclaration(selector.ToString());
                if (null == style)
                {
                    style = new StyleDeclaration(selector, true) // register
                    {
                        Module = declaration.Module
                    };
                }

                /*StyleDeclaration style = new StyleDeclaration(selector, mergedStyle == null)
                {
                    Module = declaration.Module
                };*/

                // create (blank) factory
                if (style.Set2 == null)
                {
                    StyleTable mainTable = new StyleTable();
                    style.Set2 = new StyleTableValuesFactory(mainTable);

                    // override the factory with each declaration
                    foreach (Serialization.StyleDeclaration styleDeclaration in decls)
                    {
                        StyleTable styleTable = new StyleTable();
                        foreach (StyleProperty property in styleDeclaration.Properties)
                        {
                            var value = property.Value;

                            /**
                             * Very important:
                             * null == value -> works only in build!
                             * For the editor we need a paralel check: value.GetType() != typeof(Object)
                             * That's because in editor the value isn't null!!!!!
                             * */
                            if (null == value || value.GetType() != typeof(Object))
                            {
                                styleTable.Add(property.Name, value);
                            }
                        }
                        mainTable.OverrideWith(styleTable);
                    }
                }

                //Debug.Log("style: " + style);
            }

            /*Debug.Log(@"!!!! declarationsPassingMediaQueries:
" + ListUtil<StyleDeclaration>.Format(declarationsPassingMediaQueries));*/

#if DEBUG
            if (DebugMode)
            {
                StringBuilder sb = new StringBuilder();
                list.Sort();
                foreach (string name in list)
                {
                    var line = string.Format(@"============== {0} ==============
", name);
                    var decls = styleManager.GetStyleDeclarations(name);
                    if (null != decls)
                        line = string.Format(@"============== {0} [found {1}] ==============
{2}", name, decls.Count, ListUtil<StyleDeclaration>.Format(decls));
                    sb.AppendLine(line);
                }
                Debug.Log(string.Format(@"Style declarations loaded from stylesheet ({0}):
{1}", count, sb));
            }
#endif
        }
Beispiel #13
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ///TODO:    fix crash with "multi" types in a branch for shapefiles, can't create lines in a points layer
            ///         fix mesh/polygon face creation issue on sphere, dropping faces or flipped faces
            ///         fix swtich case for shapfiles so that points and multipoints (eg) are written to the same file. don't use switch anymore, us ifs
            ///         fix sql statements, they don't seem to have an effect.  Need these to work for pulling apart geometry collections.

            ///Gather GHA inputs
            string filename = string.Empty;

            DA.GetData <string>("Vector Data Filename", ref filename);

            string folder = string.Empty;

            DA.GetData <string>("Vector Data Folder", ref folder);
            folder = Path.GetFullPath(folder);
            if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                folder += Path.DirectorySeparatorChar;
            }

            string shpPath = folder + filename + drvExtension;
            ///for more than one geometry type, a list of files for shapefile output needs to be established
            List <string> shpPathList = new List <string>();
            List <string> shpTypeList = new List <string>();

            List <string> fields = new List <string>();

            DA.GetDataList <string>("Fields", fields);

            GH_Structure <GH_String> values = new GH_Structure <GH_String>();

            DA.GetDataTree <GH_String>("Values", out values);

            GH_Structure <IGH_GeometricGoo> gGoo = new GH_Structure <IGH_GeometricGoo>();

            DA.GetDataTree <IGH_GeometricGoo>("Feature Geometry", out gGoo);

            bool export = false;

            DA.GetData <bool>("Export", ref export);

            ///GDAL setup
            RESTful.GdalConfiguration.ConfigureOgr();
            OSGeo.GDAL.Gdal.SetConfigOption("OGR_SKIP", "KML");

            string driverType = drvType;

            //OSGeo.OGR.Driver drv = Ogr.GetDriverByName("LIBKML");// driverType);
            OSGeo.OGR.Driver drv = Ogr.GetDriverByName("GeoJSON");



            if (export == true)
            {
                ///File setup for save
                FileInfo file = new FileInfo(folder);
                file.Directory.Create();

                if (File.Exists(shpPath))
                {
                    drv.DeleteDataSource(shpPath);
                }

                ///Create virtual datasource to be converted later
                ///Using geojson as a flexiblle base file type which can be converted later with ogr2ogr
                DataSource ds = drv.CreateDataSource("/vsimem/out.geojson", null);

                ///Use WGS84 spatial reference
                OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
                dst.SetWellKnownGeogCS("WGS84");
                Transform transform = Heron.Convert.XYZToWGSTransform();

                ///Use OGR catch-all for geometry types
                var gtype = wkbGeometryType.wkbGeometryCollection;

                ///Create layer
                //string[] layerOptions = new string[] { "LIBKML_USE_SCHEMADATA=NO", "LIBKML_USE_SIMPLEFIELD=NO", "LIBKML_ALTITUDEMODE_FIELD=relativeToGround" };
                //string[] layerOptions = new string[] { "LIBKML_STRICT_COMPLIANCE=FALSE" };
                OSGeo.OGR.Layer layer = ds.CreateLayer(filename, dst, gtype, null);
                FeatureDefn     def   = layer.GetLayerDefn();

                ///Add fields to layer
                for (int f = 0; f < fields.Count; f++)
                {
                    OSGeo.OGR.FieldDefn fname = new OSGeo.OGR.FieldDefn(fields[f], OSGeo.OGR.FieldType.OFTString);
                    layer.CreateField(fname, f);
                }

                ///Specific fields for LIBKML for use in Google Earth
                ///See LIBMKL driver for more info https://gdal.org/drivers/vector/libkml.html
                if (drvType == "LIBKML")
                {
                    OSGeo.OGR.FieldDefn kmlFieldAltitudeMode = new OSGeo.OGR.FieldDefn("altitudeMode", OSGeo.OGR.FieldType.OFTString);
                    layer.CreateField(kmlFieldAltitudeMode, fields.Count());
                    //OSGeo.OGR.FieldDefn kmlFieldExtrude = new OSGeo.OGR.FieldDefn("tessellate", OSGeo.OGR.FieldType.OFTInteger);
                    //layer.CreateField(kmlFieldExtrude, fields.Count()+1);
                }


                for (int a = 0; a < gGoo.Branches.Count; a++)
                {
                    ///create feature
                    OSGeo.OGR.Feature feature = new OSGeo.OGR.Feature(def);

                    ///Set LIBKML specific fields for use in Google Earth, defaulting to 'relativeToGround'.  Consider setting to 'absolute'.
                    if (drvType == "LIBKML")
                    {
                        feature.SetField("altitudeMode", "relativeToGround");
                        //feature.SetField("altitudeMode", "absolute");
                        //feature.SetField("tessellate", 0);
                    }

                    ///TODO: Build style table
                    OSGeo.OGR.StyleTable styleTable = new StyleTable();
                    //feature.SetStyleString("BRUSH(fc:#0000FF);PEN(c:#000000)");

                    ///Get geometry type(s) in branch
                    var           geomList     = gGoo.Branches[a];
                    string        geomType     = string.Empty;
                    List <string> geomTypeList = geomList.Select(o => o.TypeName).ToList();
                    ///Test if geometry in the branch is of the same type.
                    ///If there is more than one element of a type, tag as multi, if there is more than one type, tag as mixed
                    if (geomTypeList.Count == 1)
                    {
                        geomType = geomTypeList.First();
                    }
                    else if (geomTypeList.Count > 1 && geomTypeList.All(gt => gt == geomTypeList.First()))
                    {
                        geomType = "Multi" + geomTypeList.First();
                    }

                    else
                    {
                        geomType = "Mixed";
                    }

                    ///For testing
                    //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, geomType);

                    ///Add geomtery to feature
                    ///Create containers for translating from GH Goo
                    Point3d        pt  = new Point3d();
                    List <Point3d> pts = new List <Point3d>();

                    Curve        crv  = null;
                    List <Curve> crvs = new List <Curve>();

                    Mesh mesh      = new Mesh();
                    Mesh multiMesh = new Mesh();

                    switch (geomType)
                    {
                    case "Point":
                        geomList.First().CastTo <Point3d>(out pt);
                        feature.SetGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
                        if (!shpTypeList.Contains("POINT"))
                        {
                            shpTypeList.Add("POINT");
                        }
                        break;

                    case "MultiPoint":
                        foreach (var point in geomList)
                        {
                            point.CastTo <Point3d>(out pt);
                            pts.Add(pt);
                        }
                        feature.SetGeometry(Heron.Convert.Point3dsToOgrMultiPoint(pts, transform));
                        if (!shpTypeList.Contains("MULTIPOINT"))
                        {
                            shpTypeList.Add("MULTIPOINT");
                        }
                        break;

                    case "Curve":
                        geomList.First().CastTo <Curve>(out crv);
                        feature.SetGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
                        if (!shpTypeList.Contains("LINESTRING"))
                        {
                            shpTypeList.Add("LINESTRING");
                        }
                        break;

                    case "MultiCurve":
                        foreach (var curve in geomList)
                        {
                            curve.CastTo <Curve>(out crv);
                            crvs.Add(crv);
                        }
                        feature.SetGeometry(Heron.Convert.CurvesToOgrMultiLinestring(crvs, transform));
                        if (!shpTypeList.Contains("MULTILINESTRING"))
                        {
                            shpTypeList.Add("MULTILINESTRING");
                        }
                        break;

                    case "Mesh":
                        geomList.First().CastTo <Mesh>(out mesh);
                        feature.SetGeometry(Heron.Convert.MeshToMultiPolygon(mesh, transform));
                        if (!shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpTypeList.Add("MULTIPOLYGON");
                        }
                        break;

                    case "MultiMesh":
                        foreach (var m in geomList)
                        {
                            Mesh meshPart = new Mesh();
                            m.CastTo <Mesh>(out meshPart);
                            multiMesh.Append(meshPart);
                        }
                        feature.SetGeometry(Heron.Convert.MeshToMultiPolygon(multiMesh, transform));
                        if (!shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpTypeList.Add("MULTIPOLYGON");
                        }
                        break;

                    case "Mixed":
                        OSGeo.OGR.Geometry geoCollection = new OSGeo.OGR.Geometry(wkbGeometryType.wkbGeometryCollection);
                        for (int gInt = 0; gInt < geomList.Count; gInt++)
                        {
                            string geomTypeMixed = geomTypeList[gInt];
                            switch (geomTypeMixed)
                            {
                            case "Point":
                                geomList[gInt].CastTo <Point3d>(out pt);
                                geoCollection.AddGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
                                break;

                            case "Curve":
                                geomList[gInt].CastTo <Curve>(out crv);
                                geoCollection.AddGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
                                break;

                            case "Mesh":
                                geomList[gInt].CastTo <Mesh>(out mesh);
                                geoCollection.AddGeometry(Ogr.ForceToMultiPolygon(Heron.Convert.MeshToMultiPolygon(mesh, transform)));
                                break;

                            default:
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomType + " geometry at branch " + gGoo.get_Path(a).ToString() +
                                                  ". Geometry must be a Point, Curve or Mesh.");
                                break;
                            }
                        }
                        feature.SetGeometry(geoCollection);
                        if (!shpTypeList.Contains("GEOMETRYCOLLECTION"))
                        {
                            shpTypeList.Add("GEOMETRYCOLLECTION");
                        }
                        break;

                    default:
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomType + " geometry at branch " + gGoo.get_Path(a).ToString() +
                                          ". Geometry must be a Point, Curve or Mesh.");
                        break;
                    }



                    ///Give the feature a unique ID
                    feature.SetFID(a);

                    ///Add values to fields
                    GH_Path path = gGoo.get_Path(a);

                    for (int vInt = 0; vInt < fields.Count; vInt++)
                    {
                        string val = string.Empty;
                        if (values.get_Branch(path) != null)
                        {
                            val = values.get_DataItem(path, vInt).ToString();
                        }
                        feature.SetField(fields[vInt], val);
                    }

                    ///Save feature to layer
                    layer.CreateFeature(feature);

                    ///Cleanup
                    feature.Dispose();
                }

                layer.Dispose();
                ds.Dispose();
                drv.Dispose();

                ///Convert in memory dataset to file using ogr2ogr
                ///For KML set 'altitudeMode' to 'relativeToGround' or 'absolute'

                ///Set base options for all export types
                if (drvType == "KML")
                {
                    drvType = "LIBKML";
                }
                List <string> ogr2ogrOptions = new List <string> {
                    "-overwrite",
                    "-f", drvType,
                    "-dim", "XYZ",
                    "-skipfailures",

                    //"-lco", "LIBKML_STRICT_COMPLIANCE=FALSE",
                    //"-lco", "AltitudeMode=absolute",

                    //"-dsco", "SHAPE_REWIND_ON_WRITE=YES"
                };

                Dataset src = Gdal.OpenEx("/vsimem/out.geojson", 0, null, null, null);

                if (drvType != "ESRI Shapefile")
                {
                    Dataset destDataset = Gdal.wrapper_GDALVectorTranslateDestName(shpPath, src, new GDALVectorTranslateOptions(ogr2ogrOptions.ToArray()), null, null);
                    destDataset.Dispose();
                    shpPathList.Add(shpPath);
                }

                ///Export multiple layers for shapefile
                ///https://trac.osgeo.org/gdal/wiki/FAQVector#HowdoItranslateamixedgeometryfiletoshapefileformat
                else
                {
                    ///
                    if (shpTypeList.Count <= 1 && shpTypeList.First() != "GEOMETRYCOLLECTION")
                    {
                        if (shpTypeList.First() == "POLYGON" || shpTypeList.First() == "MULTIPOLYGON")
                        {
                            ogr2ogrOptions.AddRange(new List <string> {
                                "-lco", "SHPT=MULTIPATCH"
                            });
                        }
                        Dataset destDataset = Gdal.wrapper_GDALVectorTranslateDestName(shpPath, src, new GDALVectorTranslateOptions(ogr2ogrOptions.ToArray()), null, null);
                        destDataset.Dispose();
                        shpPathList.Add(shpPath);
                    }

                    else
                    {
                        ///Add -explodecollections for mixed geometries in a branch
                        ///"-where" statement is not necessary, but could speed up big datasets

                        string        shpFileName       = string.Empty;
                        List <string> ogr2ogrShpOptions = new List <string>();

                        if (shpTypeList.Contains("POINT") || shpTypeList.Contains("MULTIPOINT"))
                        {
                            shpFileName = folder + filename + "_points.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsPts = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            //ogr2ogrShpOptionsPts.AddRange(new List<string> { "-where", "ogr_geometry=POINT", "-where", "ogr_geometry=MULTIPOINT", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"});
                            ogr2ogrShpOptionsPts.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOINT' OR OGR_GEOMETRY='POINT'", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsPts.AddRange(new List<string> { "-dialect", "sqlite", "-sql", "select * from " + filename + " where GeometryType(geometry) in ('POINT','MULTIPOINT')", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetPoint = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsPts.ToArray()), null, null);
                            destDatasetPoint.Dispose();
                        }

                        if (shpTypeList.Contains("LINESTRING") || shpTypeList.Contains("MULTILINESTRING"))
                        {
                            shpFileName = folder + filename + "_lines.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsLines = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            //ogr2ogrShpOptionsLines.AddRange(new List<string> { "-where", "ogr_geometry=LINESTRING25D", "-where", "ogr_geometry=MULTILINESTRING25D", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });
                            ogr2ogrShpOptionsLines.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='LINESTRING' OR OGR_GEOMETRY='MULTILINESTRING'", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsLines.AddRange(new List<string> { "-dialect", "sqlite", "-sql", "select * from " + filename + " where GeometryType(geometry) in ('LINESTRING','MULTILINESTRING')", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetLinestring = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsLines.ToArray()), null, null);
                            destDatasetLinestring.Dispose();
                        }

                        if (shpTypeList.Contains("POLYGON") || shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpFileName = folder + filename + "_polygons.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsPolygons = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures",
                                "-dsco", "SHAPE_REWIND_ON_WRITE=NO"
                            };
                            //ogr2ogrShpOptionsPolygons.AddRange(new List<string> { "-where", "ogr_geometry=POLYGON", "-where", "ogr_geometry=MULTIPOLYGON", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI" });
                            ogr2ogrShpOptionsPolygons.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOLYGON25D' OR OGR_GEOMETRY='POLYGON25D'", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            Dataset destDatasetPolygon = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsPolygons.ToArray()), null, null);
                            destDatasetPolygon.Dispose();
                        }

                        ///Not working properly when multiple geometry types are part of the same branch for SHP export.
                        if (shpTypeList.Contains("GEOMETRYCOLLECTION"))
                        {
                            AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "One or more branches contain a mix of geometry types.");
                            ///export points
                            shpFileName = folder + filename + "_gc-points.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCPts = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            ogr2ogrShpOptionsGCPts.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCPts.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOINT' OR OGR_GEOMETRY='POINT'", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetGCPoints = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCPts.ToArray()), null, null);
                            destDatasetGCPoints.Dispose();

                            ///export lines
                            shpFileName = folder + filename + "_gc-lines.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCLines = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            ogr2ogrShpOptionsGCLines.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCLines.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTILINESTRING25D' OR OGR_GEOMETRY='LINESTRING25D'", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });
                            Dataset destDatasetGCLines = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCLines.ToArray()), null, null);
                            destDatasetGCLines.Dispose();

                            ///export meshes
                            shpFileName = folder + filename + "_gc-polygons.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCPolygons = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures",
                                "-dsco", "SHAPE_REWIND_ON_WRITE=NO"
                            };
                            ogr2ogrShpOptionsGCPolygons.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCPolygons.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOLYGON' OR OGR_GEOMETRY='POLYGON'", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI" });
                            Dataset destDatasetGCPolygons = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCPolygons.ToArray()), null, null);
                            destDatasetGCPolygons.Dispose();
                        }
                    }
                }

                ///Clean up
                Gdal.Unlink("/vsimem/out.geojson");
            }

            DA.SetDataList(0, shpPathList);
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="table"></param>
 public StyleTableValuesFactory(StyleTable table)
 {
     _table = table;
 }
 internal override StyleTable AddStyleToProtoChain(StyleTable chain, object target)
 {
     // If we have a local _style, then add only it to the chain. It will
     // take are of adding its parent to the chain.
     // If then is no _style, but a _parentStyle, then add the parent Style
     // to the chain.
     if (null != _style)
         return _style.AddStyleToProtoChain(chain, target/*, filterMap*/);
     //if (null != _parentStyle)
     //    return _parentStyle.AddStyleToProtoChain(chain, target/*, filterMap*/);
     return chain;
 }