Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Alignment name and station value from given point

w.wesselink
Contributor

Alignment name and station value from given point

w.wesselink
Contributor
Contributor

Is it possible to retrieve the name of the alignment and the station value at a given point?

I'm using C# for customization.

 

I want the software to use the X- and Y-value as input and that the class returns which alignment is located at that point and what the station value is on that point in the given alignment.

0 Likes
Reply
296 Views
8 Replies
Replies (8)

hosneyalaa
Advisor
Advisor
0 Likes

w.wesselink
Contributor
Contributor

We use Civil 3D for Rail alignment design.

I've written a program that checks an alignment if it meets the design requirements.

As an input for the alignment checker I use LandXML.

 

I also want to check the alignment for objects in, under, above and next to the alignment, like crossings, bridges, turnouts and platforms.

A turnout has a mathematical point (block insertion point) and 3 (or 4) end points (front, straight track en diverting track). A crossing, a bridge and a platform have 2 point (start and end).

From the block insertion point, insertion angle, direction and type of the turnout I can calculate the end points.

 

What I want to establish is that from the calculated end points the code can retrieve in which alignment the point is situated and what the station value of that point in the alignment is. For crossing, bridges and platforms I want the users to click in the drawing to pinpoint the start and end points.

 

 

0 Likes

hosneyalaa
Advisor
Advisor
0 Likes

w.wesselink
Contributor
Contributor

I've seen this in another post and I believe it will help.

The only thing is, I thing this method uses the alignment as input. I could use it on every alignment in the model and check the PointNotOnEntityException.

 

Is there a method I can use that returns the alignment a point is on? Then I can use it as a two steps method:

1. Get the ID of an alignment a point is on.

2. Use this ID to calculate the station on this alignment

0 Likes

hosneyalaa
Advisor
Advisor

It's better share
Drawing example and some of your code

0 Likes

w.wesselink
Contributor
Contributor

For start and end points I want to use the following method:

wwesselink_2-1736844320802.png

 

In the picture you see two alignments. Near these alignments you see  a level crossing and 2 platforms. As input I want to use the X,Y of the points I marked with a leader. To calculate the stationing the software has to know on which alignment the point is situated. I hope the station for the begin and end of the platform can be calculated by enlarging the offset or tolerance.

 

wwesselink_3-1736845024628.png

In the next picture you see three alignments and 2 turnouts. For the turnout it is possible to determine the coordinates of the front and both back points (I marked with a leader). In this case the front and the left side of the back of the turnout are situated in the same alignment. The back right side is situated in another alignment.

So in this case I also want to know on which alignment(s) every point is situated.

 

0 Likes

hippe013
Advisor
Advisor

Natively, there is not a function that returns an alignment based on a given point. However, one could easily be written. It might look something like this. 

Using VB.NET, 

 

Public Shared Function GetClosestAlignment(point As Point3d, cvlDoc As CivilDocument, ByRef result As Tuple(Of String, Double, Double)) As Boolean
   Dim ids As ObjectIdCollection = cvlDoc.GetAlignmentIds

   If ids.Count = 0 Then
      result = Nothing
      Return False
   End If

   Dim db As Database = ids(0).Database

   Dim minOffset As Double = Double.MaxValue
   Dim minStation As Double = 0
   Dim minAlignName As String = ""

   Dim station, offset As Double

   Using tr As Transaction = db.TransactionManager.StartTransaction
      For Each id As ObjectId In ids
         Dim align As Alignment = tr.GetObject(id, OpenMode.ForRead)

         Try
            align.StationOffset(point.X, point.Y, station, offset)
            If offset < minOffset Then
               minOffset = offset
               minStation = station
               minAlignName = align.Name
            End If
               Catch ex As PointNotOnEntityException
         End Try
      Next
   tr.Commit()
   End Using
   result = New Tuple(Of String, Double, Double)(minAlignName, minStation, minOffset)
   Return True
End Function

 

 

***EDIT*** 

 

Or a version that also passes back the ObjectId of the alignment too. 

 

Public Shared Function GetClosestAlignment(point As Point3d, cvlDoc As CivilDocument, ByRef result As Tuple(Of String, ObjectId, Double, Double)) As Boolean
   Dim ids As ObjectIdCollection = cvlDoc.GetAlignmentIds

   If ids.Count = 0 Then
      result = Nothing
      Return False
   End If

   Dim db As Database = ids(0).Database

   Dim minOffset As Double = Double.MaxValue
   Dim minStation As Double = 0
   Dim minAlignName As String = ""
   Dim minId As ObjectId = ObjectId.Null

   Dim station, offset As Double

   Using tr As Transaction = db.TransactionManager.StartTransaction
      For Each id As ObjectId In ids
         Dim align As Alignment = tr.GetObject(id, OpenMode.ForRead)

         Try
            align.StationOffset(point.X, point.Y, station, offset)
            If offset < minOffset Then
               minOffset = offset
               minStation = station
               minAlignName = align.Name
               minId = id
            End If
               Catch ex As PointNotOnEntityException
         End Try
      Next
      tr.Commit()
   End Using
   result = New Tuple(Of String, ObjectId, Double, Double)(minAlignName, minId, minStation, minOffset)
   Return True
End Function
0 Likes

w.wesselink
Contributor
Contributor

Thanks a lot hippe013

 

This code helped me a lot. The thing that went wrong with it at first, was that an offset can return a negative number, so this meant that it was marked as smaller than minOffset.

 

The code I wrote -based on your code- in C# works as a charm:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using StationTools;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(Commands))]

 

namespace StationTools

{

class Commands
{

[CommandMethod("PointToStation")]
public void PointToStation()
{

Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

 

PromptPointResult pPtRes;
PromptPointOptions pPtOpts = new PromptPointOptions("");

 

pPtOpts.Message = "\nSelect point: ";
pPtRes = doc.Editor.GetPoint(pPtOpts);

Point3d ptSelected = pPtRes.Value;

 

var result = GetClosestAlignment(ptSelected);

ed.WriteMessage("\nAlignment name: " + result.Item1);
ed.WriteMessage("\nStation: " + result.Item2);

}

public (string,double) GetClosestAlignment (Point3d point)
{

Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;

 

double offset = double.NaN;
double station = double.NaN;

double minOffset = double.MaxValue;
double minStation = double.MinValue;
string AlignName = "";

 

using (Transaction tr = db.TransactionManager.StartTransaction())

{

CivilDocument civDoc = CivilApplication.ActiveDocument;
ObjectIdCollection alignColl = civDoc.GetAlignmentIds();
foreach (ObjectId AlignId in alignColl)

{
Alignment align = (Alignment)tr.GetObject(AlignId, OpenMode.ForRead);
try
{

if (align.AlignmentType == AlignmentType.Rail)

{

align.StationOffset(point.X, point.Y, ref station, ref offset);

if (Math.Abs(offset) < minOffset)
{

minOffset = Math.Abs(offset);
minStation = station;
AlignName = align.Name;

}

}

}
catch
{

PointNotOnEntityException exception = new PointNotOnEntityException();

}

}
tr.Commit();

}
return (AlignName, minStation);

}

}

}