Import shapefile to polylines in C# .NET framework

Import shapefile to polylines in C# .NET framework

m.chavet7MJRB
Enthusiast Enthusiast
2,554 Views
32 Replies
Message 1 of 33

Import shapefile to polylines in C# .NET framework

m.chavet7MJRB
Enthusiast
Enthusiast

Hello,  I don't find how to import a shapefile layer, and then convert it to a 2D polyline through a #C language  code. I know that in Autacad/C3D it's "mapimport". 

0 Likes
Accepted solutions (2)
2,555 Views
32 Replies
Replies (32)
Message 2 of 33

fieldguy
Advisor
Advisor

I think OSGEO FDO is what you are looking for.  The APIs (OSGeo.FDO.dll, OSGeo.FDO.Geometry.dll, OSGeo.FDO.Common.dll) are installed with C3D to  C:\Program Files\Autodesk\AutoCAD 2023\Map\bin\FDO (on my pc).  

I believe you can download the APIs separately but have never tried.

Check this link: https://svn.osgeo.org/fdo/tags/3.3_S010/www/docs/FDO_API_managed/main.htm 

0 Likes
Message 3 of 33

norman.yuan
Mentor
Mentor

If you use AutoCAD Map/C3D, it comes with Map .NET API for importing/exporting from/to shape file, exactly the same way as Map's command "MAPIMPORT/MAPEXPORT". The API classes are in Autdesk.Gis.Map.ImportExport namespace of ManagedMapApi.dll, which you can find in "C:\Program Files\Autodesk\[AutoCAD version folder]\Map". However, if you use plain AutoCAD, or other flavors of AutoCAD, you need find third party APIs.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 4 of 33

hosneyalaa
Advisor
Advisor

@m.chavet7MJRB 

Can you attached example drawing 

0 Likes
Message 5 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Thank you for you answers!

It's just a bunch of Polylines. I'm trying to automate the process from an importation of one shapefile of lines to polylines, then to alignements and then profiles.

But I'm a beginner with #C on .NET framework. Do you know how can I find the functions to do that? (with managedmapapi or OSGEO). For the first one, I don't find sample codes and in general, I don't know how to find these functions.

 
0 Likes
Message 6 of 33

hosneyalaa
Advisor
Advisor

 

@m.chavet7MJRB 

see this

Read coordinates of line features with Map 3D API 

 

 

 

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.Gis.Map.Platform.Interop;
using Autodesk.Gis.Map.Platform;
using OSGeo.MapGuide;
 
// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(GetFeatureType.MyCommands))]
 
