The following code demonstrates how to create valid polygons efficiently. Each of the functions uses a different interface in the creation:
- createMultipartPolygonRingSegmentCollection: Create a multipart polygon using rings via ISegmentCollection.
- createMultipartPolygonRingPointCollection: Create a multipart polygon using rings via IPointCollection.
- createSinglepartPolygonPointCollection: Create a single part polygon via IPointCollection.
- createSinglepartPolygonSegmentCollection: Create a single part polygon via ISegmentCollection.
- createRectanglePolygonFromEnvelope: Convert an envelope to a polygon via ISegmentCollection.
How to use
- Add the functions to your project.
//************************************************************************************************
//* GEOMETRY TYPE : POLYGON
//* NOTE :In the following samples the geometries are simple without having to use ITopologicalOpeartor::Simplify.
//* However if the data creation process cannot insure simple geometries
//* the geometries have to be simplified before storing or using those in geometry operations.
//************************************************************************************************
//*************************************************************************
//* NAME : createMultipartPolygonRingSegmentCollection
//* DESCRIPTION: Create a multipart polygon using rings via ISegmentCollection.
//* This function is demonstrating it by creating 1001
//* concentric square rings and add those to a polygon.
//* NOTE : This is the approach to use if non-linear segments (Circular Arc, Elliptical Arc and Bezier Curve) have to be created.
//*************************************************************************
HRESULT createMultipartPolygonRingSegmentCollection()
{
IGeometryCollectionPtr ipGonColl(CLSID_Polygon);
//*********************************************************
//THE SPATIAL REFERENCE SHOULD BE SET HERE ON THE POLYGON
//Here the spatial reference is created in memory but could also come from various sources:
//IMap, IGeodataset, IGeometry etc...
ISpatialReferencePtr ipspref(CLSID_UnknownCoordinateSystem);
ipspref->SetFalseOriginAndUnits( - 10000, - 10000, 100000);
// Set the false origin and units.
// The XYUnits value is equivalent to the precision specified when creating a feature class
IGeometryPtr ipGeoSpRef(ipGonColl);
ipGeoSpRef->putref_SpatialReference(ipspref);
// *********************************************************
// Initialize offset values
double d0X0=0, d0Y0=0, d0X1=0, d0Y1=0, d0X2=0, d0Y2=0, d0X3=0,
d0Y3=0;
double d1X0=10000, d1Y0=10000, d1X1=10000, d1Y1=10000, d1X2=10000,
d1Y2=10000, d1X3=10000, d1Y3=10000;
int i, j;
// Initialize the points
IPointPtr ipPointsRing0[4];
IPointPtr ipPointsRing1[4];
for (i=0; i < 4; ++i)
{
ipPointsRing0[i].CreateInstance(CLSID_Point);
ipPointsRing1[i].CreateInstance(CLSID_Point);
}
// Loop to change the coordinates of the points
ISegmentCollectionPtr ipRingColl[2];
ILinePtr ipLine0[4];
ILinePtr ipLine1[4];
ISegmentPtr ipSeg0[4];
ISegmentPtr ipSeg1[4];
IGeometryPtr ipGeometry[2];
for (i=0; i < 1001; ++i)
{
ipRingColl[0].CreateInstance(CLSID_Ring);
ipRingColl[1].CreateInstance(CLSID_Ring);
// Lines are passed by reference to the polygon using ISegmentCollection
// so a new line has to be instantiated to avoid the polygon to become degenerated
for (j=0; j < 4; ++j)
{
ipLine0[j].CreateInstance(CLSID_Line);
ipLine1[j].CreateInstance(CLSID_Line);
// QI (Query interface) to make sure that we have the correct type of geometry
// when passing these arrays to the addsegments.
// If passing directly the lines array it will fatal VB. This is a known limit of VB.
ipSeg0[j]=ipLine0[j];
ipSeg1[j]=ipLine1[j];
}
ipGeometry[0]=ipRingColl[0];
ipGeometry[1]=ipRingColl[1];
d0X0 -= 5;
d0Y0 -= 5;
d0X1 += 5;
d0Y1 -= 5;
d0X2 += 5;
d0Y2 += 5;
d0X3 -= 5;
d0Y3 += 5;
// Put the coordinates of the points to use in the first ring
ipPointsRing0[0]->PutCoords(d0X0, d0Y0);
ipPointsRing0[1]->PutCoords(d0X1, d0Y1);
ipPointsRing0[2]->PutCoords(d0X2, d0Y2);
ipPointsRing0[3]->PutCoords(d0X3, d0Y3);
d1X0 -= 5;
d1Y0 -= 5;
d1X1 -= 5;
d1Y1 += 5;
d1X2 += 5;
d1Y2 += 5;
d1X3 += 5;
d1Y3 -= 5;
// Put the coordinates of the points to use in the second ring
ipPointsRing1[0]->PutCoords(d1X0, d1Y0);
ipPointsRing1[1]->PutCoords(d1X1, d1Y1);
ipPointsRing1[2]->PutCoords(d1X2, d1Y2);
ipPointsRing1[3]->PutCoords(d1X3, d1Y3);
// Put the coordinates of the lines
ipLine0[0]->PutCoords(ipPointsRing0[0], ipPointsRing0[1]);
ipLine0[1]->PutCoords(ipPointsRing0[1], ipPointsRing0[2]);
ipLine0[2]->PutCoords(ipPointsRing0[2], ipPointsRing0[3]);
ipLine0[3]->PutCoords(ipPointsRing0[3], ipPointsRing0[0]);
ipLine1[0]->PutCoords(ipPointsRing1[0], ipPointsRing1[1]);
ipLine1[1]->PutCoords(ipPointsRing1[1], ipPointsRing1[2]);
ipLine1[2]->PutCoords(ipPointsRing1[2], ipPointsRing1[3]);
ipLine1[3]->PutCoords(ipPointsRing1[3], ipPointsRing1[0]);
// Add the segments to the rings
for (j=0; j < 4; ++j)
{
ipRingColl[0]->AddSegment(ipSeg0[j]);
ipRingColl[1]->AddSegment(ipSeg1[j]);
}
// Add the rings to the polygon
for (j=0; j < 2; ++j)
{
ipGonColl->AddGeometry(ipGeometry[j]);
}
}
// You can draw, store or use the polygon (ipGonColl) in other geometry operations at this point
return S_OK;
}
//*************************************************************************
//* NAME : createMultipartPolygonRingPointCollection
//* DESCRIPTION : Create a multipart polygon using rings via IPointCollection.
//* This sub is demonstrating it by creating 1001
//* concentric square rings and add those to a polygon.
//*************************************************************************
HRESULT createMultipartPolygonRingPointCollection()
{
// Create the resulting polygon
IGeometryCollectionPtr ipGonColl(CLSID_Polygon);
//*********************************************************
// THE SPATIAL REFERENCE SHOULD BE SET HERE ON THE POLYGON
// Here the spatial reference is created in memory but could also come from various sources:
// IMap, IGeodataset, IGeometry etc...
ISpatialReferencePtr ipspref(CLSID_UnknownCoordinateSystem);
ipspref->SetFalseOriginAndUnits( - 10000, - 10000, 100000);
// Set the false origin and units.
// The XYUnits value is equivalent to the precision specified when creating a feature class
IGeometryPtr ipGeoSpRef(ipGonColl);
ipGeoSpRef->putref_SpatialReference(ipspref);
// *********************************************************
double d0X0=0, d0Y0=0, d0X1=0, d0Y1=0, d0X2=0, d0Y2=0, d0X3=0,
d0Y3=0;
double d1X0=10000, d1Y0=10000, d1X1=10000, d1Y1=10000, d1X2=10000,
d1Y2=10000, d1X3=10000, d1Y3=10000;
int i, j;
IPointCollectionPtr ipRingsColl[2];
IGeometryPtr ipGeometry[2];
IPointPtr ipPointsRing0[5];
IPointPtr ipPointsRing1[5];
// Loop to change the coordinates of the points
for (i=0; i < 1001; ++i)
{
ipRingsColl[0].CreateInstance(CLSID_Ring);
ipRingsColl[1].CreateInstance(CLSID_Ring);
//QI(Query Interface) to make sure that we have the correct type of geometry when passing this array to the addsegments
ipGeometry[0]=ipRingsColl[0];
ipGeometry[1]=ipRingsColl[1];
// Create the new points
for (j=0; j < 5; ++j)
{
ipPointsRing0[j].CreateInstance(CLSID_Point);
ipPointsRing1[j].CreateInstance(CLSID_Point);
}
d0X0 -= 5;
d0Y0 -= 5;
d0X1 -= 5;
d0Y1 += 5;
d0X2 += 5;
d0Y2 += 5;
d0X3 += 5;
d0Y3 -= 5;
// Put the coordinates of the points to use in the first ring
ipPointsRing0[0]->PutCoords(d0X0, d0Y0);
ipPointsRing0[1]->PutCoords(d0X1, d0Y1);
ipPointsRing0[2]->PutCoords(d0X2, d0Y2);
ipPointsRing0[3]->PutCoords(d0X3, d0Y3);
ipPointsRing0[4]->PutCoords(d0X0, d0Y0);
// Add the points to the ring
for (j=0; j < 5; ++j)
{
ipRingsColl[0]->AddPoint(ipPointsRing0[j]);
}
d1X0 -= 5;
d1Y0 -= 5;
d1X1 -= 5;
d1Y1 += 5;
d1X2 += 5;
d1Y2 += 5;
d1X3 += 5;
d1Y3 -= 5;
// Put the coordinates of the points to use in the second ring
ipPointsRing1[0]->PutCoords(d1X0, d1Y0);
ipPointsRing1[1]->PutCoords(d1X1, d1Y1);
ipPointsRing1[2]->PutCoords(d1X2, d1Y2);
ipPointsRing1[3]->PutCoords(d1X3, d1Y3);
ipPointsRing1[4]->PutCoords(d1X0, d1Y0);
// Add the points to the ring
for (j=0; j < 5; ++j)
{
ipRingsColl[1]->AddPoint(ipPointsRing0[j]);
}
// Add the rings to the polygon
for (j=0; j < 2; ++j)
{
ipGonColl->AddGeometry(ipGeometry[j]);
}
}
// You can draw, store or use the polygon (ipGonColl) in other geometry operations at this point
return S_OK;
}
//*************************************************************************
//* NAME : createSinglepartPolygonPointCollection
//* DESCRIPTION : Create a single part polygon via IPointCollection.
//*************************************************************************
HRESULT createSinglepartPolygonPointCollection()
{
IPointCollectionPtr ipGonColl(CLSID_Polygon);
;
//*********************************************************
// THE SPATIAL REFERENCE SHOULD BE SET HERE ON THE POLYGON
// Here the spatial reference is created in memory but could also come from various sources:
// IMap, IGeodataset, IGeometry etc...
ISpatialReferencePtr ipspref(CLSID_UnknownCoordinateSystem);
ipspref->SetFalseOriginAndUnits( - 10000, - 10000, 100000);
// Set the false origin and units.
// The XYUnits value is equivalent to the precision specified when creating a feature class
IGeometryPtr ipGeoSpRef(ipGonColl);
ipGeoSpRef->putref_SpatialReference(ipspref);
//*********************************************************
int i;
// Initialize the points
IPointPtr ipPoint[5];
for (i=0; i < 5; ++i)
{
ipPoint[i].CreateInstance(CLSID_Point);
}
ipPoint[0]->PutCoords(0, 0);
ipPoint[1]->PutCoords(0, 10);
ipPoint[2]->PutCoords(10, 10);
ipPoint[3]->PutCoords(10, 0);
ipPoint[4]->PutCoords(0, 0);
// Add the points to the polygon
for (i=0; i < 5; ++i)
{
ipGonColl->AddPoint(ipPoint[i]);
}
// You can draw, store or use the polygon (ipGonColl) in other geometry operations at this point
return S_OK;
}
//*************************************************************************
//* NAME : createSinglepartPolygonSegmentCollection
//* DESCRIPTION : Create a single part polygon via ISegmentCollection.
//*************************************************************************
HRESULT createSinglepartPolygonSegmentCollection()
{
ISegmentCollectionPtr ipGonColl(CLSID_Polygon);
//*********************************************************
// THE SPATIAL REFERENCE SHOULD BE SET HERE ON THE POLYGON
// Here the spatial reference is created in memory but could also come from various sources:
// IMap, IGeodataset, IGeometry etc...
ISpatialReferencePtr ipspref(CLSID_UnknownCoordinateSystem);
ipspref->SetFalseOriginAndUnits( - 10000, - 10000, 100000);
// Set the false origin and units.
// The XYUnits value is equivalent to the precision specified when creating a feature class
IGeometryPtr ipGeoSpRef(ipGonColl);
ipGeoSpRef->putref_SpatialReference(ipspref);
//*********************************************************
// Initialize things
int i;
ILinePtr ipLine[4];
IPointPtr ipPoint[4];
ISegmentPtr ipSegment[4];
for (i=0; i < 4; ++i)
{
ipLine[i].CreateInstance(CLSID_Line);
ipPoint[i].CreateInstance(CLSID_Point);
ipSegment[i]=ipLine[i];
}
// Put the coordinates of the points
ipPoint[0]->PutCoords(0, 0);
ipPoint[1]->PutCoords(0, 10);
ipPoint[2]->PutCoords(10, 10);
ipPoint[3]->PutCoords(10, 0);
// Put the coordinates of the line
ipLine[0]->PutCoords(ipPoint[0], ipPoint[1]);
ipLine[1]->PutCoords(ipPoint[1], ipPoint[2]);
ipLine[2]->PutCoords(ipPoint[2], ipPoint[3]);
ipLine[3]->PutCoords(ipPoint[3], ipPoint[0]);
// Add the segments in the polygon via the ISegmentCollection
for (i=0; i < 4; ++i)
{
ipGonColl->AddSegment(ipSegment[i]);
}
// You can draw or store the polygon (ipGonColl)
return S_OK;
}
//*************************************************************************
//* NAME : CreateRectanglePolygonFromEnvelope
//* DESCRIPTION : Convert an envelope to a polygon via ISegmentCollection
//*************************************************************************
HRESULT CreateRectanglePolygonFromEnvelope()
{
IEnvelopePtr ipEnvelope(CLSID_Envelope);
//*********************************************************
// THE SPATIAL REFERENCE SHOULD BE SET HERE ON THE ENVELOPE
// Here the spatial reference is created in memory but could also come from various sources:
// IMap, IGeodataset, IGeometry etc...
ISpatialReferencePtr ipspref(CLSID_UnknownCoordinateSystem);
ipspref->SetFalseOriginAndUnits( - 10000, - 10000, 100000);
// Set the false origin and units.
// The XYUnits value is equivalent to the precision specified when creating a feature class
ipEnvelope->putref_SpatialReference(ipspref);
//*********************************************************
ipEnvelope->PutCoords(0, 0, 100, 100);
ISegmentCollectionPtr ipSegmentColl(CLSID_Polygon);
ipSegmentColl->SetRectangle(ipEnvelope);
// This is transferring the spatial reference
//You can draw or store the polygon (ipSegmentColl)
return S_OK;
}
Development licensing | Deployment licensing |
---|---|
Engine Developer Kit | Engine |