Problems with layer list order

I don’t believe there are any problems here.

Unlike Rhino, AutoCAD does not allow you to reorder layers. Thus, whenever you open a DWG or DXF file in AutoCAD, it will always appear sorted.

Also, if you open the 3DM file and then SaveAs both DWG and DXF without closing the 3DM file, you will see that the layers from the DWG and DXF file appear in the same order when opened in Rhino.

My guess is that Rhino saves layers to DWG and DXF files in the order in which they appear in the layer table. There is no reason to write layers in sorted order as, again, AutoCAD does not track a layer’s sort order.

Thanks for the explanation Dale, I’d forgotten that AutoCAD maintains sorted layers - I used to prefix layers with numbers in Acad to maintain some assemblance of order and grouping, the Rhino system is so… much better.

To modify my query, when an Acad created .dwg, is opened in Rhino, is the layer list arranged according to a sort index applied in Acad as opposed to the way they are displayed in Acad?

Secondly, keeping Autocad out of it, in the dxf example above (1 and 2), the unsorted original list becomes re-ordered, yet still unsorted, when exported as a dxf.

Is this expected behaviour, I am curious now, that in files I send off for cnc cutting, the layers are probably displaying in a different order than intended when opened in 3rd party software? I’ve never had feedback from cnc-cutters over this, but reading @DanBayn comments above, this could be problematic.

Thanks for the code Dale, but I am sorry, I still get incorrect layers sort index.
Below is the code I now use:

Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc;

doc.Views.RedrawEnabled = false;
doc.Views.RedrawEnabled = true;
doc.Views.Redraw();

List<KeyValuePair<int, int>> sortList = new List<KeyValuePair<int, int>>(doc.Layers.Count);

foreach (Rhino.DocObjects.Layer layer in doc.Layers)
{
  if (!layer.IsDeleted)
    sortList.Add(new KeyValuePair<int, int>(layer.LayerIndex, layer.SortIndex));
}

sortList.Sort(
  delegate(KeyValuePair<int, int> firstPair,
               KeyValuePair<int, int> nextPair)
               {
                 return firstPair.Value.CompareTo(nextPair.Value);
               }
  );

RhinoApp.WriteLine("---------------- Layer order --------------------------------------------");
foreach (KeyValuePair<int, int> pair in sortList)
  if (IsToolpathLayer(doc.Layers[pair.Key]))
    RhinoApp.WriteLine("Toolpath Name = {0}, LayerIndex = {1}, SortIndex = {2}", doc.Layers[pair.Key].Name, pair.Key, pair.Value);
  else
    RhinoApp.WriteLine("Name = {0}, LayerIndex = {1}, SortIndex = {2}", doc.Layers[pair.Key].Name, pair.Key, pair.Value);

The ui layers looks like this when open the model:

…and the layer order i get.

---------------- Layer order --------------------------------------------

Name = 01 Block, LayerIndex = 0, SortIndex = 0
Name = 02 Surfaces, LayerIndex = 1, SortIndex = 1
Name = madCAM, LayerIndex = 2, SortIndex = 2
Name = Clipping Planes, LayerIndex = 3, SortIndex = 3
Name = Box-region, LayerIndex = 4, SortIndex = 4
Name = 36_T14_Ø50.8r1.6_finish_bullnose_alum, LayerIndex = 5, SortIndex = 5
Name = 40_T8_Ø10_finish_ballnose_alum, LayerIndex = 6, SortIndex = 6
Toolpath Name = Z_Levels_40_T8_Ø10_finish_ballnose_alum Group:3, LayerIndex = 7, SortIndex = 7
Toolpath Name = Roughing_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:0, LayerIndex = 8, SortIndex = 8
Toolpath Name = Roughing_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:1, LayerIndex = 9, SortIndex = 9
Toolpath Name = Planar_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:0, LayerIndex = 10, SortIndex = 10

Layer number 7 should be the last toolpath, but it goes as the first toolpath. If I manually move layer number 5 down in the ui list and then up again, it seems like the layer list becomes correct and the sortindexes syncs with the ui as it should.

Below is what I get after manually moving a layer in the list.

---------------- Layer order --------------------------------------------

Name = 01 Block, LayerIndex = 0, SortIndex = 0
Name = 02 Surfaces, LayerIndex = 1, SortIndex = 1
Name = madCAM, LayerIndex = 2, SortIndex = 2
Name = Clipping Planes, LayerIndex = 3, SortIndex = 3
Name = Box-region, LayerIndex = 4, SortIndex = 4
Name = 36_T14_Ø50.8r1.6_finish_bullnose_alum, LayerIndex = 5, SortIndex = 5
Toolpath Name = Roughing_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:0, LayerIndex = 8, SortIndex = 6
Toolpath Name = Roughing_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:1, LayerIndex = 9, SortIndex = 7
Toolpath Name = Planar_36_T14_Ø50.8r1.6_finish_bullnose_alum Group:0, LayerIndex = 10, SortIndex = 8
Name = 40_T8_Ø10_finish_ballnose_alum, LayerIndex = 6, SortIndex = 9
Toolpath Name = Z_Levels_40_T8_Ø10_finish_ballnose_alum Group:3, LayerIndex = 7, SortIndex = 10

Thanks,

Joakim

@dale, any thoughts on the original issue Joakim posted? It’s just a matter of time before someone doesn’t notice the layer order and ends up smashing something expensive. Can you take another look at the layer sort index and see if you can find a problem with it? I would think that Joakim can provide more code samples if you need. He is just as eager as I am to get this resolved.

Thanks,

Dan

Dan, its pretty hard to fix something that I cannot repeat. I’ve never seen a model that repeats the report behavior. Until I get a model, source code and/or a procedure that I can use to replicate the issue, I’m not sure how to help.

Yeah, it’s the repeatability that’s the tough thing here. I had a file saved that gave me this problem, and I was about to send it to you, but it’s working fine now. I’ll ask Joakim if he has something he can repeat.

Thanks, and have a great weekend,

Dan

Hi Dale,

Here is a file that can repeat the issue. However, don’t save the file or the issue will disappear. Perhaps there is a clue in that. This was a file I sent to Joakim a while ago but I’ve resaved mine, so that’s why I couldn’t repeat it.

kuverta-1.3dm(443.7 KB)

As for samples of source code for madCAM, I don’t have access to that.

Dan

Hi Dale,

madCAM saves tool paths as regular curves in Rhino. You can test with the following code without having madCAM installed.

Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc;

doc.Views.RedrawEnabled = false;
doc.Views.RedrawEnabled = true;
doc.Views.Redraw();

List<KeyValuePair<int, int>> sortList = new List<KeyValuePair<int, int>>(doc.Layers.Count);

foreach (Rhino.DocObjects.Layer layer in doc.Layers)
{
if (!layer.IsDeleted)
sortList.Add(new KeyValuePair<int, int>(layer.LayerIndex, layer.SortIndex));
}

sortList.Sort(
delegate(KeyValuePair<int, int> firstPair,
KeyValuePair<int, int> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);

foreach (KeyValuePair<int, int> pair in sortList)
RhinoApp.WriteLine(“Name = {0}, LayerIndex = {1}, SortIndex = {2}”, doc.Layers[pair.Key].Name, pair.Key, pair.Value);

Thanks,

Joakim

Hi Joakim,

I’ve made a small change to Rhino 5 SR6 that might fix this. When a release candidate is available, try the code you posted above and see if it works more consistent.

Thank you!

Looking forward to testing here too.

Thanks Dale

Its working now. I get correct layer sort indexes with SR6.

Thanks Dale.

There is still a layer sorting order issue with Illustrator export. Most users won’t notice if they casually create layers from top to bottom, but in fact Illustrator export is according to layer creation order, and it totally ignores changes in Rhino Layers palette order.

Problem detailed here:

http://discourse.mcneel.com/t/illustrator-layers/1392/19?u=nikwillmore

@NikWillmore, can you explain more why this is a problem?

@tim, is this something that is fixable?

Illustrator treats layer order as object overlap stacking order, visually. Yet I have no control over what Rhino layer order is exported into an .ai file since mere layer creation order is rather chaotic and arbitrary as I work, a mere historical artifact of my whims and attention span as I create a complex model on top of some architectural plan in a picture frame. But I need my lines and text on top of any eventually filled in areas or they won’t be visible. With perhaps hundreds of text annotations generated by Grasshopper, I can’t realistically manually reorder them in Illustrator to recreate my Rhino layer order.

I have developed a Python script to export objects as an SVG file to get around this issue for now.

I can assure you that layer creation is neither chaotic nor arbitrary. New layers are appended to the end of an internal array of layers, which resides on the active document. The display order - the order the layers appear in the Layer panel, has nothing to do with a layer’s layer index.

That said, when Rhino saves the document, it does save layers in their display order. This is done because the display order is not saved in the 3dm file. Thus when you reopen a file, the layers appear how you arranged them before saving. So one inconvenient work around it to save the document, reopen the document, and then export to .AI.

I’ve added a YouTrack item to modify the .AI exporter to write layers in display order. You can track the item here:

http://mcneel.myjetbrains.com/youtrack/issue/RH-32743

Hi @dale,

I’ve noticed a specific moment when the UI and SortIndices appear to be out of sync: namely the moment a layer is added to the table:

RhinoLayerSortIndex

The sort indices are correct after Sorted or Deleted events (or if the sort order is requested at the command line), but I need to detect the correct order programatically after an Added event (which, in the screenshot above, is the only event raised). Is there a way to force the change to register before I check the indices? I’m lifting your code from earlier in this thread.

internal static void OnLayerTableEvent(object sender, LayerTableEventArgs e)
{
    List<KeyValuePair<int, int>> sortList = new List<KeyValuePair<int, int>>(e.Document.Layers.Count);

    foreach (Rhino.DocObjects.Layer layer in e.Document.Layers)
    {
         if (!layer.IsDeleted)
        sortList.Add(new KeyValuePair<int, int>(layer.LayerIndex, layer.SortIndex));
    }

    sortList.Sort(
        delegate (KeyValuePair<int, int> firstPair,
        KeyValuePair<int, int> nextPair)
        {
            return firstPair.Value.CompareTo(nextPair.Value);
        }
    );

    RhinoApp.WriteLine(e.EventType.ToString() + " " + e.Document.Layers.FindIndex(e.LayerIndex).Name);
    foreach (KeyValuePair<int, int> pair in sortList)
        RhinoApp.WriteLine("Name = {0}, LayerIndex = {1}, SortIndex = {2}", e.Document.Layers[pair.Key].Name, pair.Key, pair.Value);
}

This is Rhino 6 by the way.

Cheers,

Jon

Hi @Jon,

Yes, this is true. The sort order cannot be updated until the new layer has been and added (and thus can be included in the sort).

– Dale

Hi @dale,

I don’t follow. The new layer (Layer 04) has already been added to the LayerTable – as evident in the app writelines visible in the screenshot. The problem is that it’s been added in the wrong sort position.

Is there a fix for this? Clearly the sort order gets corrected at some (later) point, but as far as I can tell, there’s no catchable event to indicate when the correction has occurred.

Jon

Yes this is correct. The sorting occurs after the Add event.

– Dale