| name | c3d-points |
| description | COGO points, point groups, UDPs, description keys, point styles, bulk editing |
Civil 3D Points
Use this skill when working with COGO points - creating, querying, grouping, styling, or using description keys.
Points Collection
All points are in CivilDocument.CogoPoints (CogoPointCollection):
CogoPointCollection cogoPoints = doc.CogoPoints;
ObjectId pointId = cogoPoints.Add(new Point3d(4958, 4079, 200), true);
ObjectId pointId2 = cogoPoints.Add(new Point3d(100, 200, 225), "GRND", true);
ObjectId pointId3 = cogoPoints.Add(
new Point3d(100, 200, 225), "GRND",
useDescriptionKey: true, matchOnParams: true, useNextPointNumSetting: true);
Point3dCollection pts = new Point3dCollection(
new[] { new Point3d(4927, 3887, 150), new Point3d(5101, 3660, 250) });
ObjectIdCollection ids = cogoPoints.Add(pts, true);
ObjectIdCollection ids2 = cogoPoints.Add(pts, "GRND", true);
ObjectId found = cogoPoints.GetPointByPointNumber(100);
bool exists = cogoPoints.Contains(100);
uint total = cogoPoints.Count;
foreach (ObjectId pid in cogoPoints)
{
CogoPoint pt = pid.GetObject(OpenMode.ForRead) as CogoPoint;
ed.WriteMessage("Point #{0}: Elev={1}\n", pt.PointNumber, pt.Elevation);
}
cogoPoints.Remove(779);
cogoPoints.Remove(pointId);
cogoPoints.Clear();
CogoPoint Properties
CogoPoint pt = pointId.GetObject(OpenMode.ForWrite) as CogoPoint;
pt.PointName = "point1";
pt.RawDescription = "Point description";
pt.DescriptionFormat = "$*";
pt.PointNumber = 100;
pt.Renumber(100);
pt.Renumber(100, PointNumberResolveType.UseNext);
string fullDesc = pt.FullDescription;
Point3d location = pt.Location;
ObjectId primaryGroup = pt.PrimaryPointGroupId;
bool movable = pt.IsMovable;
bool survey = pt.IsSurveyPoint;
double easting = pt.Easting;
double northing = pt.Northing;
double elevation = pt.Elevation;
double gridE = pt.GridEasting;
double gridN = pt.GridNorthing;
double lat = pt.Latitude;
double lon = pt.Longitude;
double conv = pt.Convergence;
pt.IsLocked = true;
pt.ShowToolTip = true;
pt.MarkerRotation = 0.785;
pt.LabelRotation = 0.0;
pt.LabelLocation = new Point3d(, , );
pt.ScaleXY = ;
pt.ScaleZ = ;
scale = pt.Scale;
pt.IsLabelVisible = ;
pt.IsLabelPinned = ;
dragged = pt.IsLabelDragged;
pt.LeaderVisibility = LeaderVisibilityType.Always;
pt.LeaderAttachment = LeaderAttachmentBehaviorType.TopOfText;
pt.LeaderTailVisibility = LeaderTailVisibilityType.UseStyle;
ObjectIdCollection compIds = pt.GetLabelTextComponentIds();
pt.SetLabelTextComponentOverride(compIds[], );
overrideText = pt.GetLabelTextComponentOverride(compIds[]);
isOverridden = pt.IsLabelTextComponentOverriden(compIds[]);
pt.ClearLabelTextComponentOverrides(compIds[]);
pt.ClearAllLabelTextComponentOverrides();
pt.ResetLabel();
pt.ResetLabelLocation();
pt.ResetLabelRotation();
pt.StyleId = pointStyleId;
pt.LabelStyleId = labelStyleId;
(pt.IsProjectPoint)
{
checkedOut = pt.IsCheckedOut;
version = pt.ProjectVersion;
}
pt.ApplyDescriptionKeys();
Bulk Editing
CogoPointCollection provides bulk methods with three overloads each:
- Single point by ObjectId
- All points in list to single value
- All points in list to corresponding values
cogoPoints.SetElevationByOffset(cogoPoints, 3.00);
cogoPoints.SetRawDescription(cogoPoints, "NEW_DESC");
cogoPoints.SetDescriptionFormat(cogoPoints, "$*");
cogoPoints.SetElevationBySurface(cogoPoints, surfaceId);
cogoPoints.SetEasting(cogoPoints, 1000.0);
cogoPoints.SetNorthing(cogoPoints, 2000.0);
cogoPoints.SetScaleXY(cogoPoints, 1.0);
cogoPoints.SetScaleZ(cogoPoints, 1.0);
cogoPoints.SetMarkerRotation(cogoPoints, 0.785);
cogoPoints.SetLabelRotation(cogoPoints, 0.0);
cogoPoints.SetPointName(pointId, "PT1");
cogoPoints.SetIsLocked(cogoPoints, true);
cogoPoints.SetShowTooltips(cogoPoints, true);
Point Groups
Point groups define subsets of points. All groups in doc.PointGroups.
PointGroupCollection pgCollection = doc.PointGroups;
ObjectId pgId = pgCollection.Add("My Point Group");
PointGroup pg = pgId.GetObject(OpenMode.ForWrite) as PointGroup;
pg.Description = "Optional description";
bool exists = pgCollection.Contains("My Point Group");
ObjectId existingId = pgCollection["My Point Group"];
ObjectId byIndex = pgCollection[0];
int count = pgCollection.Count;
ObjectId allPtsId = pgCollection.AllPointsPointGroupId;
string allPtsName = PointGroup.AllPointsGroupName;
pgCollection.Remove(pgId);
pgCollection.Remove("My Point Group");
if (pg.ContainsPoint(cogoPoint.PointNumber))
ed.WriteMessage("Point is in group\n");
uint[] pointNumbers = pg.GetPointNumbers();
uint pointCount = pg.PointsCount;
bool isAllPoints = pg.IsAllPointsGroup;
pg.LockPoints();
pg.UnlockPoints();
pg.IsLocked = true;
pg.DeletePoints();
pg.PointStyleId = styleId;
pg.IsPointStyleOverridden = true;
pg.PointLabelStyleId = labelStyleId;
pg.IsPointLabelStyleOverridden = true;
pg.ElevationOverride.FixedElevation = 100;
pg.ElevationOverride.ActiveOverrideType = PointGroupOverrideType.FixedValue;
pg.IsElevationOverridden = true;
pg.RawDescriptionOverride.FixedRawDescription = ;
pg.RawDescriptionOverride.ActiveOverrideType = PointGroupOverrideType.FixedValue;
pg.IsRawDescriptionOverridden = ;
ObjectIdCollection drawOrder = pgCollection.DrawOrder;
pgCollection.DrawOrder = drawOrder;
outOfDate = pg.IsOutOfDate;
ObjectIdCollection staleGroups = pgCollection.GetOutOfDatePointGroupIds();
pgCollection.UpdateAllPointGroups();
Standard Queries
Match points by descriptions, elevations, names, numbers:
StandardPointGroupQuery query = new StandardPointGroupQuery();
query.IncludeElevations = "100-200";
query.IncludeFullDescriptions = "FLO*";
query.IncludeNumbers = ">2200";
query.ExcludeElevations = "150-155";
query.ExcludeNames = "BRKL";
pg.SetQuery(query);
pg.Update();
ed.WriteMessage("Selected: {0} points\nQuery: {1}\n",
pg.PointsCount, query.QueryString);
Include/Exclude property values:
- Single number:
"110.01"
- Range:
"1-100"
- Greater/less than:
">200", "<-100"
- Multiple (comma-separated):
"<-100,1-100,110.01,>200"
- Wildcards in descriptions/names:
"IP*", "?X*"
All Include* properties are ORed; all Exclude* properties are ORed. Final query = (Includes) AND NOT (Excludes).
Custom Queries
For nested queries not expressible with StandardQuery:
CustomPointGroupQuery customQuery = new CustomPointGroupQuery();
customQuery.QueryString =
"(RawDescription='GR*') AND (PointElevation>=100 AND PointElevation<=300)";
pg.SetQuery(customQuery);
pg.Update();
Operators: =, >, <, >=, <=, AND, OR, NOT, parentheses for grouping.
Pending Changes
PointGroupChangeInfo changes = pg.GetPendingChanges();
ed.WriteMessage("To add: {0}, To remove: {1}\n",
changes.PointsToAdd.Length, changes.PointsToRemove.Length);
pg.Update();
Changes are registered when points matching the query are added/removed, NOT when the query itself changes.
User-Defined Properties (UDPs)
UDPs attach custom data to points, organized in classifications:
UDPClassification udpClass = doc.PointUDPClassifications.Add("Example");
AttributeTypeInfoInt attrInfo = new AttributeTypeInfoInt("Int UDP");
attrInfo.DefaultValue = 15;
attrInfo.UpperBoundValue = 20;
attrInfo.LowerBoundValue = 10;
UDPInteger udp = udpClass.CreateUDP(attrInfo);
PointGroup pg = pgId.GetObject(OpenMode.ForWrite) as PointGroup;
pg.UseCustomClassification("Example");
UDP Types
| Type | Class | Extra Properties |
|---|
| Integer | UDPInteger | UpperBoundValue, LowerBoundValue, *Inclusive |
| Double | UDPDouble | UpperBoundValue, LowerBoundValue, *Inclusive |
| String | UDPString | (none) |
| Boolean | UDPBoolean | (none) |
| Enumeration | UDPEnumeration | GetEnumValues() |
AttributeTypeInfo Classes
AttributeTypeInfoInt - integer with bounds
AttributeTypeInfoDouble - double with bounds
AttributeTypeInfoString - string
AttributeTypeInfoBool - boolean
AttributeTypeInfoEnum - enumeration
CreateUDP() accepts an optional GUID parameter to create identical UDPs across drawings.
Listing UDPs
foreach (UDPClassification udpClass in doc.PointUDPClassifications)
{
foreach (UDP udp in udpClass.UDPs)
{
ed.WriteMessage("UDP: {0}, GUID: {1}, Default: {2}\n",
udp.Name, udp.Guid, udp.DefaultValue);
}
}
Point Styles
ObjectId styleId = doc.Styles.PointStyles.Add("My Point Style");
PointStyle style = styleId.GetObject(OpenMode.ForWrite) as PointStyle;
style.MarkerType = PointMarkerDisplayType.UseCustomMarker;
style.CustomMarkerStyle = CustomMarkerType.CustomMarkerPlus;
style.CustomMarkerSuperimposeStyle = CustomMarkerSuperimposeType.Square;
style.MarkerSymbolName = "BLOCK_NAME";
cogoPoint.StyleId = styleId;
Display settings accessed via GetDisplay*(), GetLabelDisplay*(), GetMarkerDisplay*() methods for Model, Plan, Profile, or Section views.
Point Label Styles
var labelStyles = doc.Styles.LabelStyles.PointLabelStyles;
cogoPoint.LabelStyleId = labelStyleId;
Point Label Property Fields
<[Name(CP)]>
<[Point Number]>
<[Northing(Uft|P4|RN|AP|Sn|OF)]>
<[Easting(Uft|P4|RN|AP|Sn|OF)]>
<[Raw Description(CP)]>
<[Full Description(CP)]>
<[Point Elevation(Uft|P3|RN|AP|Sn|OF)]>
<[Latitude(Udeg|FDMSdSp|P6|RN|DPSn|CU|AP|OF)]>
<[Longitude(Udeg|FDMSdSp|P6|RN|DPSn|CU|AP|OF)]>
<[Grid Northing(Uft|P4|RN|AP|Sn|OF)]>
<[Grid Easting(Uft|P4|RN|AP|Sn|OF)]>
<[Scale Factor(P3|RN|AP|OF)]>
<[Convergence(Udeg|FDMSdSp|P6|RN|AP|OF)]>
<[Survey Point]>
Description Keys
Automatically apply styles and settings to points by matching descriptions:
ObjectId keySetId = PointDescriptionKeySetCollection
.GetPointDescriptionKeySets(acaddoc.Database)
.Add("My Key Set");
PointDescriptionKeySet keySet = keySetId.GetObject(OpenMode.ForWrite)
as PointDescriptionKeySet;
ObjectId keyId = keySet.Add("GRND*");
PointDescriptionKey key = keyId.GetObject(OpenMode.ForWrite) as PointDescriptionKey;
key.StyleId = pointStyleId;
key.ApplyStyleId = true;
key.LabelStyleId = labelStyleId;
key.ApplyLabelStyleId = true;
key.ApplyDrawingScale = false;
key.ScaleParameter = 1;
key.ApplyScaleParameter = true;
key.ApplyScaleXY = true;
key.FixedMarkerRotation = 0.785398163;
key.RotationDirection = RotationDirType.Clockwise;
key.ApplyFixedMarkerRotation = true;
var allKeySets = PointDescriptionKeySetCollection
.GetPointDescriptionKeySets(acaddoc.Database);
ObjectIdCollection searchOrder = allKeySets.SearchOrder;
allKeySets.SearchOrder = searchOrder;
pointGroup.ApplyDescriptionKeys();
Wildcards ? and * are supported in the Code property.
Using Points with TIN Surfaces
TinSurface surface = surfaceId.GetObject(OpenMode.ForWrite) as TinSurface;
surface.PointGroupsDefinition.AddPointGroup(pointGroupId);
cogoPoints.SetElevationBySurface(pointId, surfaceId);
cogoPoints.SetElevationBySurface(pointIds, surfaceId);
Import / Export Points
PointFileFormatCollection formats =
PointFileFormatCollection.GetPointFileFormats(acaddoc.Database);
PointFileFormat pnezd = formats["PNEZD (comma delimited)"];
uint importedCount = CogoPointCollection.ImportPoints(
@"C:\points.csv", pnezd);
uint importedCount2 = CogoPointCollection.ImportPoints(
@"C:\points.csv", pnezd, pointGroupId);
uint importedCount3 = CogoPointCollection.ImportPoints(
@"C:\points.csv", pnezd,
useAdjustedElevation: false,
shouldTransformCoordinate: false,
shouldExpandCoordinateData: false);
uint exportedCount = CogoPointCollection.ExportPoints(
@"C:\output.csv", pnezd);
uint exportedCount2 = CogoPointCollection.ExportPoints(
@"C:\output.csv", pnezd, pointGroupId);
Reading / Writing UDP Values on Points
CogoPoint pt = pointId.GetObject(OpenMode.ForWrite) as CogoPoint;
pt.SetUDPValue(udpInteger, 42);
pt.SetUDPValue(udpDouble, 3.14);
pt.SetUDPValue(udpString, "hello");
pt.SetUDPValue(udpBoolean, true);
pt.SetUDPValue(udpEnumeration, "ValueName");
int intVal = pt.GetUDPValue(udpInteger);
double dblVal = pt.GetUDPValue(udpDouble);
string strVal = pt.GetUDPValue(udpString);
bool boolVal = pt.GetUDPValue(udpBoolean);
string enumVal = pt.GetUDPValue(udpEnumeration);
Gotchas
PointNumber setter throws if number exists; use Renumber() for conflict resolution
FullDescription is read-only (computed from DescriptionFormat + RawDescription)
Location is read-only; modify via Easting, Northing, Elevation
- Accessing
IsCheckedOut/ProjectVersion on non-project points throws
- All
Add overloads on CogoPointCollection require a bool useNextPointNumSetting parameter
- Point group overrides take precedence over individual point settings
StandardPointGroupQuery ORs all includes and ORs all excludes
- Pending changes aren't registered when the query itself changes, only when matching points are added/removed
- Description key search order determines priority when multiple keys match
SetPointName on CogoPointCollection has no "set all to same value" overload (unlike other bulk methods)
Related Skills
c3d-label-styles - Point label style creation
c3d-surfaces - Points as surface data
c3d-root-objects - Accessing point collections
acad-editor-input - Selection sets for COGO point operations
c3d-survey — Survey points imported as COGO points