Once in a while we are presented a task that doesn’t lend itself to the existing commands within Civil 3D. One case that I came across recently was the need to convert blocks and text to Civil 3D points. The points were needed to do a preliminary design and later a survey would be performed to get an adequate surface for design. In this post I’ll create a command that will have the user select the block (for position), select the text (for elevation), create a point and then output the newly created points information to the command line. To accomplish this I’ll be using the free version of the Sincpac.
First thing is I’m going to add a new class to the SincpacC3D 2010 Free Edition solution. Right click on the title in Solution Explorer and choose add new item.
Select the Class template and provide it a name that makes sense.
We can then open the newly created class and start programming.
In order to make it easier to program I usually rely on looking at other code. The easy way to do this is to create a new Vertical or Horizontal Tab. While I don’t state what code I’ve looked at, rest assured that I did use this.
Next we need to add the other using statements that will be required by the code and change the class to a public class. If we leave it as a class Civil 3D won’t be able to see the code.
Next I’ll add an aeccConn object from the C3DUtilities. The aeccConn object makes it easy to access the current drawings Civil 3D database. It’s a much easier way than outlined in the help files. I’ll use this later on in the code. In order to access it a new instance of it needs to be created. I’ve also add a Command Method for the code.
The next step is to get the block where the point I want to create is located at and then make sure getting the block was successful. The AddAllowedClass ensures the user may only select a block and no other types of objects. The SetRejectMessage is necessary to tell the user what type of object may be selected.
If its successful I’ll get the text which contains the elevation information using the same method as the block.
Next I’ll get the objects from the drawing’s database to get the required information to create the point, but first I need to get the database and use a transaction to get the objects.
From the text I’ll take the text string and convert it to a double value. I’ve enclosed it within a try in case there is other characters in there that aren’t convertible to a double value. If there are other characters additional code would be required to remove them to get to the elevation value only. A search of the internet will find examples on how to parse text.
Once the point was created I gave it a generic raw description. Now I’ll output the point’s Northing, Easting and Elevation to the command line. To format the number I’ll use the Formatter code from the Sincpac. This make it easy to convert a number to a string with a set percision, in this case to 2 decimal places.
Lastly I’ll end the try, commit the changes to the transaction and set the aeccConn value to null.
Now when I run the command I can easily change a block and text into a Civil 3D point. With some additional programming one could use a selection set of blocks and text and associate them based on their location. In my case it wasn’t worth the effort so I spent my time selecting the block and text entities separately. To run the command continuously use the Multiple AutoCAD command to repeat the command over and over again. Alternatively a loop could be added to continue the command until something is triggered, but the multiple command achieves the same affect with less effort on my part.
The completed code formatted poorly:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AECC.Interop.Land;
using Quux.C3DUtilities;
using Quux.AcadUtilities;
namespace Quux.SincpacC3D.ConvertBlocks
{
public class ConvertBlocks
{
private AeccAppConnection aeccConn = null;
[CommandMethod("SINCPAC-C3D", "ConvBlocks", null, CommandFlags.Modal, null, "SincpacC3D.chm", "SP_ChangeElevation")]
public void ChangeElevationCommand()
{
aeccConn = new AeccAppConnection();
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
// Select the block
PromptEntityOptions pops = new PromptEntityOptions("\nSelect Block: ");
pops.SetRejectMessage("\nSelection must be a block!");
pops.AddAllowedClass(typeof(BlockReference), false);
PromptEntityResult pres;
pres = ed.GetEntity(pops);
if (pres.Status == PromptStatus.OK)
{
// Select the text
PromptEntityOptions popsTxt = new PromptEntityOptions("\nSelect Text: ");
popsTxt.SetRejectMessage("\nSelection must be text!");
popsTxt.AddAllowedClass(typeof(DBText), false);
PromptEntityResult presTxt;
presTxt = ed.GetEntity(popsTxt);
if (presTxt.Status == PromptStatus.OK)
{
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
BlockReference oBlock = tr.GetObject(pres.ObjectId, OpenMode.ForRead, false) as BlockReference;
DBText oText = tr.GetObject(presTxt.ObjectId, OpenMode.ForRead, false) as DBText;
double dZ;
try
{
dZ = Converter.StringToDistance(oText.TextString);
Point3d oPt3D = new Point3d(oBlock.Position.X, oBlock.Position.Y, dZ);
AeccPoint oPoint = aeccConn.AeccDb.Points.Add(oPt3D.ToArray());
oPoint.RawDescription = "Converted Block and Text";
// Send the information to the command line.
string sE = Formatter.FormatNumberWithPrecision(oBlock.Position.X, 2);
string sN = Formatter.FormatNumberWithPrecision(oBlock.Position.Y, 2);
string sZ = Formatter.FormatNumberWithPrecision(dZ, 2);
ed.WriteMessage("\nEasting "+ sE);
ed.WriteMessage("\nNorthing "+ sN+ " Elevation "+ sZ);
}
catch { }
}
finally
{
tr.Commit();
}
}
}
}
aeccConn = null;
}
}
}
No comments:
Post a Comment