It seems we are doing the same work simultaneously, Ryan.
I have just been through this and created the process below. I have also attached my code.
It does require that you have the tables in a map window.
It will loop through your polygon table and for each polygon select the points that lie inside.
Depending on the number of points, it will do one of four things:
0. Ignore the polygon
1. Copy the polygon as it is
2. Split the polygon with a line connecting the two points that has been rotated 90 degrees at the centroid.
3. Create Voronoi polygons inside the polygon
Option two became a bit cumbersome as I couldn't find any spatial operations that could do this on a spatial object variable so I had to do some table magic instead and use targets.
You'll have to modify the column part to match your columns. Maybe that part can be improved a bit.
Let me know what you think and if you have suggestions on how to improve it
Include "MapBasic.def"
Dim nRowIDPolygon, nRowIDVoronoi As Integer,
oPolygon, oPoint1, oPoint2, oLine, oCutter As Object,
sQuery1, sQuery2 As String,
aObj As Alias
Fetch First From PolygonTable
Do Until EOT(PolygonTable)
nRowIDPolygon = PolygonTable.ROWID
oPolygon = PolygonTable.OBJ
Set Map Window FrontWindow() Layer PolygonTable Editable On
Select * From PolygonTable
Where ROWID = nRowIDPolygon
sQuery1 = SelectionInfo(SEL_INFO_SELNAME)
Set Target On
Select * From shops
Where OBJ Within oPolygon
sQuery2 = SelectionInfo(SEL_INFO_SELNAME)
Do Case SelectionInfo(SEL_INFO_NROWS)
Case 0
'**No points selected within boundary
Print "Whoops, some territories with no points - need to handle that manually -> ignore these"
Case 1
Print "Whoops, some territories with one point - need to handle that manually"
Insert Into VoronoiTable
(Address, City, State, Zip, OBJ)
Select Address, City, State, Zip, OBJ From sQuery2
Update VoronoiTable
Set OBJ = oPolygon
Where ROWID = TableInfo(VoronoiTable, TAB_INFO_NROWS)
Close Table sQuery2
Case 2
Print "Whoops, some territories with two points - need to handle that manually"
Set Map Window FrontWindow() Layer VoronoiTable Editable On
aObj = sQuery2 & ".obj"
Fetch First From sQuery2
oPoint1 = aObj
Fetch Next From sQuery2
oPoint2 = aObj
oLine = ConnectObjects(oPoint1, oPoint2, TRUE)
oLine = RotateAtPoint(oLine, 90, Centroid(oLine))
Insert Into VoronoiTable
(obj)
Values (oPolygon)
nRowIDVoronoi = TableInfo(VoronoiTable, TAB_INFO_NROWS)
Select * From VoronoiTable
Where ROWID = nRowIDVoronoi
Set Target On
Insert Into VoronoiTable
(obj)
Values (oLine)
nRowIDVoronoi = TableInfo(VoronoiTable, TAB_INFO_NROWS)
Select * From VoronoiTable
Where ROWID = nRowIDVoronoi
Create Cutter Into Target
Fetch Last From VoronoiTable
oCutter = VoronoiTable.OBJ
Delete From VoronoiTable
Where ROWID = (nRowIDVoronoi - 1)
Delete From VoronoiTable
Where ROWID = (nRowIDVoronoi + 0)
Delete From VoronoiTable
Where ROWID = (nRowIDVoronoi + 1)
Insert Into VoronoiTable
(Address, City, State, Zip, OBJ)
Select Address, City, State, Zip, OBJ From sQuery2
Update VoronoiTable
Set OBJ = Erase(oPolygon, oCutter)
Where ROWID = TableInfo(VoronoiTable, TAB_INFO_NROWS) - 1
Update VoronoiTable
Set OBJ = Overlap(oPolygon, oCutter)
Where ROWID = TableInfo(VoronoiTable, TAB_INFO_NROWS)
Set Map Window FrontWindow() Layer PolygonTable Editable On
Close Table sQuery2
Case Else
Create Object As Voronoi
from Selection
Into Table VoronoiTable
Data Address = Address, City = City, State = State, Zip = Zip
Close Table sQuery2
End Case
Close Table sQuery1
Fetch Next From PolygonTable
Loop
------------------------------
Peter Horsbøll Møller
Principal Presales Consultant | Distinguished Engineer
Precisely | Trust in Data
------------------------------
Original Message:
Sent: 12-07-2022 05:37
From: Ryan Cook
Subject: Voronoi with less than 3 points
Hello.
I am confused as to why a region cannot be divided into voronois using less than 3 points. A single point should return a copy of the region, while two points should comfortably divide the region into two. When running the voronoi function as part of a loop within a program that works through a region table, that MapInfo errors out when a region contains 1 or 2 points is rather frustrating. Is there a workaround for this?
Ryan
------------------------------
Ryan Cook
Knowledge Community Shared Account
------------------------------