MapGuide RFC 26 - Stylize Elevation Layer
This page contains an change request (RFC) for the MapGuide Open Source project. More MapGuide RFCs can be found on the RFCs page.
Status
RFC Template Version | 1.0 |
Submission Date | Aug 2, 2007 |
Last Modified | Maggie Yang Timestamp |
Author | Maggie Yang |
RFC Status | approved |
Implementation Status | under development |
Proposed Milestone | 2.0 |
Assigned PSC guide(s) | (when determined) |
Voting History | Aug 27, 2007 |
+1 | Jason,Andy, Haris, Tom, Bruce and Paul |
+0 | |
-0 | |
-1 |
Overview
The purpose of this RFC is to allow MapGuide to stylize the elevation data, which configured surface style in its layer definition.
Motivation
MapGuide cannot stylize the elevation layer, such as DEM and GeoTIFF file, configured by the following kind of layer definition with surface style:
<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd" version="1.0.0"> <GridLayerDefinition> <ResourceId>Library://Publish/Data/Raster_1.FeatureSource</ResourceId> <FeatureName>rasters:davenport</FeatureName> <Geometry>Image</Geometry> <GridScaleRange> <SurfaceStyle> <Band>1</Band> <DefaultColor>0000FF00</DefaultColor> </SurfaceStyle> <ColorStyle> <HillShade> <Band>1</Band> <Azimuth>45</Azimuth> <Altitude>45</Altitude> </HillShade> <ColorRule> <LegendLabel>-1.79e+308 to 1.79e+308</LegendLabel> <Filter>(Height(1) > -1.7976931348623158e+308) AND (Height(1) < 1.7976931348623158e+308)</Filter> <Color> <ExplicitColor>FF00FF00</ExplicitColor> </Color> </ColorRule> <ColorRule> <LegendLabel>{DEFAULT}</LegendLabel> <Color> <ExplicitColor>FF006423</ExplicitColor> </Color> </ColorRule> </ColorStyle> <RebuildFactor>1</RebuildFactor> </GridScaleRange> </GridLayerDefinition>
Currently, MapGuide do not have the stylization mechanism for grid surface data. So, in this release, we will make MapGuide has the ability to stylize the elevation layer. The user would see the stylized elevation data, like Figure 1 in MapGuide in the future, not the Figure 2, which is the current status for elevation data in MapGuide.
instead of | ||
Figure1 | Figure2 |
Proposed Solution
Modify Stylization project to support the stylization of the elevation data with surface style. Here, introduce some key classes for stylizing elevation data, also called grid data. They are GridStylizer, GridData, GridStyleHandler, GridColorHandler and GridApplyStatusReporter.
GridStylizer
This class only for stylization with grid data and grid styles. GridStylizer takes a grid, a grid color style, and a grid surface style. Then it applies the color style on the grid and writes the result into the color band of the grid. Moreover, it also applies the surface style on the grid and writes the result into the elevation band of the grid.
class GridStylizer { public: ///<summary> /// Stylizes a grid base on the given surface style and color style. /// It applies the surface style to generate a new elevation band to show /// 3d surface. And it also applies the color style to generate a new /// color band to show the texture of the 3d surface. ///</summary> ///<param name="pGrid"> /// A grid is a set of bands. The stylizer read band data from the grid /// and write the result into the color band and elevation band. ///</param> ///<param name="pSurfaceStyle"> /// The pointer of GridSurfaceStyle, which specifies how to calculate the elevation. ///</param> ///<param name="pColorStyle"> /// The pointer of GridColorStyle, which specifies how to stylize each pixel. ///</param> ///</param> ///<param name="fOpacity"> /// Opacity of this Grid Layer ///</param> ///<returns> /// Returns true to indicate the stylization transaction completes successfully. /// Returns false to indicate the stylization transaction encouters some errors and /// has been interruptted. ///</returns> STYLIZATION_API bool ApplyStyles( GridData *pGrid, const MdfModel::GridSurfaceStyle *pSurfaceStyle, const MdfModel::GridColorStyle *pColorStyle, double fOpacity = 1.0); ///<summary> /// Stylizes a grid base on the given color style and default color. /// It applies the color style to generate a new color band to show /// the texture of the 3d surface. And also it will set the transparent /// pixel to the default color. ///</summary> ///<param name="pGrid"> /// A grid is a set of bands. The stylizer read band data from the grid /// and write the result into the color band. ///</param> ///<param name="pColorStyle"> /// The pointer of GridColorStyle, which specifies how to stylize each pixel. ///</param> ///<param name="sDefaultColor"> /// The default color for the tansparent pixel. ///</param> ///<returns> /// Returns true to indicate the stylization transaction completes successfully. /// Returns false to indicate the stylization transaction encouters some errors and /// has been interruptted. ///</returns> STYLIZATION_API bool ApplyColorStyle( GridData *pGrid, const MdfModel::GridColorStyle *pStyle, const MdfModel::MdfString &sDefaultColor); ///<summary> /// Stylizes a grid base on the given surface style. /// It applies the surface style to generate a new elevation band to show /// 3d surface. ///</summary> ///<param name="pGrid"> /// A grid is a set of bands. The stylizer read band data from the grid /// and write the result into the color band and elevation band. ///</param> ///<param name="pSurfaceStyle"> /// The pointer of GridSurfaceStyle, which specifies how to calculate the elevation. ///</param> ///<returns> /// Returns true to indicate the stylization transaction completes successfully. /// Returns false to indicate the stylization transaction encouters some errors and /// has been interruptted. ///</returns> STYLIZATION_API bool ApplySurfaceStyle( GridData *pGrid, const MdfModel::GridSurfaceStyle *pStyle); ///<summary> /// Applied the hillshade effect to a gis band ///</summary> ///<param name="pColorBand"> /// It is the input and ouput, we read color from it, and apply hillshade, then write /// back to it. ///</param> ///<param name="pHS"> /// It describes how to apply hillshade to the gis band. ///</param> ///<returns> /// Returns true to indicate the stylization transaction completes successfully. /// Returns false to indicate the stylization transaction encouters some errors and /// has been interruptted. ///</returns> STYLIZATION_API static bool ApplyHillShade( Band* pColorBand, const MdfModel::HillShade *pHS); }
GridData
This class is a collection of all kinds of information from elevation data, such as bands, hillshade, bounding box and etc. Those grid data are populated from FdoIRaster.
class GridData { public: typedef std::vector<Band*> GISGRIDVECTOR; public: ///<summary> /// Because all the bands in the same grid have the same original point extent and count, /// so this information is kept in the GridData class. ///</summary> STYLIZATION_API GridData( const Point2D& point, double xExtent, double yExtent, unsigned int nXCount, unsigned int nYCount); /// <summary> /// Populates the GridData from an FdoIRaster /// </summary> STYLIZATION_API void ReadRaster(RS_Raster* pRaster, FdoString* pBandName, unsigned long cols, unsigned long rows, double xMin, double yMin, double xMax, double yMax, bool bAlignment); ///<summary> /// Get the Band with band name. If it is not in the grid, return NULL. ///</summary> STYLIZATION_API Band* GetBand(const MdfModel::MdfString& name) const; ///<summary> /// Get the Band with the band index. If it is not in the grid, return NULL. /// The index of the Band maybe will changed after some insert operation, /// so please don't keep the band index to get the band next time. /// In the most case, please you'd better get the Band with the band name. /// You can use this method and GetBandCount method to iterator the grid get all /// the bands. ///</summary> STYLIZATION_API Band* GetBand(unsigned int index) const; STYLIZATION_API inline size_t GetBandCount() const; ///<summary> /// This method is used to create a new band in the grid, the band name /// will be set as the name parament. And this band will be insert to the grid. /// If the name is duplicated, this method will return NULL. ///</summary> STYLIZATION_API Band* CreateBand(Band::BandDataType dataType, const MdfModel::MdfString& name); ///<summary> /// Insert a band into the grid. Because a band is identity with it's name in the grid, /// so please make sure the name of band is not empty before insert it to the grid, /// or this method will return false. And if there is a band in the grid has the same name /// with the insert band, it will return false too. ///</summary> STYLIZATION_API bool InsertBand( Band* pBand); ///<summary> /// If the elevation band is a band in the grid, set the elevation band /// with the band name and index of the band in the grid. ///</summary> STYLIZATION_API bool SetElevationBand(const MdfModel::MdfString& name); STYLIZATION_API bool SetElevationBand(unsigned int index); ///<summary> /// If the elevation band is not a band in the grid, use this method to set the /// elevation band for the grid. ///</summary> STYLIZATION_API inline void SetElevationBand(Band* pBand); ///<summary> /// Get the elevation band in this grid. ///</summary> STYLIZATION_API inline Band* GetElevationBand() const; ///<summary> /// Get a band for stylization use. If it is empty, we will create one band (double type). ///</summary> STYLIZATION_API Band* GetElevationBandDataForStylization(); ///<summary> /// Get the draped color band in this grid. ///</summary> STYLIZATION_API Band* GetDrapedColorBand() const; ///<summary> /// Create a draped color band in this grid. /// In some cases, the draped color band is not required for the grid. /// So we just offer this method to create the drpaed color band when it is required. ///</summary> STYLIZATION_API void CreateDrapedColorBand(); ///<summary> /// Get the color band in this grid. ///</summary> STYLIZATION_API Band* GetColorBand() const; ///<summary> /// Function to retrieve the band that stores the hillshade values. It is in float format. ///</summary> STYLIZATION_API const Band* GetCacheHillShadeBand(const MdfModel::HillShade *pHS) const; ///<summary> /// Function to set the band that stores the hillshade values. It is in float format. ///</summary> STYLIZATION_API bool SetCacheHillShadeBand( const MdfModel::HillShade *pHS, Band *pHSBand); ///<summary> /// Set the raw color band without hillshade effect if the color band includes effect. ///</summary> STYLIZATION_API bool SetNoHillShadeColorBand(Band *pNoHillShadeColorBand); ///<summary> /// Get the raw color band without hillshade effect if the color band includes effect. ///</summary> STYLIZATION_API const Band* GetNoHillShadeColorBand() const; ///<summary> /// Get the raw color band without hillshade effect if the color band includes effect. ///</summary> STYLIZATION_API Band* GetNoHillShadeColorBand(); ///<summary> /// Get the geometry information for the bands in this grid. ///</summary> STYLIZATION_API inline double GetXUnitDistance() const; STYLIZATION_API inline double GetYUnitDistance() const; STYLIZATION_API inline double GetInvScaledDX() const; STYLIZATION_API inline double GetInvScaledDY() const; STYLIZATION_API inline unsigned int GetXCount() const; STYLIZATION_API inline unsigned int GetYCount() const; STYLIZATION_API inline double GetXExtent () const; STYLIZATION_API inline double GetYExtent () const; STYLIZATION_API inline const Point2D& GetOriginalPoint2D() const; STYLIZATION_API inline MdfModel::Box2D GetBoundingBox() const; STYLIZATION_API inline void SetCoordSysUnitLength(double dUnitLength); STYLIZATION_API inline double GetCoordSysUnitLength() const; STYLIZATION_API Band::BandDataType GetGridDataType(RS_Raster* pRaster, bool bBandDataType = true) const; }
GridStyleHandler
Class GridStyleHandler is the base class of all the grid style handlers. This class provides the common interface to visit each pixel of the band and do the different operations, such as to stylize the band.
class GridStyleHandler { public: ///<summary> /// Function to clear the data info of the handler. ///</summary> virtual void Clear() = 0; ///<summary> /// Function to visit each pixel. ///</summary> virtual void Visit(unsigned int x, unsigned int y) = 0; ///<summary> /// Finished visiting all the pixels ///</summary> virtual void Finished(bool bSuccessful) {bSuccessful;} ///<summary> /// Set GridStatusReporter ///</summary> virtual void SetStatusReporter(GridStatusReporter *pReporter) = 0; ///<summary> /// Function to visit all pixels. ///</summary> virtual bool Visit() = 0; };
There are several derived classes of GridStyleHandler:
GridStyleColorHandler is used to handle the MdfModel::GridColorStyle.
GridStyleSurfaceColorHandler is used to set the transparent color to the default color. And it also set the invalid pixel to the default color.
GridStyleSurfaceHandler is used to handle the MdfModel::GridSurfaceStyle.
GridColorHandler
This base class provides the uniform interface for getting the color on each pixel when stylizing the band
class GridColorHandler { public: ///<summary> /// Function to initialize the GridColorHandler object. ///</summary> ///<param name = "pRules"> /// The rules includes the detail info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns true if it is intialized successfully. /// Othrewise, returns false. ///</returns> virtual bool Initialize(const MdfModel::RuleCollection *pRules, const GridData *pGrid) = 0; ///<summary> /// Function to get the color on the pixel. ///</summary> ///<param name = "color"> /// [Out] Stores the result color. ///</param> ///<param name = "x"> /// The X axis position of the pixel ///</param> ///<param name = "y"> /// The Y axis position of the pixel ///</param> ///<returns> /// Returns true if it gets the corresponding color. /// Othrewise, returns false. ///</returns> virtual bool GetColor(Color &color, unsigned int x, unsigned int y) = 0; ///<summary> /// Function to clear the data info of the handler. ///</summary> virtual void Clear() = 0; ///<summary> /// Function to create the corresponding color handler according to the different pRules. ///</summary> ///<param name = "pRules"> /// The rules includes the detail info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns the pointer to the new created GridColorHandler. /// Caller must be responsible to release it. /// Returns NULL if the handlers fail to initialize. ///</returns> static GridColorHandler* Create(const MdfModel::RuleCollection *pRules, const GridData *pGrid); ///<summary> /// Function to create the GridColorBandHandler. ///</summary> ///<param name = "pRules"> /// The rules includes the detail info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns the pointer to the new created GridColorBandHandler. /// Caller must be responsible to release it. /// Returns NULL if the handlers fail to initialize. ///</returns> static GridColorBandHandler* CreateBandHandler(const MdfModel::RuleCollection *pRules, const GridData *pGrid); ///<summary> /// Function to create the GridColorBandsHandler. ///</summary> ///<param name = "pRules"> /// The rules includes the detail info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns the pointer to the new created GridColorBandsHandler. /// Caller must be responsible to release it. /// Returns NULL if the handlers fail to initialize. ///</returns> static GridColorBandsHandler* CreateBandsHandler(const MdfModel::RuleCollection *pRules, const GridData *pGrid); ///<summary> /// Function to create the GridColorThemeHandler. ///</summary> ///<param name = "pRules"> /// The rules includes the theme info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns the pointer to the new created GridColorThemeHandler. /// Caller must be responsible to release it. /// Returns NULL if the handlers fail to initialize. ///</returns> static GridColorThemeHandler* CreateThemeHandler(const MdfModel::RuleCollection *pRules, const GridData *pGrid); ///<summary> /// Function to create the GridColorNullHandler. ///</summary> ///<param name = "pRules"> /// The rules includes the detail info. ///</param> ///<param name = "pGrid"> /// The grid that the styles are applied on. ///</param> ///<returns> /// Returns the pointer to the new created GridColorNullHandler. /// Caller must be responsible to release it. /// Returns NULL if the handlers fail to initialize. ///</returns> static GridColorNullHandler* CreateNullHandler(const MdfModel::RuleCollection *pRules, const GridData *pGrid); };
There are several derived classes of GridColorHandler:
GridColorBandsHandler is used to handle the situation when the GridColor's type is Bands. It gets the channel data from the three ChannelBands and merge them to a color value.
GridColorBandHandler is used to handle the situation when the GridColor's type is Band. It gets the band's value and return it as the color value.
GridColorNullHandler is used to handle the situation when there is no rule.
GridColorThemeHandler is used to handle the situtation when stylizer themes a band according to the aspect, slope, or height value.It calculates the geometry value and searchs the corresponding color in its generated hash table.
GridApplyStatusReporter
An implementation of GridStatusReporter. This class will delegate all the status change events to the stylizer's reactors.
class GridApplyStatusReporter : public GridStatusReporter { public: ///<summary> /// Initializes this class by the three arguments. ///</summary> ///<param name="stylizer">The the stylizer which is applying style.</param> ///<param name="pixelCount">The count of the total pixels of the grid.</param> void Init(GridStylizer *stylizer, double pixelCount); ///<summary> /// Indicates the transaction has been started. /// This class will notify the stylizer's reactors that /// the stylizer begins to apply the styles. ///</summary> virtual void Begin(); ///<summary> /// Indicates the transaction has been finished successfully. /// This class will notify the stylizer's reactors that /// the stylizer has finished applying styles. ///</summary> virtual void Commit(); ///<summary> /// Indicates the transaction encountered some error and has been terminated. /// This class will notify the stylizer's reactors that /// the stylizer failed to apply styles for some unknown reasons. ///</summary> virtual void Rollback(); ///<summary> /// Call this function when finishing a step. /// And check the returned value. /// If the returned value is true, that means the Step() function has been handled successfully. /// Otherwise, false means encountering some exceptions. ///</summary> virtual bool Step(int stepSize = 1); ///<summary> /// If isTerminate is TRUE, then Step() will return FALSE to let the stylizer stop applying. /// It just sets a flag. And the flag will show its influence when /// calling Step() next time. ///</summary> void SetTerminate(bool isTerminate); ///<summary> /// Returns m_isTerminate. ///</summary> bool IsTerminate() const; }
Some new classes will be introduced to handle Band, Color, ChannelBand, Theme and etc individually.
Implications
This RFC does not describe any GUI modifications and does not affect the existed published API.
Test Plan
Add some elevation data,such as DEM/TIFF file and layer definition with surface style,like
<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd" version="1.0.0"> <GridLayerDefinition> <ResourceId>Library://Publish/Data/Raster_1.FeatureSource</ResourceId> <FeatureName>rasters:davenport</FeatureName> <Geometry>Image</Geometry> <GridScaleRange> <SurfaceStyle> <Band>1</Band> <DefaultColor>0000FF00</DefaultColor> </SurfaceStyle> <ColorStyle> <HillShade> <Band>1</Band> <Azimuth>45</Azimuth> <Altitude>45</Altitude> </HillShade> <ColorRule> <LegendLabel>-1.79e+308 to 1.79e+308</LegendLabel> <Filter>(Height(1) > -1.7976931348623158e+308) AND (Height(1) < 1.7976931348623158e+308)</Filter> <Color> <ExplicitColor>FF00FF00</ExplicitColor> </Color> </ColorRule> <ColorRule> <LegendLabel>{DEFAULT}</LegendLabel> <Color> <ExplicitColor>FF006423</ExplicitColor> </Color> </ColorRule> </ColorStyle> <RebuildFactor>1</RebuildFactor> </GridScaleRange> </GridLayerDefinition>
to a MapGuide server, the elevation layer should display, like Figure1 in MapGuide studio.
Funding/Resources
Supplied by Autodesk.
Attachments (2)
- Before.JPG (17.4 KB ) - added by 17 years ago.
- After.JPG (45.2 KB ) - added by 17 years ago.
Download all attachments as: .zip