namespace GetFeatureType
{
 
public class MyCommands
{
 
 
// Modal Command with localized name
[CommandMethod("getPolylineCoordinates")]
public void MyCommand() // This method can have any name
{
    Editor ed = Autodesk.AutoCAD.ApplicationServices.Application
        .DocumentManager.MdiActiveDocument.Editor;
 
    Transaction trans = Autodesk.AutoCAD.ApplicationServices.Application
        .DocumentManager.MdiActiveDocument.Database.TransactionManager
        .StartTransaction();
 
    using (trans)
    {
        // Get the Map Object
        AcMapMap currentMap = AcMapMap.GetCurrentMap();
 
        // Prompt user to Select Feature in Map
        PromptSelectionOptions psop = new PromptSelectionOptions();
        psop.MessageForAdding = "Select the FDO Feature in Map 3D to read Data : ";
        psop.SingleOnly = true;
        PromptSelectionResult psResult = ed.GetSelection(psop);
 
        if (psResult.Status == PromptStatus.OK)
        {
            SelectionSet selSet = psResult.Value;
 
            // Get Map Selectionset from AutoCAD SelectionSet
            MgSelectionBase mapSelBase = AcMapFeatureEntityService
                .GetSelection(selSet);
            AcMapLayer mapLayer = AcMapFeatureEntityService
                .GetLayer(psResult.Value[0].ObjectId);
 
            //Get the ID of the selected Parcel
            MgFeatureReader ftrRdr = mapSelBase.GetSelectedFeatures(
                mapLayer, mapLayer.FeatureClassName, false);
 
            while (ftrRdr.ReadNext())
            {
                MgClassDefinition cd = ftrRdr.GetClassDefinition();
 
                //the geomety property name maybe different for your 
                //data source 
                MgByteReader byteRdr = ftrRdr.GetGeometry("Geometry");
                MgAgfReaderWriter wtr = new MgAgfReaderWriter();
 
                MgGeometry geom = wtr.Read(byteRdr);
 
                if (geom is OSGeo.MapGuide.MgCurveString)
                {
                    var cs = geom as MgCurveString;
 
                    ed.WriteMessage("\n geo is MgCurveString.");
 
                    for (int i = 0, segmentCount = cs.Count; i < segmentCount; i++)
                    {
                        var seg = cs.GetSegment(i);
                        if (seg is MgArcSegment)
                        {
                            ed.WriteMessage("\nthis is an Arc Segment.");
                            var arcSeg = seg as MgArcSegment;
 
                            string msg = string.Format(
                                "\nstart point: x= {0}, y={1}",
                                arcSeg.StartCoordinate.X,
                                arcSeg.StartCoordinate.Y);
                            ed.WriteMessage(msg);
 
                            msg = string.Format(
                                "\ncontrol point  x= {0}, y={1}",
                                arcSeg.ControlCoordinate.X,
                                arcSeg.ControlCoordinate.Y);
                            ed.WriteMessage(msg);
 
                            msg = string.Format(
                                "\nend point: x= {0}, y={1}",
                                arcSeg.EndCoordinate.X,
                                arcSeg.EndCoordinate.Y);
                            ed.WriteMessage(msg);
                        }
                        if (seg is MgLinearSegment)
                        {
                            ed.WriteMessage("\nthis is a linear Segment.");
 
                            var linearSeg = seg as MgLinearSegment;
                            var interator = linearSeg.GetCoordinates();
                            while (interator.MoveNext())
                            {
                                var x = interator.GetCurrent().X;
                                var y = interator.GetCurrent().Y;
 
                                ed.WriteMessage(string.Format(
                                    "\n x = {0}, y={1} ", x, y));
                            }
                        }
 
                    }
                }
                if (geom is OSGeo.MapGuide.MgLineString)
                {
                    var ls = geom as MgLineString;
                    var interator = ls.GetCoordinates();
                    while (interator.MoveNext())
                    {
                        var x = interator.GetCurrent().X;
                        var y = interator.GetCurrent().Y;
 
                        ed.WriteMessage(string.Format(
                            "\n x = {0}, y={1} ", x, y));
                    }
 
                }
 
            }
        }
        trans.Commit();
    }
 
}
 
 
 
}
 
}

 

0 Likes
Message 7 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Thank you! Could you tell me which references do you import please? I have some issues when I'm trying to import them and I have some errors about non-recognized functions (Platform, MapGuide, AcMap-elements,Mg-elements)

 

image_2023-09-09_144635000.png

 
0 Likes
Message 8 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Thank you! Could you tell me which references do you import please? I have some issues when I'm trying to import them and I have some errors about non-recognized functions (Platform, MapGuide, AcMap-elements,Mg-elements)

 

image_2023-09-09_144635000.png

0 Likes
Message 9 of 33

hosneyalaa
Advisor
Advisor

@m.chavet7MJRB 

Why you not reading 

@fieldguy  and @norman.yuan  @@the reply 

Very well

 

0 Likes
Message 10 of 33

norman.yuan
Mentor
Mentor

There is really no need to go the more complicated route of using Map layer FDO API in this simple case of importing/exporting shape files, if you are using AutoCAD MAP/C3D (you DID not mention it in your original post). Use Map's .NET API for importing/exporting, it is easy/simple. If you downloaded AutoCAD Map ObjectARX SDK (do not confuse it with AutoCAD ObjectARX SDK), it come sample code of MAP import/export API. If you search this AutoCAD Map Developer Discussion Forum, you would also find some sample code.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 11 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Thank you for your reply.  I finally used this code (https://forums.autodesk.com/t5/autocad-map-3d-developer/shp-import/m-p/8051198) and so the ManagedMapApi.dll reference. 

 

