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

0 Members and 1 Guest are viewing this topic.

sinc

  • Guest
( C3D ) Generate Points and Polylines from Parcels?
« on: February 14, 2007, 10:51:04 AM »
This is the companion to the "Points on all Lot Corners at once?" thread, except this time I want to do it in Civil-3D.

So, is there any way to place COGO Points on all lot corners of a Parcel (or of all Parcels in a Site) all at once?  Ideally, I could right-click on the Parcel or Parcels collection and select "Generate Points...", but evidently that's too easy.  There is no such option.

In my explorations of XML Reporting, it looks like I can use the XML report ability to generate a CSV file from parcels that is very similar to the Map report I used in Land Desktop.  Then I can delete duplicates in Excel if necessary, and dump the points back into C3D using the Import Points option.  That's the direction I'll head unless anyone knows of any nifty tricks.

I actually haven't even been able to find the equivalent of Land Desktop's "Create closed polylines from parcels".  I didn't use that command often, but it came in very handy for some situations.  Anyone found the equivalent in C3D?

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #1 on: February 14, 2007, 12:06:37 PM »
May not be what you want but ... you can use: Points  -> Create Points -> Miscellaneous -> Along Line/Curve and select parcels.


TheSwamp.org  (serving the CAD community since 2003)

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #2 on: February 14, 2007, 12:15:58 PM »
Points  -> Create Points -> Miscellaneous -> Automatic also works well with parcels.
TheSwamp.org  (serving the CAD community since 2003)

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #3 on: February 14, 2007, 01:40:38 PM »
Points  -> Create Points -> Miscellaneous -> Automatic also works well with parcels.

That one almost does what I want, but just as with Land Desktop, it also creates points at the radius point of all arcs.  That's something I don't want.  So far, it's looking like an XML Report is the optimal solution, just like the Map Report Query was the way to go with Land Desktop.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #4 on: February 14, 2007, 08:20:25 PM »
A VBA macro may do what you want, Sinc. You can obtain just 1 parcel, any # of parcels, or all parcels from the user. For ALL, each Site has a ParcelSegments Collection, from which you can gather the start & end x/y's. Similarly, each Parcel Object has a ParcelLoops collection that hold the ParcelSegments.

By using the full site you would eliminate many of the duplicate points since all shared property lines are defined only once in the site, but are defined referenced in each of the parcels.

If I have some time in the next few days I'll investigate this.
« Last Edit: February 14, 2007, 08:21:27 PM by Jeff_M »

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #5 on: February 15, 2007, 11:24:21 AM »
I suggest adding the User-defined Property >>Coordinate, to your parcels.
Be your Best


Michael Farrell
http://primeservicesglobal.com/

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #6 on: February 15, 2007, 11:44:28 AM »
By using the full site you would eliminate many of the duplicate points since all shared property lines are defined only once in the site, but are defined referenced in each of the parcels.

This sounds like the ideal solution.  Since all I really want are the points, a VBA solution could loop on the site parcels, find all the coordinates, eliminate any duplicates, and then directly create the COGO points in the DWG.

As it is, I already invested the time in figuring out the XML reports, and I haven't yet written any VBA, so it was easier for me to just churn out an XSL file for the task.  That didn't take too long, and it works for my immediate task.  But it sounds like I may need to just start digging into VBA, and start using that in the future.

I suggest adding the User-defined Property >>Coordinate, to your parcels.

I'll have to play with this.  I'm not sure I quite understand what you're saying, but it might become apparant as soon as I start trying things.  But right now I've got other tasks that are more pressing, so I'll have to get back to it...

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #7 on: February 15, 2007, 02:10:04 PM »
I suggest adding the User-defined Property >>Coordinate, to your parcels.

Well I poked around in the docs and the Prospector but came up empty, can you give me a hint on how this is done?

thanks
TheSwamp.org  (serving the CAD community since 2003)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #8 on: February 15, 2007, 08:52:24 PM »
While I understand how to create and add the UDP, I'm not so sure I can figure out what Mike is alluding to.....

For Mark:
Quote from: C3DHelp
To assign user-defined properties to a parcel

In the drawing, define the properties within the User-Defined Classification. For more information, see Creating a User-Defined Property Classification
In Toolspace, on the Prospector tab, click the Parcels collection.
Right-click and click Parcel Properties.
In the Site Parcel Properties dialog box, click the Composition tab.
On the Composition tab, under User-Defined Property Classification, select the User-Defined Classification you want to assign to the Site Parcel.
In Toolspace, on the Prospector tab, select the parcel to which you assigned the User-Defined Classification.
In the parcel list view window, right-click a column heading. Select the user-defined properties you want to display in the list view window.
NoteYou can arrange the display of columns in the list view by dragging column headings. For more information, see Customizing a List View

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #9 on: February 16, 2007, 10:23:49 AM »
For Mark:
Quote from: C3DHelp
To assign user-defined properties to a parcel

