Author Topic: Creating new layer with plot styles  (Read 11039 times)

0 Members and 1 Guest are viewing this topic.

mcarson

  • Guest
Creating new layer with plot styles
« on: February 25, 2008, 09:01:05 AM »
Seem to have a few issues adding named plot style to a new layer on creation.

Code: [Select]
/// <summary>
/// Creates a new layer
/// </summary>
/// <param name="layerName"></param>
/// <param name="layerColor"></param>
/// <param name="lineweightName"></param>
/// <param name="plotstyleName"></param>
/// <param name="linetypeName"></param>
/// <returns></returns>
/// <remarks>Attempts to avoid the erased objectid API bug</remarks>
public ObjectId CreateLayer(string layerName, short layerColor, LineWeight lineweightName, string plotstyleName)
{
   
    //Create objectid varaible for layer
    ObjectId layerId;
    //Get the current database
    Database db = HostApplicationServices.WorkingDatabase;
   
    //Start the transaction manager with a new write transaction
    using (Transaction tr = db.TransactionManager.StartTransaction()) {
        //Get layer table from database
        LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForWrite);
        //Check if layer exists
        if (lt.Has(layerName)) {
            //Return the existing layer
            layerId = lt(layerName);
            if (layerId.IsErased) {
                //OK, layer has been purged in the current drawing session,
                //We do NOT want to use the layer in it's current state
                //Set a new layer record and change the status of the erased
                //layer to false
                LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite, true);
                ltr.Erase(false);
                //return the layer record
                layerId = ltr.Id;
            }
        }
        else {
            //the layer has never existed in the current drawing
            //For test purposes, we are only allowing colors from 1 to 255
            if (layerColor > 255) {
                Layers.PrintToCmdLine(string.Format("" + Strings.Chr(10) + " ERROR: Could not use LayerColor \"{0}\", using 0 instead.", layerColor));
                layerColor = 0;
            }
           
            //Create new layer record
            LayerTableRecord ltr = new LayerTableRecord();
            //Set the name for the new record
            ltr.Name = layerName;
            //Set the color for the new record
            ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, layerColor);
            //Set the layer default lineweight
            ltr.LineWeight = lineweightName;
            //Set the plot style for the layer
            //--------------- Crashes here...
            ltr.PlotStyleName = "Color_7"
            //Add the layer record and get the objectid
            layerId = lt.Add(ltr);
            //Add the layer to the database
            tr.AddNewlyCreatedDBObject(ltr, true);
        }
        //Commit the transaction
        tr.Commit();
    }
    //Return the object id so we can make changes if needed
    return layerId;
}

I sorta know why it's breaking - the current drawing does not use named plot styles.

Now, for the real problem:

How do I convertpstyles and convertctb in .NET code? :?

mcarson

  • Guest
Re: Creating new layer with plot styles
« Reply #1 on: February 27, 2008, 02:57:37 AM »
For an update:

I have not found a method to complete this task in .NET, however as a workaround I am first checking the pstylemode variable.

Code: [Select]
/// <summary>
/// Indicates whether the current drawing is in a Color-Dependent or Named Plot Style mode.
/// </summary>
/// <returns>0: Uses named plot style tables in the current drawing
///1: Uses color-dependent plot style tables in the current drawing</returns>
/// <remarks></remarks>
public bool PlotStyleMode()
{
    bool result = false;
    if (Convert.ToInt32(AcadApp.GetSystemVariable("pstylemode")) == 1) {
        result = true;
    }
    return result;
}

If named plot styles are being used in the current drawing, I can set the plot style per layer. If not, ignore the setting and continue

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: Creating new layer with plot styles
« Reply #2 on: February 27, 2008, 05:06:44 AM »
Nice work Mark, and welcome to the Swamp!  :-)

mcarson

  • Guest
Re: Creating new layer with plot styles
« Reply #3 on: February 27, 2008, 07:14:08 AM »
Another update:
This is really starting to get to me;
I compiled and loaded the functions into AutoCAD and guess what? another error :-( eNoDatabase  :?

Right, so I am guessing when this is because I have no plotstyle with this name. Changed it to "Black" - same error
I added another function to add my plot style table file to the layout

Code: [Select]
/// <summary>
/// Adds a plot style to the current layout and sets it current
/// </summary>
/// <param name="strPlotStyleName"></param>
/// <remarks></remarks>
public void AddPlotStyle(string strPlotStyleName)
{
    Database db = HostApplicationServices.WorkingDatabase;
    LayoutManager lm = LayoutManager.Current;
    using (Transaction tr = db.TransactionManager.StartTransaction()) {
       
        PlotSettingsValidator psv = PlotSettingsValidator.Current;
        Layout layout = (Layout)tr.GetObject(lm.GetLayoutId(lm.CurrentLayout), OpenMode.ForWrite);
        psv.SetCurrentStyleSheet(layout, strPlotStyleName);
        tr.Commit();
    }
}

Same error.

Can anyone point me in the right direction?

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: Creating new layer with plot styles
« Reply #4 on: February 27, 2008, 10:04:16 AM »
I’ll try and point you somewhere, I don’t know if it’s the right direction though.  :-o
According to the docs, the layer should already be added to the database before you screw with it.

Check this out

Code: [Select]
//Hi Kerry :)
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcWd = Autodesk.AutoCAD.Windows;
#endregion

[assembly: CommandClass(typeof(ExecMethod.Commands))]

namespace ExecMethod
{
  public class Commands
  {
    public ObjectId CreateLayer(string layerName, short layerColor, LineWeight lineweightName)
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ObjectId layerId = ObjectId.Null;
      Database db = HostApplicationServices.WorkingDatabase;
      try
      {
        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
          LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForWrite);
          if (lt.Has(layerName))
          {
            layerId = lt[layerName];
            if (layerId.IsErased)
            {
              LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite, true);
              ltr.Erase(false);
              layerId = ltr.Id;
            }
          }
          else
          {
            if (layerColor > 255)
            {
              ed.WriteMessage(string.Format(" ERROR: Could not use LayerColor \"{0}\", using 0 instead.", layerColor));
              layerColor = 0;
            }
            LayerTableRecord ltr = new LayerTableRecord();
            ltr.Name = layerName;
            ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, layerColor);
            ltr.LineWeight = lineweightName;
            layerId = lt.Add(ltr);
            tr.AddNewlyCreatedDBObject(ltr, true);
          }
          tr.Commit();
        }
      }
      catch (System.Exception ex)
      {
        ed.WriteMessage(ex.StackTrace);
      }
      return layerId;
    }

    public void AddPlotStyle(ObjectId id, string strPlotStyleName)
    {
      Database db = HostApplicationServices.WorkingDatabase;
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      if (db.PlotStyleMode == false)
      {
        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
          DictionaryWithDefaultDictionary d =
            (DictionaryWithDefaultDictionary)tr.GetObject
                (db.PlotStyleNameDictionaryId, OpenMode.ForRead);

          LayerTableRecord ltr =
               (LayerTableRecord)tr.GetObject(id, OpenMode.ForWrite);

          ltr.PlotStyleNameId = d.GetAt(strPlotStyleName);
          tr.Commit();
        }
      }
    }

    [CommandMethod("doit")]
    public void doit()
    {
      AddPlotStyle(this.CreateLayer("Daniel", 7, LineWeight.ByLayer), "Normal");
    }
  }
}


« Last Edit: February 27, 2008, 10:07:39 AM by Daniel »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: Creating new layer with plot styles
« Reply #5 on: February 27, 2008, 11:59:01 AM »
Sorry, I’m an idiot, It still crashes  :oops:

sinc

  • Guest
Re: Creating new layer with plot styles
« Reply #6 on: February 27, 2008, 12:23:13 PM »
I couldn't get it to work, either, when I tried setting the PlotStyleName.  Instead, I set the PlotStyleNameId.

There is working code for this in the AcadUtilities library available for download from Quux Software.  The solution actually contains three projects, and two of them only work in Civil-3D.  But the AcadUtilities project should work in any version of Autocad (at least 2008, don't know about earlier versions).

If you download that, you can drag-n-drop a "Select Plot Style" control onto your form, and you are pretty much done.  You also need to instantiate a "command parameter" to go along with it.  Take a look at the "CreateLayerForm" class to see how to use it.

sinc

  • Guest
Re: Creating new layer with plot styles
« Reply #7 on: February 27, 2008, 12:25:25 PM »
Oh shoot, and it occurs to me I should probably test that code with CTBs.

STBs are so much better, I forget that a lot of people are still using CTBs.  But I think all I need to do is add code that disables the control if the drawing is using CTBs, since it doesn't apply to CTB drawings.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Creating new layer with plot styles
« Reply #8 on: February 27, 2008, 12:35:59 PM »
If you want to create a bigger fan base Sinc write a "The Pragmatist's Guide to Intelligent Plotting Using CTBs or STBs", because it's needed and doesn't exist.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

sinc

  • Guest
Re: Creating new layer with plot styles
« Reply #9 on: February 27, 2008, 03:22:10 PM »
If you want to create a bigger fan base Sinc write a "The Pragmatist's Guide to Intelligent Plotting Using CTBs or STBs", because it's needed and doesn't exist.

It would start with "Forget CTBs ever existed..."   :-D

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating new layer with plot styles
« Reply #10 on: February 27, 2008, 04:39:02 PM »

I've only ever used CTB's , so I can't help :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Creating new layer with plot styles
« Reply #11 on: February 27, 2008, 06:41:36 PM »
If you want to create a bigger fan base Sinc write a "The Pragmatist's Guide to Intelligent Plotting Using CTBs or STBs", because it's needed and doesn't exist.

It would start with "Forget CTBs ever existed..."   :-D
And that would create the mayhem that plotting in 2000 started
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: Creating new layer with plot styles
« Reply #12 on: February 27, 2008, 10:31:04 PM »
I tried again, but failed miserably (in ARX  too), my suggestion would be to reflect upon the built-in layer
dialog as it is managed and see if you can find the mojo. I might have a look later as well.

Off to Disneyland to see if I can get my daughter to “Space Ranger” status on the Buzz Lightyear ride.  :-P

mcarson

  • Guest
Re: Creating new layer with plot styles
« Reply #13 on: February 28, 2008, 03:39:12 AM »
This post has grown arms and legs!

It seems that it is not possible to assign a plot style name from a new inserted plot style table when no objects are using the plot style name.
i.e.
Open a new drawing
  • Run the add plot style table function:
Code: [Select]
public void AddPlotStyleTable(string plotstyletableName)
{
    Database db = HostApplicationServices.WorkingDatabase;
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    LayoutManager lm = LayoutManager.Current;
   
    try {
        ed.WriteMessage(Strings.ChrW(10) + "Starting transaction...");
        using (Transaction tr = db.TransactionManager.StartTransaction) {
            ed.WriteMessage(Strings.ChrW(10) + "Setting the psv to the current layout: " + lm.CurrentLayout);
            PlotSettingsValidator psv = PlotSettingsValidator.Current;
            Layout ly = (Layout)tr.GetObject(lm.GetLayoutId(lm.CurrentLayout), OpenMode.ForWrite);
            ed.WriteMessage(Strings.ChrW(10) + "Adding the plot style table");
            psv.SetCurrentStyleSheet(ly, plotstyletableName);
            tr.Commit();
        }
    }
    catch (Exception ex) {
        Interaction.MsgBox(ex.ToString);
    }
}
Adding a plot style table that exists in your support paths
  • Add the posted solution by Daniel :-)
Code: [Select]
public void doit()
{
    AddPlotStyleTable("test.stb");
    AddPlotStyle(CreateLayer("Test Layer", 1, LineWeight.LineWeight000), "Black");
}
The function fails eKeyNotFound
The plot style has yet to be assigned to an object, and is not in use (I guess)

Now try this..
  • New AutoCAD session
  • Add a line to model space
  • Change the objects properties to use the Black plot style name in the test.stb
  • Execute the program
Works now (or for me anyway)

We could try to add a line by code and assign the plot style name from the plot style table, but again will be facing the problem where the plot style name is not in use and therefore cannot be assigned.
A workaround could be to insert a block (one that has the plot style table attached and the plot style names in use) before the layer is created, then afterwards, delete and purge.
But this, in my opinion is not 'managed' .net development; the creation of a layer requires a block to be stored somewhere in the support paths?

mcarson

  • Guest
Re: Creating new layer with plot styles
« Reply #14 on: February 28, 2008, 03:46:45 AM »

I've only ever used CTB's , so I can't help :-)

The thing is, I am attempting to use both CTBs and STBs - both of which have similar issues.