What I'm trying to do is import shapefiles into civil 3D, but also then use the attributes of the layer geometries in order to then represent them in the band sets of the profile views. I have already succeded to convert all the polylines into alignments with a C# code thanks to that: http://alcbimlab.com/C3DCustom/C3D-1.html .

 

To give concrete examples: I have a shapefile of pipes with attributes of pressure, roughness, flow,... and I would like to represent, in civil 3D, these values in z in different bandsets along my chain. I already saw that it was possible with the AeccXUILand assembly.

 

With the "mapimport" function and the above-mentioned code, this only imports the shapefile as polylines, but not with all features. However I discovered that with the OsGeo FDO Provider objects (the _mapconnect function), my entire attribute table was imported into a "map feature" object. So, I'm trying to figure out how to get these features in my code and put them in profile views.

0 Likes
Message 12 of 33

norman.yuan
Mentor
Mentor

@m.chavet7MJRB wrote:

...

 

With the "mapimport" function and the above-mentioned code, this only imports the shapefile as polylines, but not with all features. ...


Are you saying that besides the geometries in the shape file being imported as Polyline, all data attributes are not imported, or only some of them (but not all of them) being imported? That sounds not right!

 

Not seeing your code, or the drawing after your importing code execution, I cannot say more. You might want to clarify: were all attributes not imported? or only some of them (then how did you do it in code)? 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 13 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

All the features are not imported with the "map import", and I guess it's what this code does.

 

With this code, I don't find the function ImportShape I created when I import it in C3D with netload:

 

 

 

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.Civil;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.Settings;
using System.Diagnostics;
using System.IO;
using Autodesk.Gis.Map.ImportExport;
using Autodesk.Gis.Map;

namespace import_shapefile
{
    public class Class1
    {

        #region IExtensionApplication Members

        public void Initialize()
        {
            //    throw new System.Exception("The method or operation is not implemented")
        }

        public void Terminate()
        {
            //    throw new System.Exception("The method or operation is not implemented")
        }

        #endregion


        [CommandMethod("ImportShape")]
        private void ImportShape(FileInfo file)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            MapApplication mapApp = HostMapApplicationServices.Application;
            using (Importer importer = mapApp.Importer)
            {
                importer.Init("SHP", file.FullName);

                string fileName = Path.GetFileNameWithoutExtension(file.FullName).Replace(" ", "");

                foreach (InputLayer inputLayer in importer)
                {
                    inputLayer.SetLayerName(LayerNameType.LayerNameDirect, fileName);
                    inputLayer.SetDataMapping(ImportDataMapping.NewObjectDataOnly, fileName);

                    inputLayer.Dispose();
                }

                importer.ImportPolygonsAsClosedPolylines = true;

                ImportResults result = importer.Import(true);

                sw.Stop();
                //Quest_Common.ed.WriteMessage(string.Format("\n{0} object(s) imported in {1} sec(s)", result.EntitiesImported.ToString(), sw.Elapsed.Seconds));

                importer.Dispose();
            }

            file.Delete();
        }
    }
}

 

 

  

 

Moreover, I get a problem when I launch this code to create profile with no surface, because of the style and the label style are not recognized, it says "Name no exists", I tried "Basic" and "Standard":

 

 

 

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.Civil;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.Settings;
using Autodesk.AutoCAD.Geometry;


namespace CreateProfileView
{

    public class MyCommands
    {

        #region IExtensionApplication Members

        public void Initialize()
        {
            //    throw new System.Exception("The method or operation is not implemented")
        }

        public void Terminate()
        {
            //    throw new System.Exception("The method or operation is not implemented")
        }

        #endregion