In the drawing, define the properties within the User-Defined Classification. For more information, see Creating a User-Defined Property Classification
In Toolspace, on the Prospector tab, click the Parcels collection.
Right-click and click Parcel Properties.
In the Site Parcel Properties dialog box, click the Composition tab.
On the Composition tab, under User-Defined Property Classification, select the User-Defined Classification you want to assign to the Site Parcel.
In Toolspace, on the Prospector tab, select the parcel to which you assigned the User-Defined Classification.
In the parcel list view window, right-click a column heading. Select the user-defined properties you want to display in the list view window.
NoteYou can arrange the display of columns in the list view by dragging column headings. For more information, see Customizing a List View

I've created(?) a "User-Defined Property Classification" but it's not showing up any where. Interesting though, thanks Jeff.
TheSwamp.org  (serving the CAD community since 2003)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #10 on: February 16, 2007, 11:14:29 AM »
Hi Mark,
Yes, the UDP's can be tough to figure out. Have you added the desired UDP to a parcels collection? If so, and you can't see them in the Prospector for each lot, hit F5 or close the Toolspace and re-open it. Most times this will allow the UDP's to be seen/edited. I'd post a pic or 2 for ya, but I'm heading out into the field shortly. I have 1 setup called "House Plans" that allows me to input the type & square footage of each lot's house. I then was trying to create a table that shows this information....which I was able to do by running thru all kinds of hoops since the Parcels Table won't show the UDP's. But 2008 has fixed that!

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #11 on: February 16, 2007, 12:20:10 PM »
I think the part that confuses me is how adding a UDC to a parcel gets me COGO points on the lot corners.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #12 on: February 16, 2007, 12:43:38 PM »
My thought was, that once you get the UDP (COORDINATES) on the Parcel Segments,
this would be similar to Points on Objects via the MAP Query. Then you should be able to get at those points in your parcel reports XSL sheet.
Sometimes I don't get a chance to test these ideas :lol:.....what with so many competeing for attention.
Be your Best


Michael Farrell
http://primeservicesglobal.com/

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #13 on: February 16, 2007, 02:42:23 PM »
Are you saying that then I would be able to get a list with no duplicates?

I put together an XSL that directly pulls the starting coordinate for every parcel segment.  This works well, but it means that I get duplicates for corners that are on the boundary of more than one parcel.  I purge the duplicates in Excel, and dump the coordinates into C3D to create the points for stakeout exhibits and data collector uploads.

I'm thinking I'll try putting together a C# routine to create points directly.  Either that or VBA, but I have this dislike of Visual Basic that goes back over a decade, so I'm thinking I might just try C#.

I poked around a bit with the VBAIDE last night.  After spending the better part of an hour vainly searching Autodesk's documentation for how to create and name a new project, I finally gave up and tried checking the Swamp.  Two minutes later, I had my answer.   :wink:

After that, things went more smoothly.  I actually got a small routine working before I quit for the night, but it doesn't do anything except access the Parcel collection.  I must admit that I like having a full IDE, with an object browser and everything, and support for OO programming (unlike Lisp).  But it's still Visual Basic.  And judging from some of the discussion I've seen on the topic, it sounds like Autodesk is favoring the C# anyway.  So I'll probably spend some time this weekend installing SharpDevelop and trying to get a "COGO Points from Parcels" routine written in C#, and see how it goes.
« Last Edit: February 16, 2007, 02:45:49 PM by sinc »

sinc

  • Guest
Re: ( C3D ) Generate Points and Polylines from Parcels?
« Reply #14 on: February 18, 2007, 01:52:36 AM »
OK, got SharpDevelop downloaded, got the ObjectARX SDK downloaded and the help linked into SharpDevelop and figured out how to compile and debug projects, scanned through the C# language synopsis, and rooted through various other documentation, and came up with the following.

The way it sits right now, it creates points on all parcels in all sites in the drawing, just like I wanted.  I'd like to modify this so that it asks the user to select the site(s).  But it works well if there's only one site in the drawing, and it puts one COGO Point on each lot corner.  The points are created in a rather chaotic order, but it can't get any simpler for the tech.

This being my first C# program and all, I'm sure there's some things I should do differently.  I copied-and-pasted some of this code, and I notice the C3D invocation in partiular doesn't seem to work quite right (at least it gets confused if C3D is already open, and I try starting the program from SharpDevelop).  So let me know if you see obvious ways to improve the 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 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;

        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;

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

                long siteCount = m_oAeccDb.Sites.Count;
                m_sMessage += "Number of Sites = " + siteCount.ToString() + "\n\n";
                foreach (IAeccSite site in m_oAeccDb.Sites) {
                m_sMessage += "-- " + site.DisplayName + "\n\n";
                foreach (IAeccParcelSegment parcelSegment in site.ParcelSegments) {
                foreach (IAeccParcelSegmentElement parcelSegmentElement in parcelSegment) {
                double[] coords = {parcelSegmentElement.StartX, parcelSegmentElement.StartY, 0.0};
                cogoPoint = cogoPoints.Add(coords);
                cogoPoint.RawDescription = "LOTCORNER";
                }
                }
                }
                       
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage(m_sMessage);
                m_sMessage="";
            }       

}
}
}

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