Closed griemens closed 7 years ago
Try to include frtroot
as the first element of your branch creation params. For example, add yield return parent;
to the beginning of BuildCreationParameters()
.
When parentReference
is specified, it must reference an earlier branch creation param from the same sequence.
Great it works now!
Below is the working code as reference.
using System;
using System.Collections.Generic;
using System.Linq;
using Comos.Walkinside;
namespace CopyFRT2CustomFRT
{
static class Program
{
[STAThread]
static void Main()
{
DoCopy(@"D:\stabilizer\Stabilizer.vrp");
}
static public void DoCopy(string vrpfile)
{
// Open walkinside project.
IProject vrproject = ProjectManager.Open(vrpfile, AccessMode.ReadWrite);
var branches = vrproject.Branches.GetRoots(BranchKind.Cad);
IEnumerable<BranchCreationParams> param = BuildCreationParameters(branches);
BranchCreationParams[] collection = param.ToArray(); // do actual calculations
// Create the stuff.
vrproject.Branches.Create(collection);
}
static private IEnumerable<BranchCreationParams> BuildCreationParameters(IEnumerable<IBranch> branches)
{
// Build a FRT root branch.
var frtroot = new BranchCreationParams(BranchKind.Frt, "MyFRT");
yield return frtroot; // Important to return also in the set else SDK will throw exception.
// Create all the children by making a copy of branches.
IEnumerable<BranchCreationParams> param = BuildCreationParameters(branches, frtroot, 0);
foreach (var p in param)
yield return p;
}
static private IEnumerable<BranchCreationParams> BuildCreationParameters(IEnumerable<IBranch> branches, BranchCreationParams parent, int subrange)
{
foreach (var branch in branches)
{
var newbranch = new BranchCreationParams(
referenceKey: Guid.NewGuid(),
parentReference: parent.ReferenceKey,
name: branch.Name,
subtype: subrange,
elementSources: new IBranch[] { branch });
yield return newbranch;
foreach (var child in BuildCreationParameters(branch.Children, newbranch, subrange + 1))
{
yield return child;
}
}
}
}
}
Glad it worked!
Be careful though with subrange + 1
that you use recursively. Branch subtype cannot exceed 999, so if you have deep nesting it will fail with another exception.
What do you use this subtype for, by the way? Do you query specific hierarchy levels by it?
The subtype I will use now only for debugging purposes.
But one day I would like to use it for fast isolation of a Process System.
Building a tree structure for operations and all branches of same subtype belong to the same system.
The tree would be organized by Unit > Sub Unit > Equipment/Line/…
The branches of a system will be the lines/Equipments etc … and a system can be located in different subunits or units.
So in Walkinside I would have a context menu item Isolate > Unit Sub Unit System
I know in 7.0 SDK there was a GetBranchesByRange(minrange,maxrange) or something. But I need to check if is not also deprecated or obsolete in recent versions.
Thanks again for fixing my bug ☺
Actualy I just found another bug in my code.
...
IEnumerable
one day I would like to use [branch subtype] for fast isolation of a Process System
That should definitely work.
Would a branch attribute "griemens/process-subsystem"
work as well, while also being more explicit?
It's true that branch attribute support is a bit spotty at the moment, especially in Viewer SDK. But it's one of improvements we consider for upcoming release. The way I see it, we would need a good way to bulk-set branch attributes in Data SDK (such as via BranchCreationParams
) and good querying APIs both in Viewer SDK and Data SDK.
Conslusion if SubType = 0 Walkinside considers it a root branch.
That's exactly the underlying logic used by Walkinside Viewer for several major releases and, possibly, before that. It is preserved mainly for legacy reasons.
In the future it will be changed to a more sane logic, where root branch is the one without parent, not the one with subtype 0. Meanwhile SDK clients are encouraged to retrieve root branches using GetRoots
APIs, introduced to both Viewer SDK and Data SDK some time ago. When the logic finally changes, GetRoots
will use it, improving both speed and correctness. Until then you can add .Where(b => b.Parent == null)
to filter out "not true root" branches.
Feel free to reopen if there is anything else to discuss.
Hi,
I am trying to make an application that copies the CAD hierarchy information to the FRT hierarchy. It is based on the example in the repository, but much more simple code. But I have an exception thrown and I do not understand what I am doing wrong
The source code is here below. You can copy paste in a main.cs and run after you replaced the hard coded vrp file name @"D:\stabilizer\Stabilizer.vrp".
Any help is much appreciated Thanks
Code
Exception Information
Exception thrown: 'System.ArgumentException' in WalkinsideDataSDK.dll Additional information: Branch's ParentReference must point to a known branch, but was: <Comos.Walkinside.BranchCreationParams+RootBranchReference: Kind=Frt>. Please check that:
If there is a handler for this exception, the program may be safely continued.