Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Prioritising Mindfusions NearestNode (Read 4346 times)
Waterfiets
Junior Member
**
Offline


I Love MindFusion!

Posts: 78
Joined: Sep 27th, 2013
Prioritising Mindfusions NearestNode
Nov 21st, 2013 at 8:55am
Print Post  
Hi Stoyan,

During the re-factoring of our project we found out that the snap logic sometimes isn't working as we would like it to work.

To get the node to snap to the nearest connection point we use the MindFusion method GetNearestNode, which will - at least, i presume - look up the nearest node in correspondence to the node that's being dragged. However, sometimes it will snap to a snap-point on a node that is visually not the nearest node.

According to this, a few questions come to mind:

1) The first question is, does the nearest node get calculated from the bounds of the node that is being dragged, or is it calculated from the cursor position?

2) The second question is, does it have anything to do with an error in the way we calculate our snap-points?

3) Our third question is, if the above questions are not relevant, might it be possible to prioritize certain nodes when calling the GetNearestNode method? Or if this is not possible, or the right problem, could you give us a hint as to where to fine tune this?

Code
Select All
protected void AlignToNearestPoint(Point current, InteractionState ist)
        {
            if (ist.AdjustmentHandle == 8) // If the node is moved
            {
                BRNode nearbyNode;
                switch (SnapType)
                {
                    case SnapTypes.Free: nearbyNode = (BRNode)Parent.GetNearestNode(current, 25, this); break;
                    case SnapTypes.SnapInstantly: nearbyNode = GetParentDiagramElement().GetLastAddedBRNode(); break;
                    default: nearbyNode = (BRNode)Parent.GetNearestNode(current, 25, this); break;
                }

                if (nearbyNode != null)
                {
                    if (!(nearbyNode is BRIfNode))
                        nearbyNode.SendAlignRequestToController((int)this.Tag);
                }
            }
        }  



Thanks in advance Smiley.

Greets,

Sander
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Prioritising Mindfusions NearestNode
Reply #1 - Nov 21st, 2013 at 12:49pm
Print Post  
Hi,

GetNearestNode takes a Point parameter, to which you pass first argument of your AlignToNearestPoint method. I suppose that corresponds to current mouse position, if you haven't modified it earlier to match a snap point on your nodes. Also check if Diagram.AlignToGrid is enabled, then you might be passing a grid point to GetNearestNode instead of the mouse position and getting unexpected results.

As for prioritizing nodes, instead of GetNearestNode try calling GetNodesInViewport method, and then sorting the returned list by your priorities.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Waterfiets
Junior Member
**
Offline


I Love MindFusion!

Posts: 78
Joined: Sep 27th, 2013
Re: Prioritising Mindfusions NearestNode
Reply #2 - Nov 22nd, 2013 at 10:05am
Print Post  

Hi Stoyan,

Thanks for the info, we're gonna give it a try!

Chocolate Bar status:

20 + 1;

Grin

Greetings,

Sander
  
Back to top
 
IP Logged
 
Vincent
Junior Member
**
Offline


I Love MindFusion!

Posts: 62
Joined: Oct 3rd, 2013
Re: Prioritising Mindfusions NearestNode
Reply #3 - Dec 9th, 2013 at 9:37am
Print Post  
Hi Stoyan,

We have operator nodes (with the left and right slot) which should be able to nest in each other. Initially we use diagram.GetNearestNode() for all nodes. But in the case of the operator that method always returns the outer parent which makes nesting into one of the children difficult. For operators we use our own method GetClosestNode() which utilizes diagram.GetNodesInViewPort() and then returns a node based on our criteria. So far we have:

Code
Select All
public override DiagramNode GetClosestNode()
        {
            Point sourcePoint = Bounds.TopLeft;
            DiagramNodeCollection allNodes = Parent.GetNodesInViewport();
            DiagramNode closestNode = allNodes.FirstOrDefault(x => ((new Point(x.Bounds.Left + x.Bounds.Width / 2, x.Bounds.Bottom) - sourcePoint).Length <= snapRange + 10));
            //DiagramNode closestNode = allNodes.FirstOrDefault(x => (x.GetCenter() - sourcePoint).Length <= snapRange + 10);

            if (closestNode is BROperatorNode)
            {
                List<DiagramNode> availableOperators = allNodes.ToList();
                availableOperators.RemoveAll(x => ((BRNode)x).NodeType != BRNodeType.OPERATOR);
                availableOperators.Remove(this);
                BRNode leftCopy = leftConnectedNode;
                BRNode rightCopy = rightConnectedNode;
                while (leftCopy != null)
                {
                    availableOperators.Remove(leftCopy);
                    if (leftCopy is BROperatorNode)
                    {
                        leftCopy = ((BROperatorNode)leftCopy).leftConnectedNode;
                    }
                    else
                        break;
                }
                while (rightCopy != null)
                {
                    availableOperators.Remove(rightCopy);
                    if (rightCopy is BROperatorNode)
                    {
                        rightCopy = ((BROperatorNode)rightCopy).leftConnectedNode;
                    }
                    else
                        break;
                }
                closestNode = availableOperators.FirstOrDefault(x => ((((BROperatorNode)x).txtPosWithDiagramCoordinates - sourcePoint).Length <= snapRange + 10));
            }
            return closestNode;
        }
 



The operator itself should be able to nest but also align to other nodes which is why we use allNodes.FirstOrDefault(<predicate>). Now we're having difficulties giving a concise predicate for both operators and other nodes. We tried using GetCenter() for x but the center coordinate sometimes conflicts with where the slot is (see image below).



As seen in the code of our method we now use: x => ((new Point(x.Bounds.Left + x.Bounds.Width / 2, x.Bounds.Bottom) - sourcePoint).Length

This, however, does not work when an operator is dragged towards the operator slot in the node which can be seen in image below. Now we have to drop an operator near the bottom of that node for it to align to the operator slot.



How can we make sure the method searches for the correct child in an operator and at the same time for a regular node?

We would appreciate any ideas Wink

Greets,

Vincent
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Prioritising Mindfusions NearestNode
Reply #4 - Dec 9th, 2013 at 12:18pm
Print Post  
Hi,

Create some kind of Slot class with DiagramNode, index and position members:

Code
Select All
class Slot
{
  DiagramNode Node {get; set;}
  int Index {get; set;}
  Point Position {get; set;}
} 



Add a virtual GetAvailableSlots method to your base node class that returns Slot objects describing unoccupied slots, and implement it for all slotted nodes types. Last, change GetClosestNode to a GetClosestSlot method (returning Slot object), call allNodes 's GetAvailableSlots and collect results into a List<Slot>. Now you should be able to write nice queries on these slots, sort them by distance to Position, etc. Keep the returned closest slot as a targetSlot member, and later attach child nodes to targetSlot.Node.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Vincent
Junior Member
**
Offline


I Love MindFusion!

Posts: 62
Joined: Oct 3rd, 2013
Re: Prioritising Mindfusions NearestNode
Reply #5 - Dec 10th, 2013 at 10:17am
Print Post  
Yes, we were slightly hoping there would be a easy way to do it without adding such a class. But it works perfectly nonetheless!  Grin

Thanks for the input  Smiley

Greets,

Vincent
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint