Access FeatureLine using COM

Access FeatureLine using COM

Yonas89
Collaborator Collaborator
6,354 Views
20 Replies
Message 1 of 21

Access FeatureLine using COM

Yonas89
Collaborator
Collaborator

Hello,

 

I'm trying to access feature line with python, but my main obstacle is the lack of knowledge of COM. I need to check if my selected object is a feature line. I don't know what property i need to use. Is there anyone who can help to fix this snippet of my code?

 

app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
	CivilApp = app.GetInterfaceObject("AeccXUiLand.AeccApplication.12.0")
	AecDoc = CivilApp.ActiveDocument
	AecDB = AecDoc.Database
	sset = AecDoc.PickfirstSelectionSet
	n = sset.Count	
	for i in range(n):
		if  sset.Item(i).Name == "AeccLandFeatureLine"

 

0 Likes
6,355 Views
20 Replies
Replies (20)
Message 2 of 21

Civil3DReminders_com
Mentor
Mentor

I went to the Living Museum in Seattle a few weeks ago. At the museum they have working computers from the early years (1970's to present day). My kids couldn't understand why anyone would want to use a computer that was command line based. I told her there are still people out there who prefer to use inferior technology today when there are much better user experiences out there. I still don't have a good answer for her. Do you have an answer that would make sense to her?

 

Well anyways if you download VBA for your version of AutoCAD you could open up an IDE that is very old and archaic that would provide you more information while you program. You could program the COM part in there and copy it into your Python. 

 

For your question I think it is: 

 

If TypeOf sset.Item(i) Is AeccFeatureLine Then

 

From this page: https://forums.autodesk.com/t5/visual-basic-customization/how-do-i-select-the-current-object-in-vba-...

Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni
0 Likes
Message 3 of 21

You might also want to move to .NET. I couldn't find any good examples (I didn't look long), but this might get you started: 

http://through-the-interface.typepad.com/through_the_interface/2009/03/using-ironpython-with-autocad...

Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni
0 Likes
Message 4 of 21

Yonas89
Collaborator
Collaborator

Tell your kids that they shouldn't make silly assumptions and insult people they've never met before as their father does. Common??? what was that? If you do not wish to help or do not have an answer then do not reply. 

Ok now  back to my topic. Is it possible to do such a transfer using .NET? 

 

example.gif

0 Likes
Message 5 of 21

Civil3DReminders_com
Mentor
Mentor

I was just looking for a reason. One can take things as insults right away or try to have a discussion before taking something as an insult. I'd prefer to live a world where people look for understanding instead of only looking at others having nefarious reasons for their actions. In your case it sounds like you choose Python because it's Dynamo related (not included in the original post). My experience with Python has been command line based, which prompted the question. 

 

Despite you telling me to go away, I'll continue on with the other topic. Yes, it should be possible. I'd probably do a LispFunction in AutoCAD .NET and then have Dynamo call the LispFunction with the parameters you want to change in Civil 3D. COM can be a bit painful to work with. The LispFunction can return a result buffer that can then be parsed for the return information. An added benefit is you can pass back and forth handles or ObjectIds instead of trying to go through all of the objects in the AutoCAD drawing.

 

Here is the help file for LispFunction which has some sample code:

https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-NET/files/GUI...

Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni
0 Likes
Message 6 of 21

Yonas89
Collaborator
Collaborator

Ok now we're talking. If I call the LISP function from Dynamo, what difference does it make from calling it  directly in command line? In this particular example my approach is to get FeatureLline (f.i. ETW), transfer it to Dynamo, then do some parametric modeling there ( f.i. sidewalks with dropkerbs, etc)  then write those objects back to Civil 3D. 

I'm just trying to find some ways to implement Dynamo in daily process of Civil Engineer. 

0 Likes
Message 7 of 21

Civil3DReminders_com
Mentor
Mentor

It looks like you want to create, modify, and change feature lines in Civil 3D. The COM API wasn't finished and feature line modifications and creations aren't fully supported in COM. By using the .NET API you'll get a slightly better experience (although the .NET API also wasn't finished).

 

Civil 3D, in my opinion, has no logic that would make the tasks you want to do easier. So why include it other than at the beginning and the end of the process? Grab the data, in the beginning, using a LispFunction to grab the data you need, do the work in Dynamo, and then send the final changes to Civil 3D at the end were Civil 3D can delete the old and then create new linework. 

 

Another benefit is having more code samples available.

 

If you want to use COM, this forum would probably be more appropriate: https://forums.autodesk.com/t5/visual-basic-customization/bd-p/33 

There will be more people looking at that forum, then this one, who can answer questions quicker.

 

 

Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni
0 Likes
Message 8 of 21

Yonas89
Collaborator
Collaborator

Ok thanks for the link! I will post there. However I feel that I am misunderstood. I do not want to change Feature Line at all. I just want to use it as a reference for additional modeling in dynamo. For instance extract feature line from corridor-> send it to dynamo-> use feature line's geometry as a reference to model sidewalks with parametric dropkerb locations-> write new critical geometry  or even whole solids of sidewalk pavement back to Civil 3D.  I can already do this with 3DPolyline extracted from corridor but the problem is that 3dpolyline could not be linked dynamically to corridor. 

 

0 Likes
Message 9 of 21

Civil3DReminders_com
Mentor
Mentor
Why extract the feature line in the first place? Get the AeccFeatureLine data from the corridor directly?

http://blog.civil3dreminders.com/2009/05/extract-feature-line-from-corridor.html
Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni
0 Likes
Message 10 of 21

Yonas89
Collaborator
Collaborator

just wanted to share, what I had in my mind. Made some video about how getting Civil 3D objects (even using COM api) directly in dynamo can enrich your model and make it fully parametric.  In this video  is the most simple example of creating parametric drop kerbs, driveways and sidewalks ( the first that came in my mind):

https://www.youtube.com/channel/UCiSZ_6GXh9OMOFAwRUf7dZg 

0 Likes
Message 11 of 21

atultegar
Participant
Participant

Hi,

I used below code in Dynamo - python node to get featureline points of selected corridor from running instance of Civil3D:

import clr
import System
import math
from System.Runtime.InteropServices import Marshal

clr.AddReference('ProtoGeometry')
path = 'C:\\Program Files\\Autodesk\\AutoCAD 2018\\'
path2 = 'C:\\Program Files\\Autodesk\\AutoCAD 2018\\C3D\\'
path3 = 'C:\\Program Files\\Autodesk\\AutoCAD 2018\\ACA\\'
clr.AddReferenceToFileAndPath(path3 + 'Autodesk.AEC.Interop.Base.dll')
clr.AddReferenceToFileAndPath(path3 + 'Autodesk.AEC.Interop.UIBase.dll')
clr.AddReferenceToFileAndPath(path + 'Autodesk.AutoCAD.Interop.dll')
clr.AddReferenceToFileAndPath(path + 'Autodesk.AutoCAD.Interop.Common.dll')
clr.AddReferenceToFileAndPath(path2 + 'Autodesk.AECC.Interop.Land.dll')
clr.AddReferenceToFileAndPath(path2 + 'Autodesk.AECC.Interop.UiLand.dll')
clr.AddReferenceToFileAndPath(path2 + 'Autodesk.AECC.Interop.Roadway.dll')
clr.AddReferenceToFileAndPath(path2 + 'Autodesk.AECC.Interop.UiRoadway.dll')


import Autodesk.AutoCAD.Interop
import Autodesk.AutoCAD.Interop.Common
import Autodesk.AECC.Interop.UiLand
import Autodesk.AECC.Interop.UiRoadway
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
staInc = IN[0]

m_sAcadProdID = "AutoCAD.Application.22"
m_sAeccAppProgId = "AeccXUiLand.AeccApplication.12.0"
m_sRAppName = "AeccXUiRoadway.AeccRoadwayApplication.12.0"

m_oAcadApp = Marshal.GetActiveObject(m_sAcadProdID)

m_oAeccApp = m_oAcadApp.GetInterfaceObject(m_sAeccAppProgId)
m_oRoadwayApp = m_oAcadApp.GetInterfaceObject(m_sRAppName)
m_oAeccDoc = m_oAeccApp.ActiveDocument
m_oRoadwayDoc = m_oRoadwayApp.ActiveDocument
acadDoc = m_oAcadApp.ActiveDocument
docName = m_oAeccDoc.Name
oAeccDb = m_oAeccDoc.Database

corridorList = []
featLineCodeList = []
PointList = []

for corridor in m_oRoadwayDoc.Corridors:
	corridorList.append(corridor.Name)

corridorSelect = m_oRoadwayDoc.Corridors[5]

baseline = corridorSelect.Baselines[0]
baselineFeature = baseline.MainBaselineFeatureLines
FeatureLinesCol = baselineFeature.FeatureLinesCol
FeatureLines = FeatureLinesCol[0]

for featureLine in FeatureLines:
	fCode = featureLine.CodeName
	featLineCodeList.append(fCode)
	for oFeatureLinePoint in featureLine.FeatureLinePoints:
		X = round(oFeatureLinePoint.XYZ[0],3)
		Y = round(oFeatureLinePoint.XYZ[1],3)
		Z = round(oFeatureLinePoint.XYZ[2],3)
		station = round(oFeatureLinePoint.Station,3)
		pointXYZ = [station,X,Y,Z]
		PointList.append(pointXYZ)
#Assign your output to the OUT variable.
OUT = corridorList, corridorSelect.Name, featLineCodeList, PointList

Hope it will help you 🙂

 

Thanks

Atul

Message 12 of 21

Yonas89
Collaborator
Collaborator

Hey @atultegar,

 

thanks a lot for your reply. If you  have seen my earlier message, I shared a link  of an example where I was able to achieve  and implement it.

0 Likes
Message 13 of 21

lu_an_jie
Advocate
Advocate

Would you be able to share the com part of your solution?

Regards

Andreas Luka (Lu An Jie)

http://www.luka-consult.de

Creator of the LX-Stair App for Civil 3D
0 Likes
Message 14 of 21

Yonas89
Collaborator
Collaborator

Sure, I will share it  once I'll be back at home, cause I have it on my personal laptop

0 Likes
Message 15 of 21

Yonas89
Collaborator
Collaborator

@lu_an_jie

sorry for my delay. but there it is:  This works with Civil 3D 2018. For Civil 3D 2019 change the version number to 13.0 (I guess it's 13.0, not have tried with Civil 3D 2019) 

import clr
clr.AddReference('ProtoGeometry')
import Autodesk
from Autodesk.DesignScript.Geometry import *
import System
from System import *

curvs = []
#Import Corridor Flines
if IN[0] == True:
	DPoint = Autodesk.DesignScript.Geometry.Point
	DPolyCurve = Autodesk.DesignScript.Geometry.PolyCurve
	app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
	CivilApp = app.GetInterfaceObject("AeccXUiLand.AeccApplication.12.0")
	AecDoc = CivilApp.ActiveDocument
	AecDB = AecDoc.Database
	def ptD(parr,i):
		return DPoint.ByCoordinates(parr[i],parr[i+1],parr[i+2])
	def PolyCurveD(pts):
		return DPolyCurve.ByPoints(pts,False)
	sset = AecDoc.PickfirstSelectionSet
	n = sset.Count	
	for i in range(n):
		if  sset.Item(i).EntityName == "AeccDbAutoCorridorFeatureLine":
			CoordsArr = sset.Item(i).GetPoints()
			PointsArr =[]
			int = 0
			while int <=len(CoordsArr)-3:
				pta = ptD(CoordsArr,int)
				PointsArr.append(pta)
				int+=3
			PolCurv = PolyCurveD(PointsArr)
			curvs.append(PolCurv)
#Import Flines
if IN[1] == True:
	DPoint = Autodesk.DesignScript.Geometry.Point
	DPolyCurve = Autodesk.DesignScript.Geometry.PolyCurve
	app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
	CivilApp = app.GetInterfaceObject("AeccXUiLand.AeccApplication.12.0")
	AecDoc = CivilApp.ActiveDocument
	AecDB = AecDoc.Database
	def ptD(parr,i):
		return DPoint.ByCoordinates(parr[i],parr[i+1],parr[i+2])
	def PolyCurveD(pts):
		return DPolyCurve.ByPoints(pts,False)
	sset = AecDoc.PickfirstSelectionSet
	n = sset.Count	
	for i in range(n):
		if  sset.Item(i).EntityName == "AeccDbFeatureLine":
			CoordsArr = sset.Item(i).GetPoints()
			PointsArr =[]
			int = 0
			while int <=len(CoordsArr)-3:
				pta = ptD(CoordsArr,int)
				PointsArr.append(pta)
				int+=3
			PolCurv = PolyCurveD(PointsArr)
			curvs.append(PolCurv)
#Assign your output to the OUT variable.
OUT = curvs
Message 16 of 21

Anonymous
Not applicable

Hi,

sorry to come back to this topic, but for me the python script isnt working.

Somehow it cant load the application in line 14. Any idea?

 

Thanks in advance!

 

Error.PNG



0 Likes
Message 17 of 21

hippe013
Advisor
Advisor

What version of Civil 3D are you running?

0 Likes
Message 18 of 21

Anonymous
Not applicable

Civil 3D 2018 (12.0)

0 Likes
Message 19 of 21

hippe013
Advisor
Advisor

Is your code an exact copy of the code as shown in messages 11 or 15? Could you post your code. Do you have Civil 3D Running when you execute the code?

0 Likes
Message 20 of 21

Anonymous
Not applicable
import clr
clr.AddReference('ProtoGeometry')
import Autodesk
from Autodesk.DesignScript.Geometry import *
import System
from System import *

curvs = []
#Import Corridor Flines
if IN[0] == True:
	DPoint = Autodesk.DesignScript.Geometry.Point
	DPolyCurve = Autodesk.DesignScript.Geometry.PolyCurve
	app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
	CivilApp = app.GetInterfaceObject("AeccXUiLand.AeccApplication.12.0")
	AecDoc = CivilApp.ActiveDocument
	AecDB = AecDoc.Database
	def ptD(parr,i):
		return DPoint.ByCoordinates(parr[i],parr[i+1],parr[i+2])
	def PolyCurveD(pts):
		return DPolyCurve.ByPoints(pts,False)
	sset = AecDoc.PickfirstSelectionSet
	n = sset.Count	
	for i in range(n):
		if  sset.Item(i).EntityName == "AeccDbAutoCorridorFeatureLine":
			CoordsArr = sset.Item(i).GetPoints()
			PointsArr =[]
			int = 0
			while int <=len(CoordsArr)-3:
				pta = ptD(CoordsArr,int)
				PointsArr.append(pta)
				int+=3
			PolCurv = PolyCurveD(PointsArr)
			curvs.append(PolCurv)
#Import Flines
if IN[1] == True:
	DPoint = Autodesk.DesignScript.Geometry.Point
	DPolyCurve = Autodesk.DesignScript.Geometry.PolyCurve
	app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
	CivilApp = app.GetInterfaceObject("AeccXUiLand.AeccApplication.12.0")
	AecDoc = CivilApp.ActiveDocument
	AecDB = AecDoc.Database
	def ptD(parr,i):
		return DPoint.ByCoordinates(parr[i],parr[i+1],parr[i+2])
	def PolyCurveD(pts):
		return DPolyCurve.ByPoints(pts,False)
	sset = AecDoc.PickfirstSelectionSet
	n = sset.Count	
	for i in range(n):
		if  sset.Item(i).EntityName == "AeccDbFeatureLine":
			CoordsArr = sset.Item(i).GetPoints()
			PointsArr =[]
			int = 0
			while int <=len(CoordsArr)-3:
				pta = ptD(CoordsArr,int)
				PointsArr.append(pta)
				int+=3
			PolCurv = PolyCurveD(PointsArr)
			curvs.append(PolCurv)
#Assign your output to the OUT variable.
OUT = curvs

Thats the exact code from above Im using. And Civil 3D 2018 is running.

0 Likes