Assigning Layer +Line/Curve Style with .net API
Hello all,
I am looking for a .net API routine that can set the layer and line or curve style after selecting multiple line/curve dimensions. I searched for this via LISP, but from what I gathered LISP cannot do this (or at least it would be rather hard to do so) and I believe .net can accomplish this.
Background: I do a lot of Plat based drafting which involves dimensioning lots, plat boundaries, easements, etc, and as I work through the drawing and dimensioning them I have to make sure I assign the proper layer, and line/curve styles to go with everything. This typically involves creating the dimensions, updating the line/curve style for each type of dimension so they look good for the current drawing setup (the baseline styles are embedded in the template), and then matching properties. Sometimes match properties doesn't work though for reasons unknown to me and I have to manually update the settings. I would like to be able to run a command to do so instead of manually having to scroll through all my layers/styles and it'd be nice for when I notice I miss one I could grab it, run the command, and move on. There are mice with extra side buttons you can get (typically for gaming) that I'm thinking it would be really smooth for with this as I could assign commands to those buttons.
I have no experience with API coding (and only light LISP knowledge) so unfortunately I kind of need to be spoon fed here. If I get one routine for the line style I can probably/maybe figure out how to convert it to edit the curve style if it's rather simple (IE: replace the code line that specifies line to curve?) and duplicate it for every type of layer and line/curve style.
A short and sweet version
-Sets the layer to layer X
-Sets Line or Curve label style to Y
Thanks for any and all help!
Edit: After thinking about it I somewhat rescind/alter my previous request. Rather having a command that runs the single segment label command (_AeccAddSegmentLabel) while setting the layer and using a particular line or curve style would be much more ideal.
Thanks again.
Re: Assigning Layer +Line/Curve Style with .net API
It appears you are using a vertical (probably Civil 3D) to AutoCAD. In the Drawing Settings, which can be found by a right-click on the drawing name on the Settings tab of the ToolSpace palette, there is a tab labeled Object Layers. This may do what you are wanting to do.
Re: Assigning Layer +Line/Curve Style with .net API
Quote:
Originally Posted by
Opie
... This may do what you are wanting to do.
Yes; it is my understanding, and I could be mistaken, that the OP wants a LISP routine to [implicitly] store the current settings (Object Layer, and Default Style), set the new settings, allow the Objects to be placed accordingly, and then restore same - just as we would with say Dimensions, or MLeaders, etc.
Do you happen to already have something in your toolbox for such? If not, I can help out after some project submittals.
Cheers
Re: Assigning Layer +Line/Curve Style with .net API
Quote:
Originally Posted by
Opie
It appears you are using a vertical (probably Civil 3D) to AutoCAD. In the Drawing Settings, which can be found by a right-click on the drawing name on the Settings tab of the ToolSpace palette, there is a tab labeled Object Layers. This may do what you are wanting to do.
Hi Opie, this does indeed look like an area you can change the default values. The question I have is how do I translate that into either a LISP or dot net code to do it automatically? I thought LISP couldn't handle this type of stuff, but maybe I'm wrong?
We have four different label styles
Distance Only
Bearing + Distance
Bearing + Distance (stacked)
Curve Labels
We then assign them to their respective layer. These bearings/distances are used for lot lines, plat boundaries, and easements so the end goal is to be able to run a command, say ED (Easement- Distance only), and start clicking away at all the easement lines and it will assign the label to the easement layer, and use the easement distance style. Then I may need to do the boundary so I do something like BBDS (Boundary Bearing Distance Stacked) and it sets it to the Boundary layer, and uses the Boundary Bearing/Distance stacked label style. I just hate having to go in and manually update the current label style and layer when I'm dimensioning different things, and on top of that it's easy to miss layers so removing that error is preferred. I prefer automation for this type of stuff when I can.
Quote:
Originally Posted by
BlackBox
Yes; it is my understanding, and I could be mistaken, that the OP wants a LISP routine to [implicitly] store the current settings (Object Layer, and Default Style), set the new settings, allow the Objects to be placed accordingly, and then restore same - just as we would with say Dimensions, or MLeaders, etc.
Do you happen to already have something in your toolbox for such? If not, I can help out after some project submittals.
Cheers
Hi Blackbox,
I believe you're wondering if I have something like this?
Code:
(DEFUN C:EAD()
(setq cancel *error*)
(setq *error* trapdim)
(setq oldlayer (getvar "clayer"))
(initget "E P")
(setq GET1 (getkword "[Existing/Proposed] <Proposed>"))
(COND
((= GET1 "E") (COMMAND "-LAYER" "MAKE" "SE-EASE-TXT" "COLOR" "7" "" ""))
(T(COMMAND "-LAYER" "MAKE" "SP-EASE-TXT" "COLOR" "2" "" ""))
)
(COMMAND "DIMALIGNED" "nea" PAUSE "per")
(setvar "clayer" oldlayer)
(princ)
)
I use this one for easement dimensions. If LISP can tackle this that's great, I was just under the impression it couldn't. I know the command for adding a single segment is "AeccAddSegmentLabel", but I didn't know how to go further from there with telling it to use certain styles.
Thanks!
Re: Assigning Layer +Line/Curve Style with .net API
You're partially correct; vanilla AutoLISP cannot do this in the sense that it stores some variables, changes them, does something useful, and then restores same (i.e., the Dimension, MLeader reference above). Where you are (or have been led to be) mistaken, is that Visual LISP (ActiveX COM) can do this, but requires some additional overhead to access Civil 3D's COM-exposed settings, etc. required to accomplish what you're asking for.
To the best of my knowledge, this can all be done in LISP, it's just a matter of who's going to code it first (if it hasn't been coded already; hence my inquiry of Opie's [code] toolbox Haha), and how slow does it perform, given .NET API is often exponentially faster.
... One way, or another... More to follow.
Re: Assigning Layer +Line/Curve Style with .net API
Ok I see.
I try to scour the internet a bit before asking for stuff (So glad google became popular as I grew up because the old days sound awful :D ), but of course that doesn't mean it's not hiding somewhere. I did find a handful of bearing/distance routines awhile ago, but they all utilize mtext, and are not dynamic which I felt was too much of a problem.
Whatever you can bring to the table would be greatly appreciated.
Re: Assigning Layer +Line/Curve Style with .net API
So I've just had a brief moment to look into this - It appears that the objects needed to complete this task in LISP are Read-Only (to LISP API), so we will have to step up in API:
Code:
(vl-load-com)
(defun c:GetStyleSettings (/ *error* vrsn aeccApp)
(defun *error* (msg)
(if aeccApp
(vlax-release-object aeccApp)
)
(cond ((not msg)) ; Normal exit
((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit)
((princ (strcat "\n** Error: " msg " ** "))) ; Fatal error, display it
)
(princ)
)
(if
(and
(setq vrsn (getvar 'acadver))
(setq vrsn
(cond
((vl-string-search "20.1" vrsn) "10.5")
((vl-string-search "20.0" vrsn) "10.4")
((vl-string-search "19.1" vrsn) "10.3")
((vl-string-search "19.0" vrsn) "10.0")
((vl-string-search "18.2" vrsn) "9.0")
((vl-string-search "18.1" vrsn) "8.0")
((vl-string-search "18.0" vrsn) "7.0")
((vl-string-search "17.2" vrsn) "6.0")
((vl-string-search "17.1" vrsn) "5.0")
)
)
(setq aeccApp (vla-getinterfaceobject
(vlax-get-acad-object)
(strcat
"AeccXUiLand.AeccApplication."
vrsn
)
)
)
)
(progn
(vlax-dump-object
(vlax-get
(vlax-get
(vlax-get (vlax-get aeccApp 'ActiveDocument) 'Settings)
'GeneralSettings
)
'StyleSettings
)
T
)
(textscr)
)
(prompt
"\n** Unable to interface with \"AeccXUiLand.AeccApplication\" object ** \n"
)
)
(*error* nil)
)
Re: Assigning Layer +Line/Curve Style with .net API
Quote:
Originally Posted by
BlackBox
So I've just had a brief moment to look into this - It appears that the objects needed to complete this task in LISP are Read-Only (to LISP API), so we will have to step up in API:
I think you are going down the wrong path to assign layers per object type. Those settings are located in the in the ObjectLayerSettings property of the active drawing's DrawingSettings property. When retrieving the Object Layer Settings properties, you'll notice all of the child properties are marked as read-only. Each one of these properties contains additional properties that are write enabled.
Unfortunately, my toolbox for this area is not fully fleshed out at the moment. Otherwise, I would share.
Re: Assigning Layer +Line/Curve Style with .net API
Hmmm. I'm trying to keep up with the semi-jargon to me. Sounds like Blackbox thinks this needs to be done in .net, but Opie is disagreeing? Looks like Blackbox was trying to retrieve some information with that code, which I tried in my own cad and it said I was unable to interface with the object.
Re: Assigning Layer +Line/Curve Style with .net API
Quote:
Originally Posted by
Opie
I think you are going down the wrong path to assign layers per object type. Those settings are located in the in the ObjectLayerSettings property of the active drawing's DrawingSettings property. When retrieving the Object Layer Settings properties, you'll notice all of the child properties are marked as read-only. Each one of these properties contains additional properties that are write enabled.
Unfortunately, my toolbox for this area is not fully fleshed out at the moment. Otherwise, I would share.
No worries; you're correct... And it didn't help matters that I had just finished work that night (the next morning?)... This was exactly the reminder I needed, WRT LISP + C3D, and for that I thank you. :beer:
Here's a sample routine to invoke the ADDSEGMENTLABELS Command with the specified settings:
Code:
(defun c:AddSanitaryFlowArrow ()
(_AddSegmentLabels "._addsegmentlabel" "P-SS-TX" "SS Flow Arrows" "SS Flow Arrows")
)
(defun c:AddSanitaryFlowArrows ()
(_AddSegmentLabels "._addsegmentlabels" "P-SS-TX" "SS Flow Arrows" "SS Flow Arrows")
)
;;; Arguments:
;;; commandName newGeneralSegmentLayerName newCurveLabelStyleName newLineLabelStyleName
** Note - the layer is created if it does not yet exist, but the Curve and Line Styles must already exist, or an error will result.
... And here's the dependent sub-function to handle the overhead of starting UNDO, storing the current settings, setting the new settings, and restoring when done, etc.:
Code:
(vl-load-com)
(defun _AddSegmentLabels (commandName newGeneralSegmentLayerName newCurveLabelStyleName
newLineLabelStyleName / *error* vrsn acApp
aeccApp aeccSettings aeccGeneralSegmentLabelLayer aeccGeneralCommandsSettings
aeccSegmentLabelSettings acDoc generalSegmentLayerName curveLabelStyleName
lineLabelStyleName)
(defun *error* (msg)
(if (and generalSegmentLayerName aeccGeneralSegmentLabelLayer)
(vlax-put aeccGeneralSegmentLabelLayer
'Layer
generalSegmentLayerName
)
)
(if (and curveLabelStyleName lineLabelStyleName aeccSegmentLabelStyleSettings)
(progn
(vlax-put aeccSegmentLabelStyleSettings
'CurveLabelStyle
curveLabelStyleName
)
(vlax-put aeccSegmentLabelStyleSettings
'LineLabelStyle
lineLabelStyleName
)
)
)
(if aeccApp
(vlax-release-object aeccApp)
)
(if acDoc
(vla-endundomark acDoc)
)
(cond ((not msg)) ; Normal exit
((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit)
((princ (strcat "\n** Error: " msg " ** "))) ; Fatal error, display it
)
(princ)
)
(if
(and
(setq vrsn (getvar 'acadver))
(setq vrsn
(cond
((vl-string-search "20.1" vrsn) "10.5")
((vl-string-search "20.0" vrsn) "10.4")
((vl-string-search "19.1" vrsn) "10.3")
((vl-string-search "19.0" vrsn) "10.0")
((vl-string-search "18.2" vrsn) "9.0")
((vl-string-search "18.1" vrsn) "8.0")
((vl-string-search "18.0" vrsn) "7.0")
((vl-string-search "17.2" vrsn) "6.0")
((vl-string-search "17.1" vrsn) "5.0")
)
)
(setq aeccApp (vla-getinterfaceobject
(setq acApp (vlax-get-acad-object))
(strcat
"AeccXUiLand.AeccApplication."
vrsn
)
)
)
(setq aeccSettings (vlax-get (vlax-get aeccApp 'ActiveDocument) 'Settings))
(setq aeccGeneralSegmentLabelLayer
(vlax-get
(vlax-get
(vlax-get
aeccSettings
'DrawingSettings
)
'ObjectLayerSettings
)
'GeneralSegmentLabelLayer
)
)
(setq aeccGeneralSettings (vlax-get aeccSettings 'GeneralSettings))
(setq aeccGeneralCommandsSettings
(vlax-get
(vlax-get (vlax-get aeccApp 'ActiveDocument) 'Settings)
'GeneralCommandsSettings
)
)
(setq aeccSegmentLabelStyleSettings
(vlax-get
(vlax-get
aeccGeneralCommandsSettings
(if (wcmatch (strcase commandName) "*SEGMENTLABELS")
'AddSegmentLabelsSettings
'AddSegmentLabelSettings
)
)
'StyleSettings
)
)
)
(progn
(vla-startundomark
(setq acDoc (vla-get-activedocument acApp))
)
;; store the current settings
(setq generalSegmentLayerName (vlax-get aeccGeneralSegmentLabelLayer 'Layer))
(setq curveLabelStyleName
(vlax-get
(vlax-get aeccSegmentLabelStyleSettings
'CurveLabelStyle
)
'Value
)
)
(setq lineLabelStyleName
(vlax-get
(vlax-get aeccSegmentLabelStyleSettings
'LineLabelStyle
)
'Value
)
)
;; set curve and line label styles
(vlax-put aeccSegmentLabelStyleSettings 'CurveLabelStyle newCurveLabelStyleName)
(vlax-put aeccSegmentLabelStyleSettings 'LineLabelStyle newLineLabelStyleName)
;; create layer if it doesn't exist
(vla-add (vla-get-layers acDoc) newGeneralSegmentLayerName)
(vlax-put aeccGeneralSegmentLabelLayer 'Layer newGeneralSegmentLayerName)
(prompt
(strcat
"\nCurrent Settings: "
"\nGeneral Segment Layer = " generalSegmentLayerName " --> " newGeneralSegmentLayerName
"\nCurve Label Style(s) = " curveLabelStyleName " --> " newCurveLabelStyleName
"\nLine Label Style(s) = " lineLabelStyleName " --> " newLineLabelStyleName
"\n\n "
)
)
(command commandName)
(while (= 1 (getvar 'cmdactive))
(command pause)
)
)
(prompt
"\n** Unable to interface with \"AeccXUiLand.AeccApplication\" object ** \n"
)
)
(*error* nil)
)
** Note - Tested using Civil 3D 2015, but configured to allow functionality in Civil 3D 2008-2016; please report any issues.
Cheers