Sparx Systems Forum

Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: Rik van der Schalie on July 30, 2020, 05:15:00 pm

Title: Elements contained within a Boundary
Post by: Rik van der Schalie on July 30, 2020, 05:15:00 pm
Enterprise Architect seemingly knows which elements are contained within  a boundary in a diagram; when the boundary is dragged, all elements within are dragged along.
However, when programming against EA, I do not seem to be able to find the Elements contained within a Boundary; the Boundary can be found as a DiagramObject, but the Elements and Connectors collections of the Boundary are both empty, and I cannot glance from the documentation how to find the Elements.

I'd appreciate any hints on how to proceed. T.I.A.
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 30, 2020, 05:25:15 pm
Doing it programmatically you have to do geometry (compare coordinates). The UI of EA does that internally.

q.
Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on July 30, 2020, 05:28:12 pm
Which, of course, is a nightmare for custom boundaries. But thanks for the answer.
Are there any code examples for this?
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 30, 2020, 05:35:11 pm
Well, no. Horizontal coordinates go from 0 upwards. Vertical from 0 towards negative. Not difficult, just cumbersome.

q.
Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on July 30, 2020, 05:46:59 pm
My point is that with a user-defined boundary the shape is not a simple rectangle, so the different edges of the diagram can have different Top, Bottom, Left and Right values. The small Element is not contained within the Boundary, yet according to the simple Top, Bottom, Left and Right values it would appear to be.

_______________
|                          |
|                          |  ______
|                          |  |         |
|                          |  --------
|                          -----------
|                                         |
-------------------------------
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 30, 2020, 06:09:20 pm
Well, remember your school geometry. EA's boundaries are always square (even the oval ones).

q.
Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on July 30, 2020, 06:18:32 pm
That's more than 40 years ago  ::)
I do know that the StyleEx attribute contains the Path, consisting of a list of x-y coordinates of the corner points. The trick is of course to separate the complex shape into a set of simple rectangles.
Title: Re: Elements contained within a Boundary
Post by: MichaelJ on July 30, 2020, 07:21:34 pm
Hi rchalie,

Yes, this is a real pain in the butt when working programmatically with diagram objects inside boundaries. Sparx EA ABSOLUTELY can make this easier by utilising the "Parent_ID" (or even introduce a new "Boundary_ID") column in the t_object table. Alas, good user experience is hard to find in the product because it seems "...why click once when a user can click FIVE times to achieve the same outcome? Come on! If it ain't broke (like unsorted lists all over the place)... we ain't gonna fixxy wixxy".
Nevertheless, here's a script I've used to resolve a similar problem. It's based on the same logic I believe the product uses internally to calculate whether or not an element is WITHIN a boundary:


Code: [Select]
        var diagram as EA.Diagram;
        diagram = Repository.GetDiagramByID(diagramID);
       
        var diagramObjects as EA.Collection;
        diagramObjects = diagram.DiagramObjects;

        var loadedElms = [];    // elements contained within a boundary
        var unprocessed = [];
        var boundaries = [];
       
        // iterate all elements on the diagram and find boundaries and non-boundaries
        for(var i = 0; i < diagramObjects.Count; i++) {
            var dob as EA.DiagramObject;
            dob = diagramObjects.GetAt(i);
           
            var currentElement as EA.Element;
            currentElement = Repository.GetElementByID(dob.ElementID);
           
            if (currentElement.Type !== "Boundary"){
                loadedElms.push({ name: currentElement.Name, notes: currentElement.Notes, dob: dob });
                continue;
            }

            boundaries.push(dob);
        }
       
        // we want to sort the elements alphabetically
        loadedElms.sort(sortArray);
       
        // mark all elements as NOT contained in a boundary so later processing will remove them;
        // whatever's left are elements NOT contained by a boundary
        for(var i=0;i<loadedElms.length;i++)
            unprocessed.push(loadedElms[i].dob.ElementID);
       
        for(var i=0;i<boundaries.length;i++){
            var dob = boundaries[i];
           
            var left = dob.left;
            var top = dob.top;
            var right = dob.right;
            var bottom = dob.bottom;
           
            var count = 0;
            var sortedElms = [];
           
            for (var j = 0; j < loadedElms.length; j++) {
                var elm = loadedElms[j];
                if (!elm)
                    continue;
               
                var diagramObject2 = elm.dob;
                   
                if (diagramObject2.left>= left &
                    diagramObject2.top <= top &
                    diagramObject2.right<=right &
                    diagramObject2.bottom >= bottom){
                   
                    sortedElms.push({ name: elm.name, notes: elm.notes });
                    count += 1;
                       
                   // this element is part of this boundary, so ... you know... let's remove it
                    unprocessed[j] = -1;
                }
            }

            if (count){
                // use srotedElms to iterate the elements for THIS boundary                // For exaMple, you could populate a template or do some other processing with the elements inside the boundary
            }
           
            sortedElms= [];
            count = 0;
        }   
Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on July 30, 2020, 08:10:46 pm
Hi Michael,

