TheSwamp
Code Red => .NET => Topic started by: neyton on August 03, 2009, 06:45:53 PM
-
I am writing a program for civil 3d (pipenetwork), but can not set the value of a partdatafield I've created:
Imports Autodesk.Civil.PipeNetwork.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Microsoft.VisualBasic
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Public Module c3d2010
<CommandMethod("test")> _
Public Sub test()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
Dim ts As Transaction = doc.Database.TransactionManager.StartTransaction()
Dim pipeid As ObjectId = ed.GetEntity( _
New PromptEntityOptions(vbNewLine & "Select Pipe:")) _
.ObjectId
Dim fieldname As String = ed.GetString( _
New PromptStringOptions(vbNewLine & "tag:")) _
.StringResult
Dim value As Double = ed.GetDouble( _
New PromptDoubleOptions(vbNewLine & "value:")) _
.Value
Dim tubo As Pipe = ts.GetObject(pipeid, _
Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)
Dim pf As PartDataField = tubo.PartData.GetDataFieldBy(fieldname)
Dim oldval As Double = pf.Value
pf.Value = value
ts.Commit()
ed.WriteMessage(vbNewLine & "New=" & pf.Value & _
vbNewLine & "Old=" & oldval & _
vbNewLine & "real value=" & _
tubo.PartData.GetDataFieldBy(fieldname).Value)
End Sub
End Module
the test it should be, for example:
Command: test
Select pipe:
tag: coef
Value: 3
-------
New = 3
Old = 10
real value = 3
but "real value" is equal to 10 (old value)
why not work?
-----------------------
the partdatafield was created as (in AeccPartParamCfg.xml):
<AeccDfParameter name="coef" desc="coeficiente" context="coef_" index="0" datatype="Float" usage="Double_general" unit="" visible="True" internal="True"/>
and (in AeccPartParamCfg.xml)
<AeccPartDomainCfg domain="Pipe_Domain">
<AeccReqParam context="SweptShape"/>
<AeccPartTypeCfg type="Pipe" desc="Pipe">
<AeccOptParam context="coef_"/>
...
-
up!
so? nothing?
-
autodesk, are you here???
-
I don't think many from Autodesk party here. I'd love to help but, I've never used C3D. I think sinc is our resident C3D master, maybe he'll pop in.
-
autodesk, are you here???
No, autodesk is not here ... you can find them here (http://discussion.autodesk.com/forums/forum.jspa?forumID=66)
Now on to your particular problem ...
You have defined a variable pf that holds the value of the datafield ... this variable may not automatically update to the part it came from .. you might have to manually write it back to the object ...
I don't have C3d so I can't test it .. but maybe you should do something like:
tubo.PartData.GetDataFieldBy(fieldname).Value = value
Incidently, you might want to tweak your variable names so they aren't the same as properties of objects in your code .. it can get confusing to read value = value ..
-
I think you scared off half the people when you said "VB", and the other half when you started talking about working with Parts via the API... :-D
-
awww... come on now sinc ... VB isn't *all* bad ...
and API programming is pretty neat stuff
-
and API programming is pretty neat stuff
You've obviously never used the Civil 3D API. :lol:
-
lol .. its that obvious is it ...
No, I don't have Civil 3D, and as a result, I don't use the C3D API .. but I have used API's (published and unpublished) from programs that are likely as scary ... once understood, there isn't a problem .. it can actually be quite fun.
-
Yeah, I agree... I must enjoy doing it, because I keep doing it.
The Civil 3D API is quite a mess. They started out creating a COM API, then recently decided to focus on the managed API and ignore the COM API. So now we have some things that are available only via the COM API, and some that are available only via the managed API, and we basically have to use a mish-mash of both. And many things are not available at all via the API, which is a constant source of frustration, as entire tasks are prevented because one part is not available via the API. Plus, the whole API is very low-level, anyway - hardly more than a wrapper around some core functions, with few (if any) events, etc. - and not really the sort of thing I've grown to expect from a true Framework.
But with all its problems, it's still a pretty powerful API. It's much better than what Bentley has for PowerCivil, or what Carlson has for Carlson Civil. :-)
-
So, have you verified whether or not my suggestion will resolve the OP problem?
-
The API is full of gotchas and quirks and incomplete access. I haven't dug into Pipe Networks or Parts yet, so I'm not familiar with might be lurking there. It's something I'll probably be getting into soon, but I haven't tried messing with that area yet.
-
no idea if the MEP API it is related, but for what i have seen and done with this api, to modify a pipe size, you have to use DataQuery and then the Domain and add your size parameters, then query the part GUID, then get the DataRecordCollection, then use a DataRecord and then the PartManager.ModifyPartViaRecord and ROCK AND ROLL
pretty straight forward (aha..... :lmao: )
-
Yes, I try:
...
tubo.PartData.GetDataFieldBy(fieldname).Value = val
...
and not work too
may be.... is it is missing some "openmode.forwrite" in the "transaction manager"?
I like Visual Basic, and with Visual Studio, you can say that is equivalent to C#
----
no "PartManager.ModifyPartViaRecord" in civil 3d api
( translate with google, hehehe )
-
I don't know the answer
-
tanks...
-
Have you downloaded the "Civil3d_DevelopersGuide.PDF" - in there you will find what you are trying to do, it comes with several samples code - in this case using COM or in .NET
-
yes, yes it comes with the installation of civil 3d
has only trivial things such as creating pipenetworks or styles
I am developing a program to drainage networks directly in civil 3d, without export or import anything (such as storm hidraflow anything), but some things can not be made because of the api, which is very bad
download:
http://www.inf.ufpr.br/nldm07/progs/C3D_DREN_ESG.zip
screen shot:
(http://www.inf.ufpr.br/nldm07/c3d/imgs/plandren.PNG)
I think that Autodesk has no interest to do interesting things because they want to win this ... eg the intersection builder EZY corridor became obsolete (http://www.rsteltman.com/cez_downloads.html)
-
I am talking about this section - but you been using this API, i simple downloaded to have a look in case were some similarities with the MEP API, that i need to work on:
Listing and Adding Dynamic Part Properties
Each type of pipe and structure has many unique attributes (such as size, geometry, design, and composition)
that cannot be stored in the standard pipe and structure properties. To give each part appropriate attributes,
pipe and structure objects have sets of dynamic properties. A single property is represented by an
AeccPartDataField object. Data fields are held in collections of type AeccPartDataRecord. You can reach
these collections through the PartDataRecord property of AeccPartSizeFilter, AeccPipe, and AeccStructure
objects. Each data field contains an internal variable name, a text description of the value, a global context
used to identify the field, data type, and the data value itself.
This sample enumerates all the data fields contained in a pipe object “oPipe” and displays information from
each field.
Dim oPartDataField As AeccPartDataField
Debug.Print "All data fields for this pipe:"
Debug.Print "======"
For Each oPartDataField In oPipe.PartDataRecord
Debug.Print "Context name: "; oPartDataField.ContextString
Debug.Print "Description: "; oPartDataField.Description
Debug.Print "Internal name:"; oPartDataField.Name
Debug.Print "Value: "; oPartDataField.Tag
Debug.Print "Type of value:"; oPartDataField.Type
Debug.Print "------"
Next
To create your own dynamic properties, you first create a custom parameter describing the type and name
of the property. You do this by using the pipe network catalog definitions object AeccPipeNetworkCatDef,
which you access through the ambient property AeccPipeSettingsRoot.PipeNetworkCatDef. The
AeccPipeNetworkCatDef object creates new parameters using the
AeccPipeNetworkCatDef.DeclareNewParameter method. DeclareNewParameter takes some strings describing
the parameter data type:
■ a global context (the identification string used to access the parameter type)
■ a global context (the identification string used to access the parameter type)
■ a context description (a description of the parameter)
■ a parameter name (the internally used name of the parameter)
Listing and Adding Dynamic Part Properties | 143
■ a parameter description (the public name of the parameter used by the user interface, such as in the Part
Properties tab of the Pipe and Structure Properties dialog boxes).
Once a parameter has been created, it can be made into a property available for use in parts through the
AeccPipeNetworkCatDef.DeclarePartProperty method.
NOTE The parameter name cannot contain spaces or punctuation characters.
This sample demonstrates declaring a parameter and making a property based on that parameter available
to any pipe objects:
Dim oSettings As AeccPipeSettingsRoot
Dim oPipeNetworkCatDef As AeccPipeNetworkCatDef
Set oSettings = oPipeDocument.Settings
Set oPipeNetworkCatDef = oSettings.PipeNetworkCatDef
oPipeNetworkCatDef.DeclareNewParameter _
"Global Context 01", _
"Context Description", _
aeccDoubleGeneral, _
aeccDouble, _
"Test Parameter", _
"TParam", _
"", _
True, _
False
oPipeNetworkCatDef.DeclarePartProperty
"Global Context 01", aeccDomPipe, 10
You can now choose from among those properties available to the part’s domain and create a data field.
' Make a data field based on the "Global Context 01"
' property and add it to a pipe object "oPipe". Set
' the value of the data field to "6.5".
Dim oPartDataField As AeccPartDataField
Set oPartDataField = oPipe.PartDataRecord.Append
("Global Context 01", 0)
oPartDataField.Tag = 6.5
-
in civil 3d 2010 partdatafield "tag" property (in COM API) is read only....
on 2009 and 2008, it is ok
and de example for "PipeNetworkCatDef" in help is wrong....
-
"de", ops!!!
and the example for "PipeNetworkCatDef" in help is wrong....
-
Hello again, I'm using the "red gate's. Net reflector" (http://www.red-gate.com/products/reflector/) with the dll "aeccdbmgd.dll" and interesting things appeared:
(Namespace Autodesk.Civil.PipeNetwork.DatabaseServices, partdatafield, value, set_value method)
Public Sub set_Value(ByVal newValue As Object)
Dim type As CatDataType
If Me.IsReadOnly Then
Throw New InvalidOperationException("The property is for read only.")
End If
Checker.CheckArgNull(newValue)
If (Me.IsFromList AndAlso Not Me.ValueList.IsValidValue(newValue)) Then
Throw New ArgumentException("The input value is not in valid value list.")
End If
If (Me.IsFromRange AndAlso Not Me.ValueRange.IsValidValue(newValue)) Then
Throw New ArgumentException("The input value is not in valid value range.")
End If
Dim num8 As UInt32 = DirectCast((Me.m_dataField + 8), UInt32*)
If (num8 <> 0) Then
type = DirectCast((num8 + 40), CatDataType*)
Else
type = DirectCast(0, CatDataType)
End If
Select Case type
Case DirectCast(1, CatDataType)
Dim num4 As Double = 0
Try
num4 = CDbl(newValue)
Catch exception3 As InvalidCastException
Throw New ArgumentException("Requires a value of double.")
End Try
Dim units As SettingsUnits = <Module>.AeccNetworkUtils.getBuiltinLengthUnits(Me.m_dataField)
If (units <> DirectCast(0, SettingsUnits)) Then
Dim flag2 As DwgUnitAndConvertFlag
Dim servicesPtr As AcDbHostApplicationServices ModOpt(IsConst)* ModOpt(IsConst) ModOpt(IsConst) = <Module>.acdbHostApplicationServices
<Module>.AeccUnitBase.GetDwgUnitAndConvertFlag(AddressOf flag2, servicesPtr(8), 0)
Dim num3 As Double = 0
<Module>.AeccUnitBase.GetConversionFactor(DirectCast(AddressOf flag2, SettingsUnits ModOpt(IsConst)*), DirectCast((AddressOf flag2 + 4), FootToMeterConversion ModOpt(IsConst)*), units, AddressOf num3)
Dim num9 As Double = DirectCast(AddressOf <Module>.__imp_?gTol@AcGeContext@@2VAcGeTol@@A, Integer*)
If Not <Module>.AeccGeUtils.fuzzyEqual(num3, 0, num9) Then
Dim dataField As AeccDataField* ModOpt(IsConst) ModOpt(IsConst) = Me.m_dataField
dataField(&H10) = DirectCast((num3 * num4), AeccDataField* ModOpt(IsConst) ModOpt(IsConst))
Dim num2 As UInt32 = dataField(8)
If (num2 <> 0) Then
num2(40) = 1
End If
End If
End If
Exit Select
Case DirectCast(2, CatDataType)
Dim num6 As Integer = 0
Try
num6 = CInt(newValue)
Catch exception2 As InvalidCastException
Throw New ArgumentException("Requires a value of int.")
End Try
Dim fieldPtr3 As AeccDataField* ModOpt(IsConst) ModOpt(IsConst) = Me.m_dataField
fieldPtr3(&H18) = DirectCast(num6, AeccDataField* ModOpt(IsConst) ModOpt(IsConst))
Dim num5 As UInt32 = fieldPtr3(8)
If (num5 <> 0) Then
num5(40) = 2
End If
Exit Select
Case DirectCast(3, CatDataType)
Dim flag As Boolean = False
Try
flag = CBool(newValue)
Catch exception1 As InvalidCastException
Throw New ArgumentException("Requires a value of bool.")
End Try
Dim fieldPtr4 As AeccDataField* ModOpt(IsConst) ModOpt(IsConst) = Me.m_dataField
fieldPtr4(&H1C) = DirectCast(flag, AeccDataField* ModOpt(IsConst) ModOpt(IsConst))
Dim num7 As UInt32 = fieldPtr4(8)
If (num7 <> 0) Then
num7(40) = 3
End If
Exit Select
Case DirectCast(4, CatDataType)
Dim str2 As AecRmCString
Dim cliString As String = ""
Try
cliString = CStr(newValue)
Catch exception4 As InvalidCastException
Throw New ArgumentException("The inner type of object^ should be string.")
End Try
<Module>.Autodesk.Civil.ConvertCLIString(AddressOf str2, cliString)
Try
Dim fieldPtr As AeccDataField* ModOpt(IsConst) ModOpt(IsConst) = Me.m_dataField
<Module>.ATL.CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >.=((fieldPtr + &H20), DirectCast(AddressOf str2, CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > > ModOpt(IsConst)* ModOpt(IsImplicitlyDereferenced)))
Dim num As UInt32 = fieldPtr(8)
If (num <> 0) Then
num(40) = 4
End If
Fault
<Module>.___CxxCallUnwindDtor(<Module>.AecRmCString.{dtor}, DirectCast(AddressOf str2, Void*))
End Try
<Module>.ATL.CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >.{dtor}(DirectCast(AddressOf str2, CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >* ModOpt(IsConst) ModOpt(IsConst)))
Exit Select
End Select
End Sub
note that if the value is of type double, it is modified only if the units of measurement do not match ... very strange ...
While well as for other types of data, is not working ...
If anyone here understand what is happening and to resolve the problem, I am willing to pay for the solution
-
partially resolved:
http://discussion.autodesk.com/forums/thread.jspa?messageID=6253030&
-
and not really the sort of thing I've grown to expect from a true Framework.
Quoted for 110% total agreement.
It wouldn't be so quirky and like developing in the middle of an uncharted minefield if things were also implemented following standards or at the very least some resemblance of consistency. Like, oh, collections that implement IEnumerable but instead of throwing a count as 0 instead just throw *exceptions* all over the place. :roll: