Community
Civil 3D Customization
Welcome to Autodesk’s AutoCAD Civil 3D Forums. Share your knowledge, ask questions, and explore popular AutoCAD Civil 3D Customization topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get section points problem

16 REPLIES 16
Reply
Message 1 of 17
Anonymous
1659 Views, 16 Replies

Get section points problem

Hello guys,

 

I'm trying to get and then to write the surface section points but I having some problems here.

My section line don't cross a surface entirely but the section points collection returns some strange data where it should be null.

In the picture bellow I show a surface profile where there is no data between -200 and -175 and also there is no data between -90 and 50. The problem is my code returns section points where locations are placed at this no data space (for example these points: [0.00,7.60] [4.56,8.06] [241.84,8.65] [250.00,8.70]).

 

Capturar.PNG

 

Code:

Private Sub TEMP()
            'Selecionando DOC do Civil 3D
            Dim civilDoc As CivilDocument = CivilApplication.ActiveDocument
            Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim oDBase As Database = acDoc.Database

            'Listando alinhamentos no arquivo
            Dim alignColl As ObjectIdCollection = civilDoc.GetAlignmentIds()

            Dim oTrans As Transaction = oDBase.TransactionManager.StartTransaction()
            Using (oTrans)
                Try
                    'Selecionando cada alinhamento
                    For Each oAlignmentId As ObjectId In alignColl 'for each alignment
                        Dim oAlignment As Alignment = oTrans.GetObject(oAlignmentId, OpenMode.ForRead)

                        'selecionando cada sample line groups
                        If oAlignment.GetSampleLineGroupIds.Count > 0 Then

                            For Each oSampleLineGroupId In oAlignment.GetSampleLineGroupIds
                                Dim oSampleLineGroup As SampleLineGroup = oTrans.GetObject(oSampleLineGroupId, OpenMode.ForRead)

                                'selecionando cada sample line do sample group
                                For Each oSampleLineId As ObjectId In oSampleLineGroup.GetSampleLineIds
                                    Dim oSampleLine As SampleLine = oTrans.GetObject(oSampleLineId, OpenMode.ForRead)

                                    'selecionando cada section do sampleline
                                    For Each oSectionID As ObjectId In oSampleLine.GetSectionIds
                                        Dim oSection As Autodesk.Civil.DatabaseServices.Section = oTrans.GetObject(oSectionID, OpenMode.ForRead)
                                        Dim oSectionPoints As SectionPointCollection = oSection.SectionPoints

                                    Next
                                Next oSampleLineId
                            Next oSampleLineGroupId
                        End If
                    Next oAlignmentId

                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            End Using
        End Sub

I am sending also the dwg file and the excel file with the results.

 

What am I doing wrong?

 

Thank you,

16 REPLIES 16
Message 2 of 17
tyronebk
in reply to: Anonymous

This was brought up in another thread but I can't be bothered to look for it. Basically you have to weed out the points that occur outside of the LeftOffset and RightOffset. This is a simple C# method I used to return valid points (no guarantees that it will work in all situations, you can probably neaten the code up with some linq too):

 

private IEnumerable<SectionPoint> GetValidSectionPoints( Section section )
{
  var valid = new HashSet<SectionPoint>();
  foreach ( var sp in section.SectionPoints )
  {
    try
    {
      if ( sp.Location.X >= section.LeftOffset && sp.Location.X <= section.RightOffset )
      {
        valid.Add( sp );
      }
    }
    catch {}
  }
  return valid;
}

I don't recall why the try catch is needed here, you may have to debug it to see if it ever catches anything.

 

Message 3 of 17
Jeff_M
in reply to: Anonymous

I brought this up for the COM API a few years ago. I found, then, that the .NET API also showed the same issue. I ended up with a similar solution what @tyronebk showed. It also shows that this issue occurs with all section, not just surface or corridor.

Jeff_M, also a frequent Swamper
EESignature
Message 4 of 17
Anonymous
in reply to: Jeff_M

Thank you guys,

 

Should this code work when I am in this situation?

 

Capturar.JPG

 

I'll try to use it today at home. I must understand how leftoffset and rightoffset works because I have a void between them...

 

Thanks again,

Message 5 of 17
joantopo
in reply to: Anonymous

Hi.

Have a look to this post:

 

https://forums.autodesk.com/t5/autocad-civil-3d-customization/improving-section-sectionpoints-in-api...

 

Exactly.Be careful when you get the sectionPoint collection.

 

I did some methods to filter the collection and check if a sectionpoint really is on the surface section such as:

 

Checking if a sectionpoint, converted in x, y coordinates, has an elevation with the surface class: surface.GetElevationAtXY( )

 

Or you can get the border of the surface and convert to a mpolygon to check if the point ×, y in plan is inside the mpolygon.

 

 

 

 

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
Message 6 of 17
Anonymous
in reply to: joantopo

Thank you @joantopo,

 

I am doing the same here. Checking surface correspondent data with GetElevationAtXY() at every section point.

 

This should be improved in API core. I'm working with many and long samplelines, and very triangulated surface (with gives me many section points)... it can be very time consuming 😕

 

I didn't have considered to check point x surface boundaries and it should be faster (once saving it as a list of coordinates, not using API, analyzing by math). I'll try later.

 

Thanks,

Message 7 of 17
joantopo
in reply to: Anonymous

Exactly.
The second method is very very fast.


Enviado de Samsung Mobile
Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
Message 8 of 17
joantopo
in reply to: joantopo

Hi diegoal.

 

Look at the response of Rogersame in this post.

 

http://forums.augi.com/showthread.php?100954-Como-crear-reporte-de-secciones

 

 

We can extract this data from the XML file using an editor.

 

Regards.

 

 

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
Message 9 of 17
tyronebk
in reply to: Jeff_M

I forgot to post this at the time, but I think I found a solution to this working with the COM API methods and properties. I have no idea if it's faster or slower than checking the points against the surface, but I thought I'd share it. I will admit that I don't fully understand when each of the SectionLinkType enums are used, but so far it has worked for my needs. Please offer improvements.

 

public static class Extensions_Section
{  
  public static IEnumerable<SectionPoint> GetValidSectionPoints( this Section section )
  {
    var valid = new HashSet<Point3d>();
    dynamic comSec = section.AcadObject; // AeccSection
    dynamic comLinks = comSec.Links; // AeccSectionLinks
    for ( int i = 0; i < comLinks.Count; i++ )
    {
      dynamic comLink = comLinks.Item( i ); // AeccSectionLink
      if ( comLink.Type != 1 )
      {
        valid.Add( new Point3d( comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ ) );
        valid.Add( new Point3d( comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ ) );
      }
    }
    return ( from sp in section.SectionPoints
          where valid.Contains( sp.Location )
          select sp );
  }

  public static IEnumerable<Section.SectionLink> GetSectionLinks( this Section section )
  {
    dynamic comSec = section.AcadObject; // AeccSection
    dynamic comLinks = comSec.Links; // AeccSectionLinks
    for ( int i = 0; i < comLinks.Count; i++ )
    {
      dynamic comLink = comLinks.Item( i ); // AeccSectionLink
      var start = ( from sp in section.SectionPoints
                where sp.Location.IsEqualTo( new Point3d( comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ ) )
                select sp ).First();
      var end = ( from sp in section.SectionPoints
              where sp.Location.IsEqualTo( new Point3d( comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ ) )
              select sp ).First();
      if ( start != null && end != null )
      {
        yield return new Section.SectionLink( start, end, i, comLink.Type );
      }
    }
  }

  public static IEnumerable<Section.SectionLink> GetValidSectionLinks( this Section section )
  {
    return ( from sl in section.GetSectionLinks()
          where sl.Type != SectionLinkType.NoDraw
          select sl );
  }
}

public static partial class Section
{
  public class SectionLink
  {
    public SectionPoint StartPoint;
    public SectionPoint EndPoint;
    public readonly int Index;
    public readonly SectionLinkType Type;

    public SectionLink( SectionPoint startPoint, SectionPoint endPoint, int index, SectionLinkType type )
    {
      StartPoint = startPoint;
      EndPoint = endPoint;
      Index = index;
      Type = type;
    }
  }
}

public enum SectionLinkType
{
  None = 0, // aeccSectionLinkNone
  NoDraw = 1, // aeccSectionLinkNoDraw
  All = 2 // aeccSectionLinkAll
}
Message 10 of 17
Jeff_M
in reply to: tyronebk

Thanks for sharing, Tyrone. I won't be able to do more than take a quick glance for a while, but it looks like it should be just fine for most, if not all, cases we'd need.
Jeff_M, also a frequent Swamper
EESignature
Message 11 of 17
tyronebk
in reply to: Jeff_M

Hey Jeff. Sorry, my post was in reply to your post but my comments were meant more for the community at large. I know that you always offer assistance when you have time.

Message 12 of 17
hosneyalaa
in reply to: tyronebk

HI @tyronebk 

 

can you help me
I have this code and I don't know how to use the code he wrote

Is it possible to recognize him?

 

How can he make it work?
thank you

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using aGi = Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using CivDb = Autodesk.Civil.DatabaseServices;

using Autodesk.Civil;

namespace Extensions_Section
{
    public class Extensions_Section
    {

       
        [CommandMethod("testExtensions_Section")]
        public void stExtensions_SectiondA()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            
            Database db = doc.Database;
            CivilDocument civdoc = CivilApplication.ActiveDocument;
            
            Editor ed = doc.Editor;
                        PromptEntityOptions entOpts = new PromptEntityOptions("Select section:");
            entOpts.SetRejectMessage("...not a section, try again.");
            entOpts.AddAllowedClass(typeof(CivDb.Section), true);
            PromptEntityResult entRes = ed.GetEntity(entOpts);
            if (entRes.Status != PromptStatus.OK)
                return;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                CivDb.Section sec = (CivDb.Section)entRes.ObjectId.GetObject(OpenMode.ForRead);

                var LL = GetSectionLinks(sec);
                var LLPOINT = GetValidSectionPoints(sec);


                tr.Commit();
            }
        }





    }


    public static class Extensions_Section
    {
        public static IEnumerable<SectionPoint> GetValidSectionPoints(this Section section)
        {
            var valid = new HashSet<Point3d>();
            dynamic comSec = section.AcadObject; // AeccSection
            dynamic comLinks = comSec.Links; // AeccSectionLinks
            for (int i = 0; i < comLinks.Count; i++)
            {
                dynamic comLink = comLinks.Item(i); // AeccSectionLink
                if (comLink.Type != 1)
                {
                    valid.Add(new Point3d(comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ));
                    valid.Add(new Point3d(comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ));
                }
            }
            return (from sp in section.SectionPoints
                    where valid.Contains(sp.Location)
                    select sp);
        }

        public static IEnumerable<Section.SectionLink> GetSectionLinks(this Section section)
        {
            dynamic comSec = section.AcadObject; // AeccSection
            dynamic comLinks = comSec.Links; // AeccSectionLinks
            for (int i = 0; i < comLinks.Count; i++)
            {
                dynamic comLink = comLinks.Item(i); // AeccSectionLink
                var start = (from sp in section.SectionPoints
                             where sp.Location.IsEqualTo(new Point3d(comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ))
                             select sp).First();
                var end = (from sp in section.SectionPoints
                           where sp.Location.IsEqualTo(new Point3d(comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ))
                           select sp).First();
                if (start != null && end != null)
                {
                    yield return new Section.SectionLink(start, end, i, comLink.Type);
                }
            }
        }

        public static IEnumerable<Section.SectionLink> GetValidSectionLinks(this Section section)
        {
            return (from sl in section.GetSectionLinks()
                    where sl.Type != SectionLinkType.NoDraw
                    select sl);
        }
    }

    public static partial class Section
    {
        public class SectionLink
        {
            public SectionPoint StartPoint;
            public SectionPoint EndPoint;
            public readonly int Index;
            public readonly SectionLinkType Type;

            public SectionLink(SectionPoint startPoint, SectionPoint endPoint, int index, SectionLinkType type)
            {
                StartPoint = startPoint;
                EndPoint = endPoint;
                Index = index;
                Type = type;
            }
        }
    }

    public enum SectionLinkType
    {
        None = 0, // aeccSectionLinkNone
        NoDraw = 1, // aeccSectionLinkNoDraw
        All = 2 // aeccSectionLinkAll
    }





}

 Capture1.JPG

Message 13 of 17
Jeff_M
in reply to: hosneyalaa

@hosneyalaa 

1. You cannot have a class name the same as the Namespace, changing the class to ExtensionsSection solves this.

2. Extension methods need to be called like so:

                var LL = sec.GetSectionLinks();
                var LLPOINT = sec.GetValidSectionPoints();

3. Section is ambiguous (it is defined in more than one assembly) so all of the extension methods need to be modified like so:

(this CivDb.Section section)

 

I think that should do it.

Jeff_M, also a frequent Swamper
EESignature
Message 14 of 17
hosneyalaa
in reply to: Jeff_M

Hi @Jeff_M 

Sorry I couldn't change as you directed me
Due to poor of experience with C-Sharp
Attach the project


If you have time to look at it
to make the appropriate modification


thank you

Message 15 of 17
Jeff_M
in reply to: hosneyalaa

@hosneyalaa I mistyped a portion of my previous response. It wasn't the class and namespace that was the issue, it was that you had 2 classes with the same name. This should work for you:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using aGi = Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using CivDb = Autodesk.Civil.DatabaseServices;

