Global Navigation Bar

MapInfo Products Knowledge Base


Product: MapBasic
Version: 4.x\5.x\6.x
Platform: Not Platform Related
Category: Object Functions

Summary:
Removing a polygon from a region object.

Question:
Is there a way to remove a polygon from a multi-polygon region? Is there a way to remove a segment from a multi-segment polyline?

Answer:
Try the following code:

Include "MapBasic.Def"

Declare Sub Main
Declare Function RemovePolygon(ByVal mobjRegion as Object,ByVal intPolyNum as integer)As Object

Sub Main
'This is a stub program that uses the Removepoly function to remove
'a polygon from a region object. This should also work to remove
'a segment from a multi-part pline

'The resulting object will be placed into the cosmetic layer.
'Note that the result may not be obvious because the result should align
'perfectly with the input object.

Dim mobjNewObject as Object 'variable to hold the new map object
Dim intDeadPoly as Integer 'variable to hold the # of the polygon that is to be removed
Dim mobjOldObject as Object 'variable to hold the Old map object
Dim intWinID as Integer 'Holds the Window ID

intDeadPoly=2 'As a test, remove the second Polygon

If SelectionInfo(SEL_INFO_NROWS) Then
'There was a selection. Process only the first region selected

mobjOldObject=Selection.Obj 'Get the record's Map Object

'Check to make sure it's a valid Object Type...
If ObjectInfo(mobjOldObject,OBJ_INFO_TYPE) = OBJ_TYPE_REGION or
ObjectInfo(mobjOldObject,OBJ_INFO_TYPE) = OBJ_TYPE_PLINE Then

'MapInfo treats regions and polylines the same way

'Call the function that removes a polygon....
mobjNewObject = RemovePolygon(mobjOldObject,intDeadPoly)
Else
'It's not the right object type!!!
Note "Select a Region or Polyline Object"
End Program
End If
Else
'Nothing was selected
Note "A Region or Polyline object must be selected to run this sample."
End Program
End If

'At this point the new object is in the object variable.
'Time to put it in the cosmetic layer of the current map window.

intWinID=FrontWindow() 'Get the ID of the current window

If intWinID=0 Then
Note "There are no windows open."
End Program
End If

If WindowInfo(intWinID,WIN_INFO_TYPE) = WIN_MAPPER Then
'Insert the new object into the cosmetic layer
Insert Into WindowInfo(intWinID,WIN_INFO_TABLE) (OBJ) Values (mobjNewObject )
Else
'It's not a mapper
Note "The Polygon was removed but there was no a map window to display the new object!"
End If

End Sub

Function RemovePolygon(ByVal mobjRegion as Object,ByVal intPolyNum as integer)As Object
'This function removes the specified segment/polygon from the input object

Dim intRealPolys as Integer 'Holds the number of polygons/segments in the starting object

'Check to make sure that a valid Polygon is being looked at.
intRealPolys=ObjectInfo(mobjRegion,OBJ_INFO_NPOLYGONS)

If intRealPolys >= intPolyNum Then
'A valid Polygon was chosen

Do While intRealPolys = ObjectInfo(mobjRegion,OBJ_INFO_NPOLYGONS)
'Remove the first node of the polygon
Alter Object mobjregion Node Remove Position intPolyNum,1
Loop
Else
Note "There is no polygon " + intPolyNum + " to remove!"

'Return the input polygon

End If

'Set the return value for the function
RemovePolygon=mobjRegion

End Function

polyrmve.MB

Additional information:

While there is nothing wrong with this code it could be VERY slow for large objects. The essence of the code is:

Do While intRealPolys = ObjectInfo(mobjRegion,OBJ_INFO_NPOLYGONS)
'Remove the first node of the polygon
Alter Object mobjregion Node Remove Position intPolyNum,1
Loop

Not only is one node being removed at a time BUT the object has to be revalidated internally for each node removal. This is where the slow-down occurs.

Perhaps the following logic would be more efficient:

Check for a single polygon in the region and prompt the user or just delete the whole object. Otherwise, build a new object by extracting the nodes (using the ExtractNodes function) from each polygon except the one to be deleted and add it to the new object. Of course, a mechanism is needed for detecting if a polygon is a donut. There is no MapBasic function but in this scenario it would not be too hard to write. It would look something like this:

1. Extract nodes of first valid polygon as a region.
2. For all other polygons, get any node in the polygon and check if the point is entirely within the region built so far. If it is, extract the nodes for that polygon and call Erase instead of Combine. So, the pseudo code looks something like:

DeletePolyFromRegion(obj, PolynumToDelete)
Dim newobj as object
Dim Polynum as integer

CheckForValidPolyNumber()
HandleSinglePolyRegion()

NewObj = ExtractNodes (from first valid polygon)
For all polygons in region except one to delete and one already chosen
TempObj=ExtractNodes(currentPolyNum)
If (FirstPointOfTemp Is InsideNewOb())
NewObj=Erase(NewObj, TempObj)
else
NewObj=Combine(NewObj, TempObj)
:

:



Last Modified: 09/17/1998 10:01:09 PM
Global Navigation Bar