Global Mapper v25.0

how to create an area feature and draw it with GM_CreateCustomVectorLayer?

JerryLia
JerryLia Global Mapper User
edited August 2008 in SDK
I am trying to develop a GIS application with this SDK in C# and i have a question:
how i pass the points to the structure GM_AreaFeature_t?

My code such as :
GM_AreaFeature_t lt_Customize = new GM_AreaFeature_t();
lt_Customize.mPointList = ?????;//what will be assigned?
lt_Customize.mFeatureInfo = lt_VectorFeature;
lt_Customize.mNumPoints =(uint) pList.Count;
lt_Customize.mNumHoles = 0;


Any help will be apprecated1

Jerry

Comments

  • global_mapper
    global_mapper Administrator
    edited August 2008
    Jerry,

    I'm not a C# programmer, but what the mPointList value expects is the address of a continguous chunk of memory containing a series of GM_Point_t features. In C/C++ this is just a pointer to the first element in an array of GM_Point_t features. I'm sure there is a way to allocate a chunk of memory in C# and then assign values to it.

    Let me know if I can be of further assistance.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Mike,

    Thanks for your reply.
    My code such as :

    GM_AreaFeature_t myAreaFeature = CreateMyArea(coor);
    GlobalMapperDLL.GM_AddAreaToCustomVectorLayer(LayerHandle, ref myAreaFeature , true);

    public GM_AreaFeature_t CreateMyArea(ArrayList coor)
    {
    GM_Point_t[] lt_Point = new GM_Point_t[coor.Count / 2];//My Points stored in Coor Array

    int ln_Counter = 0;
    for (int i = 0; i < coor.Count - 1; i++)//read XY coordinates and write into GM_Point_t.
    {
    lt_Point[ln_Counter].X = Convert.ToDouble(coor);
    lt_Point[ln_Counter].Y = Convert.ToDouble(coor[i + 1]);
    ln_Counter++;
    i++;
    }

    //allocate a chunk of memory
    IntPtr ptrPoint = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(GM_Point_t)));

    //assign the array[0] address to IntPtr.
    Marshal.StructureToPtr(lt_Point[0], ptrPoint, true);

    GM_AreaFeature_t lt_Customize = new GM_AreaFeature_t();
    lt_Customize.mFeatureInfo = ptrPoint ;
    lt_Customize.mNumPoints =lt_Point.Length;
    lt_Customize.mNumHoles = 0;

    return lt_Customize
    }

    It can draw out some things but not what i want!
  • global_mapper
    global_mapper Administrator
    edited August 2008
    My C# is not so good, but I would expect your Marshal.AllocCoTaskMem call to allocate enough memory for all of the points in the array and not just one. I think that line should look like the following:

    IntPtr ptrPoint = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(GM_Point_t) * coor.Count / 2));

    Then your call to Marshal the structure to the pointer will have to copy each point element into the allocated memory buffer (or just do some sort of memcpy if that is possible in C#).

    Let me know if I can be of further assistance.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Thanks Mike,
    the above question has solved with Pointer in C# and draw it correctly.But i find another question which i think as a bug:
    After drawing GM_CreateCustomVectorLayer,i resize the form again and again,or minimize it for many times,then the application seems to be dead! however , i load other layers from files instead of creating my custom vectorlayer,the application works fine!

    Could you help me again?

    Jerry
  • global_mapper
    global_mapper Administrator
    edited August 2008
    Jerry,

    Where is the program locking up when it seems to be dead? Is it stuck in a SDK function or some other location?

    If the only difference is the custom vector layer, be very careful that you aren't writing past the end of your allocated memory buffer or something like that and corrupting memory.

    Let me know if I can be of further assistance.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Mike,
    I am trying SDK and want to create my customvectorlayer,my code such as :
    public unsafe GM_AreaFeature_t CreateMyArea(ArrayList coor)
    {
    GM_Point_t[] lt_Point = new GM_Point_t[coor.Count / 2];//My Points stored in Coor Array

    int ln_Counter = 0;
    for (int i = 0; i < coor.Count - 1; i++)//read XY coordinates and write into GM_Point_t.
    {
    lt_Point[ln_Counter].X = Convert.ToDouble(coor);
    lt_Point[ln_Counter].Y = Convert.ToDouble(coor[i + 1]);
    ln_Counter++;
    i++;
    }

    IntPtr ptrPoint;

    GM_VectorFeature_t lt_VectorFeature = new GM_VectorFeature_t { Name = "testName", Desc = "testDesc", Class = 0, NumAttrs = 1 };

    fixed (GM_Point_t* point_t = &lt_Point[0])
    {
    ptrPoint = (IntPtr)point_t;
    }

    GM_AreaFeature_t lt_Customize = new GM_AreaFeature_t();
    lt_Customize.mPointList = ptrPoint;
    lt_Customize.mFeatureInfo = lt_VectorFeature;
    lt_Customize.mNumPoints = (uint)lt_Point.Length;
    lt_Customize.mNumHoles = 0;

    return lt_Customize;
    }

    I use it such as :

    private void menuItem5_Click(object sender, EventArgs e)
    {
    CreateMyPrjSys();
    Int32 LayerHandle = GlobalMapperDLL.GM_CreateCustomVectorLayer("MyPoint", ref lt_Prj);
    ........
    GM_AreaFeature_t lt_MyPoint = CreateMyArea(coor); //here coor has been filled with values.
    GlobalMapperDLL.GM_AddAreaToCustomVectorLayer(LayerHandle, ref lt_MyPoint, true);

    clsGlobalVARS.LayerHandles.Add(LayerHandle);
    DrawLayersToBitmap();
    }

    When I comment the line ticked with red color,everything goes well!
  • global_mapper
    global_mapper Administrator
    edited August 2008
    Can I see your declaration for the GM_CreateCustomVectorLayer function as well as the 'lt_Prj' variable? Can I also see your declaration for the GM_AreaFeature_t type?

    Does your application lock up as soon as you call the GM_CreateCustomVectorLayer function?

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Mike,

    I refactor my code in a new project and find that the question has gone! I use GM_DrawLayerList function to draw layers instead of GM_DrawLayer! I am so sorry for saying what it is bug.
    Here i encounter another question:I want to symbol the customVectorlayer,my code is followed:

    public void drawCustomLayer()
    {

    if (mn_CustomLayerHandle == null || mn_CustomLayerHandle.Count==0)
    {
    return;
    }
    UInt32 j = 0;

    for (int i = 0; i < mn_CustomLayerHandle.Count; i++)
    {
    Int32 lp_LayerHandle = (Int32)mn_CustomLayerHandle;
    IntPtr layerInfoPtr = GlobalMapperDLL.GM_GetLayerInfo(lp_LayerHandle);

    //my layer contains two area feature,but GM_LayerInfo_t.mNumAreas=0;
    GM_LayerInfo_t layerInfo_t = (GM_LayerInfo_t) Marshal.PtrToStructure(layerInfoPtr, typeof(GM_LayerInfo_t));

    while (true)
    {
    IntPtr ptr = GlobalMapperDLL.GM_GetAreaFeature(lp_LayerHandle, j);
    if (ptr.ToInt32() == 0) break;
    GM_AreaFeature_t areaInfo = (GM_AreaFeature_t)Marshal.PtrToStructure(ptr, typeof(GM_AreaFeature_t));

    //GlobalMapperDLL.GM_FreeAreaFeature(ptr);
    GM_VectorFeature_t lt_VectorFeature = areaInfo.mFeatureInfo;

    IntPtr ptrAttribute = lt_VectorFeature.AttrList;
    GM_AttrValue_t lt_AttrValue = (GM_AttrValue_t)Marshal.PtrToStructure(ptrAttribute, typeof(GM_AttrValue_t));
    GM_AreaStyle_t lt_AreaStyle = areaInfo.mAreaStyle;
    lt_AreaStyle.mBrushStyle = GM_BrushStyle_t16.GM_BRUSH_SOLID;
    lt_AreaStyle.mBrushColor = (uint)Color.FromArgb(255, 255, int.Parse(lt_AttrValue.mVal) * 80).ToArgb();
    GlobalMapperDLL.GM_SetAreaFeatureDrawStyle(lp_LayerHandle, (int)j, ref lt_AreaStyle);
    //Is it right release area feature here?
    GlobalMapperDLL.GM_FreeAreaFeature(ptr);

    j++;
    }

    }
    }

    there are two question in this code segment:
    1.the line ticked with red color cannot return the right number of the area features in my layer.
    2.the code ticked with green color is excuted well for the first time,an error occurses with the secondary excution:Try to access the protected memory!
  • global_mapper
    global_mapper Administrator
    edited August 2008
    Everything looks ok in your code above, assuming that your GM_LayerInfo_t structure definition is correct. Do the other values in that structure look ok?

    Assuming that is fine, when you call the GM_AddAreaToCustomVectorLayer function, is it returning 0 or some error code?

    Your GM_FreeAreaFeature code looks correct, at least from my limited understanding of C#. You should just directly pass it the value that GM_GetAreaFeature provided you. Perhaps this one will sort itself out when the other problem is fixed.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Mike,
    I think the stuct GM_LayerInfo_t declare is OK and when calling the GM_AddAreaToCustomVectorLayer function, it is returning 0 :

    public struct GM_LayerInfo_t
    {


    public string mDescription; //' Description string
    public GM_Rectangle_t mNativeRect; //' Bounding rect of layer in native coordinates
    public GM_Rectangle_t mGlobalRect; //' Bounding rect of layer in global coordinates
    public Int32 mPixelWidth; //' RASTER/ELEV ONLY: Number of pixels wide layer is
    public Int32 mPixelHeight; //' RASTER/ELEV ONLY: Number of pixels tall layer is
    public GM_Projection_t mNativeProj; //' Native projection of layer
    public IntPtr mControlPoints; //' RASTER ONLY: Ground control points list
    public Int32 mNumGCPs; //' RASTER ONLY: Number of ground control points in list
    public double mMinElevation; //' ELEV ONLY: Minimum elevation in meters
    public double mMaxElevation; //' ELEV ONLY: Maximum elevation in meters
    public Int32 mNumAreas; //' VECTOR ONLY: Number of area features
    public Int32 mNumLines; //' VECTOR ONLY: Number of line features
    public Int32 mNumPoints; //' VECTOR ONLY: Number of point features
    public double mPixelSizeX; //' RASTER/ELEV ONLY: Pixel size in meters in the x direction
    public double mPixelSizeY; //' RASTER/ELEV ONLY: Pixel size in meters in the y direction
    public byte mHasRasterData; //' Does this layer have raster or elevation data?
    public byte mEnabled; //' Is this layer enabled for display or it it hidden?
    public byte mHasVectorData; //' Does this layer have vector data (the features counts can all be 0 for things like map catalogs)
    } ;

    the following image show you what is returned(do not mind the value of mDescription parameter is "MyPoint",In fact it is an area featurelayer.):
    attachment.php?attachmentid=98&stc=1&d=1219883790
  • global_mapper
    global_mapper Administrator
    edited August 2008
    I actually see some problems in your declaration of the GM_LayerInfo_t structure. You have the mMinElevation and mMaxElevation values declared as 'double' when they should be 'float'.

    Here are some definitions from the C# sample on our web site that should work:

    // This type is used to describe a single projection attribute value
    public struct GM_ProjAttrValue_t
    {
    public PROJATTR mAttr; // Attribute
    public double mValue; // Attribute value
    };

    // This type is used to fully describe a projection.
    public struct GM_Projection_t
    {
    public PROJSYS mProjSys; // Projection system
    public DATUM mDatum; // Horizontal datum
    public UNIT mUnit; // Ground units
    public UInt32 mNumAttrs; // Number of attributes in attribute list
    public GM_ProjAttrValue_t mAttr1; // Attribute value list items (C# doesn't support fixed length arrays)
    public GM_ProjAttrValue_t mAttr2;
    public GM_ProjAttrValue_t mAttr3;
    public GM_ProjAttrValue_t mAttr4;
    public GM_ProjAttrValue_t mAttr5;
    public GM_ProjAttrValue_t mAttr6;
    public GM_ProjAttrValue_t mAttr7;
    public GM_ProjAttrValue_t mAttr8;
    public GM_ProjAttrValue_t mAttr9;
    public GM_ProjAttrValue_t mAttr10;
    public GM_ProjAttrValue_t mAttr11;
    public GM_ProjAttrValue_t mAttr12;
    public GM_ProjAttrValue_t mAttr13;
    public GM_ProjAttrValue_t mAttr14;
    public GM_ProjAttrValue_t mAttr15;
    public GM_ProjAttrValue_t mAttr16;
    };

    // This type is used when rectifying imagery
    public struct GM_GroundControlPoint_t
    {
    public double PixelX; // x pixel coordinate of GCP
    public double PixelY; // y pixel coordinate of GCP (top is 0, increases down)
    public double GroundX; // x ground coordinate of GCP (in provided projection)
    public double GroundY; // y ground coordinate of GCP (in provided projection)
    };

    // This type is used when returning information about a layer
    public struct GM_LayerInfo_t
    {
    public string mDescription; // Description string
    public GM_Rectangle_t mNativeRect; // Bounding rect of layer in native coordinates
    public GM_Rectangle_t mGlobalRect; // Bounding rect of layer in global coordinates
    public UInt32 mPixelWidth; // RASTER/ELEV ONLY: Number of pixels wide layer is
    public UInt32 mPixelHeight; // RASTER/ELEV ONLY: Number of pixels tall layer is
    public GM_Projection_t mNativeProj; // Native projection of layer
    public IntPtr mControlPoints; // RASTER ONLY: Ground control points list. Point to GM_GroundControlPoint_t
    public UInt32 mNumGCPs; // RASTER ONLY: Number of ground control points in list
    public float mMinElevation; // ELEV ONLY: Minimum elevation in meters
    public float mMaxElevation; // ELEV ONLY: Maximum elevation in meters
    public UInt32 mNumAreas; // VECTOR ONLY: Number of area features
    public UInt32 mNumLines; // VECTOR ONLY: Number of line features
    public UInt32 mNumPoints; // VECTOR ONLY: Number of point features
    public double mPixelSizeX; // RASTER/ELEV ONLY: Pixel size in meters in the x direction
    public double mPixelSizeY; // RASTER/ELEV ONLY: Pixel size in meters in the y direction
    public Byte mHasRasterData; // Does this layer have raster or elevation data?
    public Byte mEnabled; // Is this layer enabled for display or it it hidden?
    public Byte mHasVectorData; // Does this layer have vector data (the features counts can all be 0 for things like map catalogs)
    public Byte mUsedDefaultPos; // RASTER/ELEV ONLY: Was the default position used for this layer since the file could not be automatically positioned?
    public string mFilename; // Filename from which layer was loaded (if this is an archive file, like .zip, then the name of the actual loaded file will be in mArchiveFilename
    public string mArchiveFilename; // Filename within archive file (e.g. .zip or .tar.gz) from which layer was loaded, if any (might be NULL)
    public string mTypeName; // Layer type name
    public UInt32 mGlobalPixelWidth; // RASTER/ELEV ONLY: Approximate number of pixels required in width for a 1:1 pixel mapping in the current projection
    public UInt32 mGlobalPixelHeight; // RASTER/ELEV ONLY: Approximate number of pixels required in height for a 1:1 pixel mapping in the current projection
    public IntPtr mMetadataList; // List of metadata attributes and values for the layer
    public UInt32 mMetadataListSize; // Number of entries in mMetadataList
    };


    Let me know if I can be of further assistance.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • JerryLia
    JerryLia Global Mapper User
    edited August 2008
    Hi,Mike,
    Now it works well,Thanks a lot!