namespace Extensions_Section
{
    public class Extensions_Section
    {
        [CommandMethod("testExtensions_Section")]
        public void stExtensions_SectiondA()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;
            CivilDocument civdoc = CivilApplication.ActiveDocument;

            Editor ed = doc.Editor;
            PromptEntityOptions entOpts = new PromptEntityOptions("Select section:");
            entOpts.SetRejectMessage("...not a section, try again.");
            entOpts.AddAllowedClass(typeof(CivDb.Section), true);
            PromptEntityResult entRes = ed.GetEntity(entOpts);
            if (entRes.Status != PromptStatus.OK)
                return;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                CivDb.Section sec = (CivDb.Section)entRes.ObjectId.GetObject(OpenMode.ForRead);

                var LL = sec.GetSectionLinks();
                var LLPOINT = sec.GetValidSectionPoints();


                tr.Commit();
            }
        }
    }


    public static class ExtensionsSection
    {
        public static IEnumerable<SectionPoint> GetValidSectionPoints(this CivDb.Section section)
        {
            var valid = new HashSet<Point3d>();
            dynamic comSec = section.AcadObject; // AeccSection
            dynamic comLinks = comSec.Links; // AeccSectionLinks
            for (int i = 0; i < comLinks.Count; i++)
            {
                dynamic comLink = comLinks.Item(i); // AeccSectionLink
                if (comLink.Type != 1)
                {
                    valid.Add(new Point3d(comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ));
                    valid.Add(new Point3d(comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ));
                }
            }
            return (from sp in section.SectionPoints
                    where valid.Contains(sp.Location)
                    select sp);
        }

        public static IEnumerable<Section.SectionLink> GetSectionLinks(this CivDb.Section section)
        {
            dynamic comSec = section.AcadObject; // AeccSection
            dynamic comLinks = comSec.Links; // AeccSectionLinks
            for (int i = 0; i < comLinks.Count; i++)
            {
                dynamic comLink = comLinks.Item(i); // AeccSectionLink
                var start = (from sp in section.SectionPoints
                             where sp.Location.IsEqualTo(new Point3d(comLink.StartPointX, comLink.StartPointY, comLink.StartPointZ))
                             select sp).First();
                var end = (from sp in section.SectionPoints
                           where sp.Location.IsEqualTo(new Point3d(comLink.EndPointX, comLink.EndPointY, comLink.EndPointZ))
                           select sp).First();
                if (start != null && end != null)
                {
                    yield return new Section.SectionLink(start, end, i, comLink.Type);
                }
            }
        }

        public static IEnumerable<Section.SectionLink> GetValidSectionLinks(this CivDb.Section section)
        {
            return (from sl in section.GetSectionLinks()
                    where sl.Type != SectionLinkType.NoDraw
                    select sl);
        }
    }

    public static partial class Section
    {
        public class SectionLink
        {
            public SectionPoint StartPoint;
            public SectionPoint EndPoint;
            public readonly int Index;
            public readonly SectionLinkType Type;

            public SectionLink(SectionPoint startPoint, SectionPoint endPoint, int index, SectionLinkType type)
            {
                StartPoint = startPoint;
                EndPoint = endPoint;
                Index = index;
                Type = type;
            }
        }
    }

    public enum SectionLinkType
    {
        None = 0, // aeccSectionLinkNone
        NoDraw = 1, // aeccSectionLinkNoDraw
        All = 2 // aeccSectionLinkAll
    }
}
Jeff_M, also a frequent Swamper
EESignature
Message 16 of 17
hosneyalaa
in reply to: Jeff_M

HI @Jeff_M 

Thank you so much
It works fine
Thanks

Message 17 of 17
LS67
in reply to: Anonymous

Years ago i had to deal with the same problem.

It is 2022 and i found the solution accidentally.

Just in case someone has not realized it yet, autodesk solved our problem.

They exposed the SegmentTo property for the SectionPoint class

No longer any need to use workarounds.

 

Below is the link...

autodesk solution 

 

Copy-paste from the Civil 3D developer's API reference guide...

 

SectionPoint.SegmentTo

 

"Returns the index of the other section point that creates a line segment with this section point. If no segment can be drawn from this point, then -1 is returned. This can happen if there is no underlying surface to determine elevation, such as a hole in a tin/dtm surface, or if the terrain is narrower than the section or the sample line, such that it's not possible to compute all elevations of the section point elevations. For valid segments, only consider segments from this point to other points of index >= 0 "

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


 

Autodesk Design & Make Report