Thanks! I'm going to look into this, but my issue is that you work here on the assumption that the boundary is a simple rectangle. My boundary is a user-define boundary, so an irregular shape (with only orthogonal angles). I need a way to separate my irregular boundary in a set of rectangular boundaries, based only on a list of corner points. I cannot make an assumption on where on my user-defined boundary that list starts. I think I cannot even make an assumption on whether the list of corner points is in the clockwise or anti-clockwise direction along the boundary border.
Title: Re: Elements contained within a Boundary
Post by: MichaelJ on July 30, 2020, 11:43:57 pm
...you work here on the assumption that the boundary is a simple rectangle. My boundary is a user-define boundary, so an irregular shape...
Every shape can be broken down into a series of smaller rectangles. If you want to determine whether an element is part of an irregular shape, you'd need to check if an element's "bounding box" is contained fully or partially by one or more of rectangles that make up the irregular shape.

Referring to your earlier post...
...The small Element is not contained within the Boundary, yet according to the simple Top, Bottom, Left and Right values it would appear to be....

_______________
|                          |
|                          |  ______
|                          |  |         |
|                          |  --------
|                          -----------
|                                         |
-------------------------------
Could you please validate inside the t_diagramobjects table that this is indeed the case? Each element on a diagram canvas has the required bounding box dimensions, so if, according to the post above, the small element is *outside* the irregular shape, then the bounding boxes for the irregular shape and the small element contained in t_diagramobjects table will indeed reflect that.

Now, how to go about to determine if the small element is inside an irregular shape with straigh edges?

I see a two-step approach could be helpful:

Step one: break into smaller rectangles
_______________
|                          |
|                          |  ______
|          #1            |  |         |
|                          |  --------
_______________
|------------------------------
|              #2                       |
-------------------------------


Step two: use the script code provided to test if the small element is contained within [#1] or [#2].

Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on July 31, 2020, 12:03:51 am
The only graphical information I can find about the irregular Boundary is, in the StyleEx atttribute, a Path, consisting of an ordered set of corners of the type "X1:Y1@X2:Y2@X3:Y3@X4:Y4@X5:Y5@X6:Y6" for a boundary with six corners (which could be split up in two rectangles X1:Y1@X2:Y2@X2:Y6@X6:Y6 and X2:Y4@X4:Y4@X5:Y5@Xx:Y5). The issue is of course that an irregular boundary would have to be split up in (N-4)/2 rectangles for N corners, so 6 corners will give two rectangles, 10 corners will give 4 rectangles. The thing is, there are multiple ways of splitting any irregular boundary into rectangles.
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 31, 2020, 05:16:32 am
I'm not sure what you think you see there. EA diagram objects are either rectangles or drawn via shape script. From where do you take this path information?

q.
Title: Re: Elements contained within a Boundary
Post by: MichaelJ on July 31, 2020, 06:38:35 am
...EA diagram objects are either rectangles or drawn via shape script. From where do you take this path information?
StyleEx is located in the t_object table; ObjectStyle column in the t_diagramobjects table.
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 31, 2020, 07:47:35 am
Interesting. How do you define a boundary with, say, L-shape? Is that new with V15?

I skimmed these columns and none has anything like the above path. At least that path must be preprended with some "key=". Which would that be? Path? And how does it interact with shape scripts???

q.
Title: Re: Elements contained within a Boundary
Post by: MichaelJ on July 31, 2020, 08:38:06 am
...How do you define a boundary with, say, L-shape? Is that new with V15?...
The data is stored in t_object in the StyleEx column. For example, I did an L-Shape and got this data "BT=81;Path=124:-493@505:-493@505:-599@306:-599@306:-747@124:-747;". Then in t_diagramobjects, the ObjectStyle column records this data "DUID=1D9BC707;shape=freestyle;"

...Is that new with V15?...
Yes.

...And how does it interact with shape scripts???...
I'm not sure; I have only worked with rectangular boundaries in scripts. However, rchalie wants to work with L-Shaped boundaries and then calculate while diagram objects are "contained" within it.
Title: Re: Elements contained within a Boundary
Post by: KP on July 31, 2020, 08:53:32 am
Interesting. How do you define a boundary with, say, L-shape? Is that new with V15?

Introduced in EA14
Title: Re: Elements contained within a Boundary
Post by: Paolo F Cantoni on July 31, 2020, 10:25:09 am
Enterprise Architect seemingly knows which elements are contained within a boundary in a diagram; when the boundary is dragged, all elements within are dragged along.
However, when programming against EA, I do not seem to be able to find the Elements contained within a Boundary; the Boundary can be found as a DiagramObject, but the Elements and Connectors collections of the Boundary are both empty, and I cannot glance from the documentation how to find the Elements.

I'd appreciate any hints on how to proceed. T.I.A.
AFAIK, there is NO actual API to return this information.  We did a lot of work in detecting visual embedding for model analysis purposes and we had to write a sophisticated script to do the work.

Paolo
Title: Re: Elements contained within a Boundary
Post by: qwerty on July 31, 2020, 04:39:37 pm
Ok, thanks. Looks like I have to make an update to my Inside book.

q.

P.S. A shape script overrides any custom shape. The bends are still selectable (which gives the right Sparx-feeling). And the outmost dimension define the 100x100 area for the shape script.
Title: Re: Elements contained within a Boundary
Post by: Rik van der Schalie on September 03, 2020, 05:04:24 pm
I now have a working solution. By the way, for simple rectangles the StyleEx attribute is empty. You will need to get the dimensions of the boundary from the DiagramObject itself.