Author Topic: ( C3D ) Generate Points and Polylines from Parcels?  (Read 9520 times)

0 Members and 1 Guest are viewing this topic.

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #15 on: February 19, 2007, 02:08:44 AM »
Here's an improved version.  I noticed that, due to the way C3D works, the first version sometimes created duplicates for some points.  And occasionally, it would skip a point.  So I changed the routine to scan through all parcels, grab the coordinates of both ends of each segment and throw them in a list of coordinates, throw out duplicates, and create only one Cogo points for each unique coordinate.  The code counts two coordinates as being the same point if they fall within .01 of each other.  This precision is currently hard-coded, but could be made a user-configurable parameter.  Likewise, it sets the description for all points to "LOTCORNER" in the code; this could be configured to use any user-selected string, or the current default description.

I also put in some code to allow the user to select a single site, or just hit return to create points for all parcels on all sites.  I started off trying to create a dialog box, but it looks like it's going to take a bit longer to figure out Windows Forms programming than it took to figure out the basics of C#...   :?

Code: [Select]
/*
 * Created by SharpDevelop.
 * User: Sinc
 * Date: 2/17/2007
 * Time: 1:38 PM
 *
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AECC.Interop.Land;
using Autodesk.AECC.Interop.UiLand;

namespace LotCorner
{
/// <summary>
/// Description of MyClass.
/// </summary>
public class LotCornerApp
{
private Autodesk.AutoCAD.Interop.IAcadApplication m_oAcadApp = null;
private Autodesk.AECC.Interop.UiLand.IAeccApplication m_oAeccApp = null;
private Autodesk.AECC.Interop.UiLand.IAeccDocument m_oAeccDoc = null;
private IAeccDatabase m_oAeccDb = null;
private CoordinateList m_oCoordinateList = null;

string m_sAcadProdID = "AutoCAD.Application";
string m_sAeccAppProgId = "AeccXUiLand.AeccApplication";

private string m_sMessage="";

[CommandMethod("LOTCORNERS")]
public void LotCorners()
{
//Start Civil-3D, or get it if it's already running
try
{
m_oAcadApp = (Autodesk.AutoCAD.Interop.IAcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject(m_sAcadProdID);
}
catch (System.Exception /*ex*/)
{
System.Type AcadProg = System.Type.GetTypeFromProgID(m_sAcadProdID);
m_oAcadApp  = (Autodesk.AutoCAD.Interop.IAcadApplication)System.Activator.CreateInstance(AcadProg, true);
//Instead above two lines of code, simply use following new ().
//However, this always creates an instance of the
//AutoCAD even if it is already running.
//m_oAcadApp = new Autodesk.AutoCAD.Interop.AcadApplicationClass();
}

if (m_oAcadApp != null)
{
m_oAcadApp.Visible = true;
m_oAeccApp = (IAeccApplication)m_oAcadApp.GetInterfaceObject(m_sAeccAppProgId);
m_oAeccDoc = (IAeccDocument)m_oAeccApp.ActiveDocument;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

// get the Database object via a late bind
m_oAeccDb = (IAeccDatabase)m_oAeccDoc.GetType().GetProperty("Database").GetValue(m_oAeccDoc, null);

int siteCount = m_oAeccDb.Sites.Count;
int idx = 0;
m_sMessage += "Number of Sites = " + siteCount.ToString() + "\n";
while (idx < siteCount) {
m_sMessage += idx.ToString() + " -- " + m_oAeccDb.Sites.Item(idx++).DisplayName + "\n";
}
ed.WriteMessage(m_sMessage);
m_sMessage="";
PromptIntegerOptions ops = new PromptIntegerOptions("Select a Site, or hit <RETURN> for all: ");
ops.AllowNone = true;
ops.LowerLimit = 0;
ops.UpperLimit = siteCount - 1;
PromptIntegerResult choice = ed.GetInteger(ops);
m_oCoordinateList = new CoordinateList();
switch (choice.Status) {
case PromptStatus.None:
foreach (IAeccSite site in m_oAeccDb.Sites) {
addPointsForSite(site);
}
goto default;
case PromptStatus.OK:
addPointsForSite(m_oAeccDb.Sites.Item(choice.Value));
goto default;
case PromptStatus.Cancel:
break;
default:
createAllPoints();
break;
}
ed.WriteMessage(m_sMessage);
m_sMessage="";
}
}

private void addPointsForSite(IAeccSite site) {
foreach (IAeccParcelSegment parcelSegment in site.ParcelSegments) {
foreach (IAeccParcelSegmentElement parcelSegmentElement in parcelSegment) {
addPointsForElement(parcelSegmentElement);
}
}
}

private void addPointsForElement(IAeccParcelSegmentElement parcelSegmentElement) {
m_oCoordinateList.Add(new Coordinate(parcelSegmentElement.StartX, parcelSegmentElement.StartY, 0.0));
m_oCoordinateList.Add(new Coordinate(parcelSegmentElement.EndX, parcelSegmentElement.EndY, 0.0));
}

private void createAllPoints() {
IEnumerator<Coordinate> e = m_oCoordinateList.GetEnumerator();
while (e.MoveNext()) {
IAeccPoint cogoPoint = m_oAeccDb.Points.Add(e.Current.CoordinateArray());
cogoPoint.RawDescription = "LOTCORNER";
}
}
}

public class Coordinate
{
private double x, y, z;
public Coordinate(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}

public double[] CoordinateArray() {
// this returns full precision for coordinates
double[] cArray = {this.x, this.y, this.z};
return cArray;
}

public string key() {
// key rounds coordinates to 2 decimal places
string key = this.x.ToString("F2") + "," + this.y.ToString("F2") + "," + this.z.ToString("F2");
return key;
}
}

public class CoordinateList : KeyedCollection<string, Coordinate>
{
public CoordinateList() : base() {}

protected override string GetKeyForItem(Coordinate item)
{
return item.key();
}

public new void Add(Coordinate item) {
// because key is rounded to 2 decimal places, coordinate will
// not be added to list if it is within ~0.01 feet of a point
// that is already in the list
if (!this.Contains(item.key())) {
base.Add(item);
}
}
}

}
« Last Edit: February 19, 2007, 02:11:05 AM by sinc »

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #16 on: February 20, 2007, 02:31:18 PM »
Nicely Done....!
Be your Best


Michael Farrell
http://primeservicesglobal.com/

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #17 on: February 21, 2007, 01:32:48 AM »
Thanks.

I cleaned things up a bit more, and also created a DLL for people who haven't gotten into compiling .NET code yet.  Revised code, DLL, and instructions can be found here.

Since it's now compiled into a DLL, I went ahead and added the ability to set the default description for the points.  After the DLL is loaded, type LCDESC to change the description.  This value gets written to the registry, so it will persist even when Civil-3D is shut down and restarted.

Cannon

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #18 on: February 21, 2007, 10:55:47 AM »
Nice work, Sinc. I posted a link and couple of comments on civil3d.com.

Thank you for sharing, that's a good one.

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #19 on: March 05, 2007, 05:24:50 PM »
The "new and improved" version of this routine is now available at:

http://www.ejsurveying.com/sincpacc3d.htm