        [CommandMethod("CreateProfileNoSurface")]
        public void CreateProfileNoSurface()
        {
            CivilDocument doc = CivilApplication.ActiveDocument;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
            {
                // Ask the user to select an alignment 
                PromptEntityOptions opt = new PromptEntityOptions("\nSelect an Alignment");
                opt.SetRejectMessage("\nObject must be an alignment.\n");
                opt.AddAllowedClass(typeof(Alignment), false);
                ObjectId alignID = ed.GetEntity(opt).ObjectId;

                Alignment oAlignment = ts.GetObject(alignID, OpenMode.ForRead) as Alignment;

                // use the same layer as the alignment
                ObjectId layerId = oAlignment.LayerId;
                // get the standard style and label set 
                // these calls will fail on templates without a style named "Standard"

                ObjectId styleId = doc.Styles.ProfileStyles["Basic"];
                ObjectId labelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles["Basic"];

                ObjectId oProfileId = Profile.CreateByLayout("My Profile", alignID, layerId, styleId, labelSetId);

                // Now add the entities that define the profile.

                Profile oProfile = ts.GetObject(oProfileId, OpenMode.ForRead) as Profile;

                Point3d startPoint = new Point3d(oAlignment.StartingStation, -40, 0);
                Point3d endPoint = new Point3d(758.2, -70, 0);
                ProfileTangent oTangent1 = oProfile.Entities.AddFixedTangent(startPoint, endPoint);

                startPoint = new Point3d(1508.2, -60.0, 0);
                endPoint = new Point3d(oAlignment.EndingStation, -4.0, 0);
                ProfileTangent oTangent2 = oProfile.Entities.AddFixedTangent(startPoint, endPoint);

                oProfile.Entities.AddFreeSymmetricParabolaByLength(oTangent1.EntityId, oTangent2.EntityId, VerticalCurveType.Sag, 900.1, true);

                ts.Commit();
            }

        }

       
    }
}

 

 

0 Likes
Message 14 of 33

fieldguy
Advisor
Advisor

At first glance I see that the first method is defined as "private".  The second is defined as "public".

IIRC commandmethods need to be defined as "public".

 

[CommandMethod("ImportShape")]
private void ImportShape(FileInfo file)

[CommandMethod("CreateProfileNoSurface")]
public void CreateProfileNoSurface()

0 Likes
Message 15 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Ok, thank you for your reply

 

Now I get this error when I launch on C3D (to import the shapefile):

 

 

 

Application does not support just-in-time (JIT)
debugging. See the end of this message for details.

************** Exception Text **************
System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()

 

 

0 Likes
Message 16 of 33

hosneyalaa
Advisor
Advisor

Try @m.chavet7MJRB 

ObjectId styleId = doc.Styles.ProfileStyles[0];
                ObjectId labelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles[0];

 

 

0 Likes
Message 17 of 33

Alexander.Rivilis
Mentor
Mentor

@m.chavet7MJRB 

Instead of:

 

[CommandMethod("ImportShape")]
private void ImportShape(FileInfo file)

 

you have to use:

 

[CommandMethod("ImportShape")]
public void ImportShape()

 

Command method can not have any argument and have to be public

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 18 of 33

norman.yuan
Mentor
Mentor

<QUOTE>
All the features are not imported with the "map import", and I guess it's what this code does.
</QUOTE>

 

Again, it is utterly WRONG to say that. It is your code that is wrong, not the API:

 

foreach (InputLayer inputLayer in importer)
{
    inputLayer.SetLayerName(LayerNameType.LayerNameDirect, fileName);
    inputLayer.SetDataMapping(ImportDataMapping.NewObjectDataOnly, fileName);

 

    inputLayer.Dispose();
}

 

Why do you dispose the InputLayer? This simply prevented all data attributes being imported.

 

Of course, the error from the other command has nothing to do with the shape importing, for now, because you have not gotten the data attributes into the drawing (once you do, you'll need to learn how to data data from ObjectData attached to the imported polylines, this would be a whole new different topic).

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 19 of 33

m.chavet7MJRB
Enthusiast
Enthusiast

Thank you for your response, I will check that.

 

I still get this error in both codes : "The application does not support Windows form debugging in just in time (JIT)".  I found this to solve the problem: https://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-A2CD7540-69C5-4085-BCE8-2A8ACE16BFDD , but I don't get how to implement it in the code.

 

 

 

 

0 Likes
Message 20 of 33

norman.yuan
Mentor
Mentor

The link you quoted probably has nothing to do with the error you get. Have you read the reply from @Alexander.Rivilis ? Command method doe not allow an argument or arguments (the "ImportShape" command).

 

 

Norman Yuan

Drive CAD With Code

EESignature