import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;


public class CrossSection {
    private ArrayList<Node> nodes = null;
    private double sectionArea = 0.0;
    private double sectorialStaticMoment = 0.0;
    private double sectorialInertiaMoment = 0.0;
    private Point sectorialLinearStaticMoment = null;
    private Point inertiaMoment = null;
    private Point gravityCenter = null;
    private Point rigidityCenter = null;
    private Point pole = null;

    public CrossSection(ArrayList<Node> nodes) {
        this.nodes = connect(nodes);
    }

    public double getSectionArea() {
        return getSectionArea(true);
    }

    public double getSectionArea(boolean lazy) {
        if (sectionArea > 0 && lazy) {
            return sectionArea;
        }

        sectionArea = 0.0;
        traverseNodes(this.nodes.get(0), "sectionAreaCallback");

        return sectionArea;
    }

    private void sectionAreaCallback(Node node) {
        if (node.parent == null) return;

        double ds = node.distanceTo(node.parent);
        double thickness = 0.5 * (node.thickness + node.parent.thickness);
        sectionArea += thickness * ds;
    }

    public Point getGravityCenter() {
        return getGravityCenter(true);
    }

    public Point getGravityCenter(boolean lazy) {
        if (gravityCenter != null && lazy) {
            return gravityCenter;
        }

        gravityCenter = new Point();
        traverseNodes(this.nodes.get(0), "gravityCenterCallback");

        gravityCenter.x /= getSectionArea();
        gravityCenter.y /= getSectionArea();

        return gravityCenter;
    }

    private void gravityCenterCallback(Node node) {
        if (node.parent == null) return;

        double ds = node.distanceTo(node.parent);
        double thickness = 0.5 * (node.thickness + node.parent.thickness);

        gravityCenter.x += 0.5 * (
            node.x + node.parent.x
        ) * thickness * ds;

        gravityCenter.y += 0.5 * (
            node.y + node.parent.y
        ) * thickness * ds;
    }



    private void traverseNodes(Node rootNode, String methodName) {
        Method callback = null;

        try {
            callback = this.getClass().getMethod(methodName, Node.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return;
        }

        // ...

        try {
            callback.invoke(this, this.nodes.get(0));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private ArrayList<Node> connect(ArrayList<Node> nodes) {
        ArrayList<Node> connectedNodes = new ArrayList<Node>();
        ArrayList<Node> disconnectedNodes = new ArrayList<Node>(nodes);

        connectedNodes.add(disconnectedNodes.remove(nodes.size() - 1));

        while (disconnectedNodes.size() > 0) {
            double min_dist = Double.POSITIVE_INFINITY;
            Node d_node = null;
            Node c_node = null;

            for (Node c : connectedNodes) {
                for (Node d : disconnectedNodes) {
                    double dist = d.distanceTo(c);
                    if (dist < min_dist) {
                        min_dist = dist;
                        d_node = d;
                        c_node = c;
                    }
                }
            }

            c_node.connect(d_node);
            d_node.connect(c_node);

            connectedNodes.add(d_node);
            disconnectedNodes.remove(d_node);
        }

        return connectedNodes;
    }
}

@@ -1,20 +1,44 @@
+import java.util.Stack;%0A
 import java.util.Arr
@@ -916,18 +916,59 @@
 .get(0),
- %22
+%0A                      (Node node) -%3E this.
 sectionA
@@ -970,33 +970,38 @@
 tionAreaCallback
-%22
+(node)
 );%0A%0A        retu
@@ -1591,10 +1591,51 @@
 (0),
- %22
+%0A                      (Node node) -%3E this.
 grav
@@ -1655,9 +1655,14 @@
 back
-%22
+(node)
 );%0A%0A
@@ -2213,18 +2213,16 @@
 %0A    %7D%0A%0A
-%0A%0A
     priv
@@ -2263,52 +2263,91 @@
 de, 
-String methodName) %7B%0A        Method callback
+Callback callback) %7B%0A        for (Node node : this.nodes) %7B%0A            node.parent
  = n
@@ -2351,25 +2351,24 @@
 = null;%0A
-%0A
         
 try %7B%0A  
@@ -2351,37 +2351,34 @@
 = null;%0A        
-try %7B
+%7D%0A
 %0A            cal
@@ -2374,169 +2374,240 @@
     
-    callback = this.getClass().getMethod(methodName, Node.class);%0A        %7D catch (NoSuchMethodException e) %7B%0A            e.printStackTrace();%0A            return
+ArrayList%3CNode%3E visitedNodes = new ArrayList%3CNode%3E();%0A        Stack%3CNode%3E nodesToVisit = new Stack%3CNode%3E();%0A%0A        nodesToVisit.push(rootNode);%0A%0A        while (!nodesToVisit.empty()) %7B%0A            Node curNode = nodesToVisit.pop()
 ;%0A  
@@ -2616,26 +2616,45 @@
     
-%7D%0A%0A
     
-    // ...%0A
+for (Node node : curNode.links) %7B
 %0A   
@@ -2662,22 +2662,16 @@
     
-try %7B%0A
         
     
@@ -2670,290 +2670,238 @@
     
-    callback.invoke(this, this.nodes.get(0));%0A        %7D catch (IllegalArgumentException e) %7B%0A            e.printStackTrace();%0A        %7D catch (IllegalAccessException e) %7B%0A            e.printStackTrace();%0A        %7D catch (InvocationTargetException e) %7B%0A            e.printStackTrace(
+if (!visitedNodes.contains(node)) %7B%0A                    node.parent = curNode;%0A                    nodesToVisit.push(node);%0A                %7D%0A            %7D%0A            callback.invoke(curNode);%0A            visitedNodes.add(curNode
 );%0A 
@@ -3921,8 +3921,61 @@
     %7D%0A%7D%0A
+%0A%0Ainterface Callback %7B%0A    void invoke(Node node);%0A%7D%0A

use lambdas for callback mechanism, complete traverseNodes