Max points in a polyline shapefile? Redraw slows down considerably after 300 points added...

Jul 6, 2011 at 9:39 PM

Hello,

I'm attempting to display a path of a vehicle by adding many points to a polyline shape in a shapefile.

I've discovered that after about adding 400 points, the refresh rate slows down drastically.  What is the limit of the number of points that can be added to a shapefile?

I call the following code from an OnTimer method.  After about 300 points, the redraw rate goes to about 1 second... VERY SLOW.

int CMyMapDlg::AddPathPoint(int layerHandle, double x, double y, long shapeIndex)
{
    VARIANT_BOOL returnVal;
    HRESULT hr;
    try
    {
        MapWinGIS::IShapefilePtr pShapefile = (MapWinGIS::IShapefilePtr)m_Map.get_GetObject(layerHandle);
        hr = pShapefile->StartEditingShapes(TRUE, NULL, &returnVal);
        MapWinGIS::IShapePtr pShape;
        hr = pShapefile->get_Shape(shapeIndex, &pShape);
        MapWinGIS::IPointPtr pPoint;
        hr = pPoint.CreateInstance(__uuidof(MapWinGIS::Point));
        pPoint->put_x(x);
        pPoint->put_y(y);
        long pointIndex = 0;
        hr = pShapefile->EditInsertShapes(pShape, &shapeIndex, &returnVal);
        hr = pShape->InsertPoint(pPoint, &pointIndex, &returnVal);
        hr = pShapefile->StopEditingShapes(TRUE, TRUE, NULL, &returnVal);
        return pointIndex;
    }
    catch
    {
    }
}
Any help would be greatly appreciated!
Frank

Developer
Jul 7, 2011 at 1:26 AM

Frank, 

no such limit exists (apart from limit on std::vector size, RAM, etc.). 

The first suggestion: don't start/stop editing mode after every change. Start in the beginning of execution and stop on closing. Probably consider to use in-memory shapefile (empty string should be passed in Shapefile.Open).

But 1 second on redraw is still very suspicious, probably some drawing issues are involved. Let me know how it works after proposed changes.

The other thing: check whether the time is spent on redraw or some other operations (set Map.ShowRedrawTime property to true).

Jul 7, 2011 at 2:21 PM

sleschinski,

Thanks for the quick response.

I am using the ShowRedrawTime property - that's how I discovered the redraw rate was slow.

I am using an in-memory (empty file name) shapefile.  When I call my CreateShapefile method (listed below), I send in NULL as the sFilename (first parameter).

I did add a line to StartEditShapes method call inside the CreateShapefile method, and have added the corresponding StopEditShapes method call in the DestroyWindow method (on dialog close).

Unfortunately, there still appears to be an issue with adding more than 300 points.  The redraw rate starts out at 0.090 seconds and by the time the 300 points are added, the redraw rate is above 1.0 second

 

Question:  What shapeIndex should I send in to my AddPathPoint (in my previous post)?  I'm using zero (0), thinking that it should add the point as the last item on the point vector...  

 

int CMyMapDlg::CreateShapefile(LPCTSTR sFilename,
                               MapWinGIS::ShpfileType sfType, //MapWinGIS::ShpfileType::SHP_POINT
                               BOOL isVisible, // = TRUE
                               float opacityFlag, // = 1.0f
                               long lineColor, // = RGB(0,0,0)
                               float lineWidth, // = 1.0f
                               long fillColor) // = RGB(255,255,255)
{
    HRESULT hr;
    VARIANT_BOOL returnVal;
    int layerHandle = -1;
    BSTR bstrSFFilename = SysAllocString(sFilename);
    BSTR bstrFieldName;
    //Declare a shapefile pointer
    MapWinGIS::IShapefilePtr pShapefile;
    //Create an instance of shapefile
    hr = pShapefile.CreateInstance(__uuidof(MapWinGIS::Shapefile));


    if (FAILED(hr))
    {
        //AfxMessageBox(TEXT("Error: Failed to create a new shapefile."));
        return IDS_ERROR_FAILED_CREATE_SHAPEFILE;
    }
    //pShapefile->get_SourceType(MapWinGIS::tkShapefileSourceType::sstInMemory);
    hr = pShapefile->CreateNew(bstrSFFilename, sfType, &returnVal); //MapWinGIS::ShpfileType::SHP_POINT

    if (SUCCEEDED(hr))
    {
        MapWinGIS::IFieldPtr pField;
        long FieldIndex = 0;
        hr = pField.CreateInstance(__uuidof(MapWinGIS::Field));
        if (FAILED(hr))
            return IDS_ERROR_FAILED_CREATE_FIELD;

        if (!bstrSFFilename)
            bstrFieldName = SysAllocString(TEXT("InMemoryFile"));
        else
            bstrFieldName = SysAllocString(sFilename);
        hr = pField->put_Name(bstrFieldName);
        if (FAILED(hr))
        {
            //afxmessagebox(text("error: failed to set the field name."));
            return IDS_ERROR_FAILED_FIELD_NAME;
        }
        hr = pField->put_Type(MapWinGIS::STRING_FIELD);  //MapWinGIS::FieldType::STRING_FIELD
        if (FAILED(hr))
            return IDS_ERROR_FAILED_FIELD_TYPE;

        hr = pShapefile->StartEditingShapes(TRUE, NULL, &returnVal);
        hr = pShapefile->EditInsertField(pField, &FieldIndex, NULL, &returnVal);

        hr = pShapefile->StopEditingShapes(TRUE, TRUE, NULL, &returnVal);

        layerHandle = m_Map.AddLayer(pShapefile, isVisible);
        //Now, modify the drawing attributes
        m_Map.put_ShapeLayerLineColor(layerHandle, lineColor);
        m_Map.put_ShapeLayerLineWidth(layerHandle, lineWidth);
        m_Map.put_ShapeLayerFillColor(layerHandle, fillColor);
        m_Map.put_ShapeLayerFillTransparency(layerHandle, opacityFlag);

        //NEW CODE: Start edit mode here --- Stop edit mode on close
        pShapefile->StartEditShapes(TRUE, TRUE, NULL, &returnVal);
    }
    return layerHandle;
}

 

 

Jul 7, 2011 at 5:48 PM

Using a for loop in my OnInitDialog method, I added 300 points.  I then use a timer event (OnTimer) to move the vehicle.  I noticed that as soon as I zoomed into just the vehicle (meaning, MapWinGIS didn't have to draw the 300 point path) the redraw rate shot back up to a normal amount.

So, I'm wondering if there is a possible work around I could use.  I've not used shape parts.  Would making points in a path as a "part" of the line work better?  

Frank

Developer
Jul 7, 2011 at 7:42 PM

Frank,

<<Question:  What shapeIndex should I send in to my AddPathPoint (in my previous post)?  I'm using zero (0), thinking that it should add the point as the last item on the point vector...  

In case you pass 0 as index, the point will be added at 0 position, which is ineffective. Better to pass Shape.numPoints as index or simply a big number (it will be corrected to Shape.numPoints automatically);

Try to save your in-memory shapefile (Shapefile.SaveAs) and then load it once more (in MapWindow for example) and see the redraw rate. Then it will be clear is there a problem of in-memory mode or a problem with particular shapefile.

Regards,

Sergei