コード例 #1
0
ファイル: nurbsInterface.cs プロジェクト: liulei2776/Mothra5
        void createNurbsElements(branch branch)
        {
            double[] uKnot;

            int N = branch.N;
            int uDim = branch.crv.Order;
            int uDdim = branch.crv.Order - 1;
            uKnot = new double[branch.N - uDdim + 1 + uDdim * 2];
            for (int i = 0; i < uDdim; i++)
            {
                uKnot[i] = 0;
            }
            for (int i = 0; i < branch.N - uDdim + 1; i++)
            {
                uKnot[i + uDdim] = i;
            }
            for (int i = 0; i < uDdim; i++)
            {
                uKnot[i + branch.N + 1] = branch.N - uDdim;
            }
            branch.myArch=new Minilla3D.Objects.arch();
            int[] index = new int[uDim];
            for (int i = 1; i < branch.N - uDdim+1; i++)
            {
                for (int l = 0; l < uDim; l++)
                {
                    index[l] = i - 1 + l;
                }
                branch.myArch.elemList.Add(new Minilla3D.Elements.nurbsCurve(uDim, index, i, uKnot));
            }
        }
コード例 #2
0
ファイル: Numerics.cs プロジェクト: liulei2776/Mothra5
 public void defineKinkAngle2(branch branch, leaf leaf1, leaf leaf2, mosek.Task task, int numCon, int numVar)
 {
     for (int t = 0; t < branch.tuples.Count(); t++)
     {
         task.putaij(numCon + t, numVar + t, -1);
         task.putconbound(numCon + t, mosek.boundkey.fx, 0, 0);
         var tup = branch.tuples[t];
         for (int h = 0; h < 2; h++)
         {
             Minilla3D.Elements.nurbsElement.tuple target = null;
             leaf leaf = null;
             if (h == 0) { target = tup.left; leaf = leaf1; }
             if (h == 1) { target = tup.right; leaf = leaf2; }
             target.dcdtstar[0] = target.dcdt[1];
             target.dcdtstar[1] = -target.dcdt[0];
             double gamma = 0;
             for (int i = 0; i < 2; i++)
             {
                 for (int j = 0; j < 2; j++)
                 {
                     gamma += target.dcdt[i] * target.gij[i, j] * target.dcdt[j];
                     gamma += target.dcdt[i] * target.gij[i, j] * target.dcdt[j];
                 }
             }
             for (int k = 0; k < target.nNode; k++)
             {
                 for (int i = 0; i < 2; i++)
                 {
                     target.s[i] = target.d1[i][k];
                 }
                 var val = 0d;
                 for (int i = 0; i < 2; i++)
                 {
                     for (int j = 0; j < 2; j++)
                     {
                         val += target.s[i] * target.Gij[i, j] * target.dcdtstar[j];
                     }
                 }
                 val *= target.refDv;
                 val /= Math.Sqrt(gamma);
                 task.putaij(numCon + t, target.internalIndex[k] + leaf.varOffset, val);
             }
         }
     }
 }
コード例 #3
0
ファイル: Numerics.cs プロジェクト: liulei2776/Mothra5
 public void defineKinkAngle(branch branch,leaf leaf,mosek.Task task, int numCon, int numVar)
 {
     //todo add valDc//
     for (int t= 0; t < branch.tuples.Count(); t++)
     {
         task.putaij(numCon + t, numVar + t, -1);
         task.putconbound(numCon + t, mosek.boundkey.fx, 0, 0);
         var tup = branch.tuples[t];
         var target = tup.target;
         target.dcdtstar[0] = target.dcdt[1];
         target.dcdtstar[1] = -target.dcdt[0];
         double gamma = 0;
         for (int i = 0; i < 2; i++)
         {
             for (int j = 0; j < 2; j++)
             {
                 gamma += target.dcdt[i] * target.gij[i, j] * target.dcdt[j];
             }
         }
         for (int k = 0; k < target.nNode; k++)
         {
             for (int i = 0; i < 2; i++)
             {
                 target.s[i] =target.d1[i][k];
             }
             var val = 0d;
             for (int i = 0; i < 2; i++)
             {
                 for (int j = 0; j < 2; j++)
                 {
                     val += target.s[i] * target.Gij[i, j] * target.dcdtstar[j];
                 }
             }
             val *= target.refDv;
             val /= Math.Sqrt(gamma);
             task.putaij(numCon + t, target.internalIndex[k] + leaf.varOffset, val);
         }
     }
 }
コード例 #4
0
ファイル: Numerics.cs プロジェクト: liulei2776/Mothra5
        public void tieBranchD3(branch branch, leaf leaf, mosek.Task task, int num0/*1 or 2*/, int num1/*0 or 1*/)
        {
            if (leaf.branch[0] == branch)
            {
                if (leaf.nU == branch.N)
                {
                    for (int i = 0; i < branch.N; i++)
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            task.putconbound((i * num0 + num1) * 3 + k + branch.conOffset, mosek.boundkey.fx, 0, 0);
                            if (leaf.flip[0])
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, ((branch.N - 1 - i) * 3 + k) + leaf.varOffset, -1);
                            }
                            else
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + leaf.varOffset, -1);
                            }
                        }
                    }
                }
            }
            if (leaf.branch[1] == branch)
            {
                if (leaf.nV == branch.N)
                {
                    for (int i = 0; i < branch.N; i++)
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            task.putconbound((i * num0 + num1) * 3 + k + branch.conOffset, mosek.boundkey.fx, 0, 0);
                            if (leaf.flip[1])
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * (branch.N - i) - 1) * 3 + k + leaf.varOffset, -1);
                            }
                            else
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * (i + 1) - 1) * 3 + k + leaf.varOffset, -1);
                            }
                        }
                    }
                }
            }
            if (leaf.branch[2] == branch)
            {
                if (leaf.nU == branch.N)
                {
                    for (int i = 0; i < branch.N; i++)
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            task.putconbound((i * num0 + num1) * 3 + k + branch.conOffset, mosek.boundkey.fx, 0, 0);
                            if (leaf.flip[2])
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * (leaf.nV - 1) + (branch.N - 1 - i)) * 3 + k + leaf.varOffset, -1);
                            }
                            else
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * (leaf.nV - 1) + i) * 3 + k + leaf.varOffset, -1);
                            }
                        }
                    }
                }
            }

            if (leaf.branch[3] == branch)
            {
                if (leaf.nV == branch.N)
                {
                    for (int i = 0; i < branch.N; i++)
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            task.putconbound((i * num0 + num1)*3+k + branch.conOffset, mosek.boundkey.fx, 0, 0);
                            if (leaf.flip[3])
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * (branch.N - 1 - i)) * 3 + k + leaf.varOffset, -1);
                            }
                            else
                            {
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (i) * 3 + k + branch.varOffset, 1);
                                task.putaij(branch.conOffset + (i * num0 + num1) * 3 + k, (leaf.nU * i) * 3 + k + leaf.varOffset, -1);
                            }
                        }
                    }
                }
            }
        }
コード例 #5
0
ファイル: nurbsMasonry.cs プロジェクト: liulei2776/Mothra5
    protected override void SolveInstance(Grasshopper.Kernel.IGH_DataAccess DA)
    {
        init();
            _listSrf = new List<Surface>();
            _listCrv = new List<Curve>();
            listPnt = new List<Point3d>();
            List<string> crvTypes = new List<string>();
            List<string> pntHeights = new List<string>();
            if (!DA.GetDataList(0, _listSrf)) { return; }
            if (!DA.GetDataList(1, _listCrv)) { return; }
            if (!DA.GetDataList(2, crvTypes)) { return; }
            if (!DA.GetDataList(3, listPnt)) { listPnt.Clear(); }
            if (!DA.GetData(4, ref globalC)) { return; }

            if (_listCrv.Count != crvTypes.Count) { AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Error, "need types for curves"); return; }

            listSlice = new Dictionary<string, slice>();
            listSlice2 = new Dictionary<string, slice2>();
            listRange = new Dictionary<string, range>();
            listRangeOpen = new Dictionary<string, range>();
            listRangeLeaf = new Dictionary<string, range>();
            listLeaf = new List<leaf>();
            listBranch = new List<branch>();
            listNode=new List<node>();
            myControlBox.clearSliders();
            for (int i = 0; i < _listCrv.Count; i++)
            {
                var branch = new branch();
                branch.crv = _listCrv[i] as NurbsCurve;
                branch.N = branch.crv.Points.Count;
                branch.dom = branch.crv.Domain;
                branch.Dim= branch.crv.Order;
                branch.dDim = branch.crv.Order - 1;
                branch.nElem = branch.N - branch.dDim;
                branch.scaleT = (branch.dom.T1 - branch.dom.T0) / branch.nElem;
                branch.originT = branch.dom.T0;
                if(crvTypes[i].StartsWith("reinforce"))
                {
                    branch.branchType = branch.type.reinforce;
                    var key=crvTypes[i].Replace("reinforce","");
                    branch.sliceKey=key;
                    try{
                        branch.slice=listSlice[key];
                        branch.slice.sliceType = slice.type.fr;
                        branch.slice.lB.Add(branch);
                    }
                    catch (KeyNotFoundException e){
                        listSlice[key]=new slice();
                        branch.slice=listSlice[key];
                        branch.slice.sliceType=slice.type.fr;
                        branch.slice.lB.Add(branch);
                    }
                }
                else if(crvTypes[i].StartsWith("kink"))
                {
                    branch.branchType = branch.type.kink;
                    var key = crvTypes[i].Replace("kink", "");
                    if (key == "") key = "kink"; else key = "kink:" + key;
                    branch.sliceKey = key;
                    try
                    {
                        branch.range = listRange[key];
                        branch.range.rangeType = range.type.lo;
                        branch.range.lb = 0;
                        branch.range.ub = 0;
                        branch.range.lB.Add(branch);

                    }
                    catch (KeyNotFoundException)
                    {
                        listRange[key] = new range();
                        branch.range = listRange[key];
                        branch.range.rangeType = range.type.lo;
                        branch.range.lb = 0;
                        branch.range.ub = 0;
                        branch.range.lB.Add(branch);
                        var adjuster = myControlBox.addRangeSetter(key, (th,sw, lb, ub) =>
                        {
                            if (listRange[key].firstPathDone)
                            {
                                th.setMeasured(listRange[key].lastMin,listRange[key].lastMax);
                            }
                            foreach (var _branch in listRange[key].lB)
                            {
                                if (sw == 0)
                                {
                                    _branch.range.rangeType = range.type.lo;
                                    _branch.range.lb = lb;
                                    _branch.range.ub = 0d;
                                }
                                if (sw == 2)
                                {
                                    _branch.range.rangeType = range.type.ra;
                                    _branch.range.lb = lb;
                                    _branch.range.ub = ub;
                                }
                            }
                        }
                         );
                    }

                }else if(crvTypes[i].StartsWith("open"))
                {
                    branch.branchType = branch.type.open;
                    var key = crvTypes[i].Replace("open", "");
                    if (key == "") key = "open"; else key = "open:" + key;
                    branch.sliceKey = key;
                    try
                    {
                        branch.slice = listSlice[key];
                        branch.slice.sliceType = slice.type.fr;
                        branch.slice.lB.Add(branch);
                    }
                    catch (KeyNotFoundException e)
                    {
                        listSlice[key] = new slice();
                        branch.slice = listSlice[key];
                        branch.slice.sliceType = slice.type.fr;
                        branch.slice.lB.Add(branch);
                    }
                    try
                    {
                        branch.range = listRangeOpen[key];
                        branch.range.rangeType = range.type.lo;
                        branch.range.lb = 0;
                        branch.range.ub = 0;
                        branch.range.lB.Add(branch);
                    }
                    catch (KeyNotFoundException)
                    {
                        listRangeOpen[key] = new range();
                        branch.range = listRangeOpen[key];
                        branch.range.rangeType = range.type.lo;
                        branch.range.lb = 0;
                        branch.range.ub = 0;
                        branch.range.lB.Add(branch);
                        var adjuster = myControlBox.addRangeSetter(key, (th,sw, lb, ub) =>
                        {
                            if (listRangeOpen[key].firstPathDone)
                            {
                                th.setMeasured(listRangeOpen[key].lastMin,listRangeOpen[key].lastMax);
                            }
                            foreach (var _branch in listRangeOpen[key].lB)
                            {
                                if (sw == 0)
                                {
                                    _branch.range.rangeType = range.type.lo;
                                    _branch.range.lb = lb;
                                    _branch.range.ub = 0d;
                                }
                                if (sw == 2)
                                {
                                    _branch.range.rangeType = range.type.ra;
                                    _branch.range.lb = lb;
                                    _branch.range.ub = ub;
                                }
                            }
                        }
                            );
                    }
                }
                else if (crvTypes[i].StartsWith("fix"))
                {
                    branch.branchType = branch.type.fix;
                    var key = crvTypes[i].Replace("fix", "");
                    branch.sliceKey = key;
                    try
                    {
                        branch.slice2 = listSlice2[key];
                    }
                    catch (KeyNotFoundException e)
                    {
                        listSlice2[key] = new slice2();
                        branch.slice2 = listSlice2[key];

                        var slider = myControlBox.addSliderVert(0, 1, 200, 100);
                        slider.Converter = (val) =>
                            {
                                double height = val / 10d - 10d;
                                branch.slice2.height = height;
                                this.ExpirePreview(true);
                                return height;
                            };
                    }
                }else{
                        AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Error, "type should be either of reinforce, kink, fix, or open");
                }
                listBranch.Add(branch);
            }

            for(int i=0;i<_listSrf.Count;i++)
            {
                var srf = _listSrf[i];
                var leaf=new leaf();
                listLeaf.Add(leaf);
                leaf.srf = srf as NurbsSurface;
                leaf.nU = leaf.srf.Points.CountU;
                leaf.nV = leaf.srf.Points.CountV;
                leaf.domU = leaf.srf.Domain(0);
                leaf.domV = leaf.srf.Domain(1);
                leaf.uDim = leaf.srf.OrderU;
                leaf.vDim = leaf.srf.OrderV;
                leaf.uDdim = leaf.srf.OrderU - 1;
                leaf.vDdim = leaf.srf.OrderV - 1;
                leaf.nUelem = leaf.nU - leaf.uDdim;
                leaf.nVelem = leaf.nV - leaf.vDdim;
                leaf.scaleU = (leaf.domU.T1 - leaf.domU.T0) / leaf.nUelem;
                leaf.scaleV = (leaf.domV.T1 - leaf.domV.T0) / leaf.nVelem;
                leaf.originU = leaf.domU.T0;
                leaf.originV = leaf.domV.T0;
                var domainU = leaf.srf.Domain(0);
                var domainV = leaf.srf.Domain(1);
                //Find corresponding curve
                //(0,0)->(1,0)
                var curve = leaf.srf.IsoCurve(0, domainV.T0) as NurbsCurve;
                leaf.flip[0] = findCurve(leaf,ref leaf.branch[0], listBranch, curve);//bottom
                //(1,0)->(1,1)
                curve = leaf.srf.IsoCurve(1, domainU.T1) as NurbsCurve;
                leaf.flip[1] = findCurve(leaf, ref leaf.branch[1], listBranch, curve);//right
                //(1,1)->(0,1)
                curve = leaf.srf.IsoCurve(0, domainV.T1) as NurbsCurve;
                leaf.flip[2] = findCurve(leaf, ref leaf.branch[2], listBranch, curve);//top
                //(0,1)->(0,0)
                curve = leaf.srf.IsoCurve(1, domainU.T0) as NurbsCurve;
                leaf.flip[3] = findCurve(leaf, ref leaf.branch[3], listBranch, curve);//left

                var key = "leaf";
                try
                {
                    leaf.range = listRangeLeaf[key];
                    leaf.range.rangeType = range.type.lo;
                    leaf.range.lb = 0;
                    leaf.range.ub = 0;
                    leaf.range.lL.Add(leaf);
                }
                catch (KeyNotFoundException)
                {
                    listRangeLeaf[key] = new range();
                    leaf.range = listRangeLeaf[key];
                    leaf.range.rangeType = range.type.lo;
                    leaf.range.lb = 0;
                    leaf.range.ub = 0;
                    leaf.range.lL.Add(leaf);
                    var adjuster = myControlBox.addRangeSetter(key, (th, sw, lb, ub) =>
                    {
                        if (listRangeLeaf[key].firstPathDone)
                        {
                            th.setMeasured(listRangeLeaf[key].lastMin, listRangeLeaf[key].lastMax);
                        }
                        foreach (var _leaf in listRangeLeaf[key].lL)
                        {
                            if (sw == 0)
                            {
                                _leaf.range.rangeType = range.type.lo;
                                _leaf.range.lb = lb;
                                _leaf.range.ub = 0d;
                            }
                            if (sw == 2)
                            {
                                _leaf.range.rangeType = range.type.ra;
                                _leaf.range.lb = lb;
                                _leaf.range.ub = ub;
                            }
                        }
                    }
                     );
                }

            }
            // Connect nodes
            foreach (var leaf in listLeaf)
            {
                leaf.globalIndex = new int[leaf.srf.Points.CountU * leaf.srf.Points.CountV];
                for (int j = 0; j < leaf.srf.Points.CountV; j++)
                {
                    for (int i = 0; i < leaf.srf.Points.CountU; i++)
                    {
                        var P = leaf.srf.Points.GetControlPoint(i, j).Location;
                        bool flag = false;
                        foreach (var node in listNode)
                        {
                            if (node.compare(P))
                            {
                                flag = true;
                                node.N++;
                                node.shareL.Add(leaf);
                                node.numberL.Add(i + j * leaf.nU);
                                leaf.globalIndex[i + j * leaf.nU] = listNode.IndexOf(node);
                                break;
                            }
                        }
                        if (!flag)
                        {
                            var newNode = new node();
                            listNode.Add(newNode);
                            newNode.N = 1;
                            newNode.x = P.X;
                            newNode.y = P.Y;
                            newNode.z = P.Z;
                            newNode.shareL.Add(leaf);
                            newNode.numberL.Add(i + j * leaf.nU);
                            leaf.globalIndex[i + j * leaf.nU] = listNode.IndexOf(newNode);
                        }
                    }
                }
            }
            foreach (var branch in listBranch)
            {
                branch.globalIndex = new int[branch.crv.Points.Count];
                for (int i = 0; i < branch.crv.Points.Count; i++)
                {
                    var P = branch.crv.Points[i].Location;
                    bool flag = false;
                    foreach (var node in listNode)
                    {
                        if (node.compare(P))
                        {
                            flag = true;
                            node.N++;
                            node.shareB.Add(branch);
                            node.numberB.Add(i);
                            if (branch.branchType == branch.type.fix)
                            {
                                node.nodeType = node.type.fx;
                            }
                            branch.globalIndex[i] = listNode.IndexOf(node);
                            break;
                        }
                    }
                    if (!flag)
                    {
                        var newNode = new node();
                        listNode.Add(newNode);
                        newNode.N = 1;
                        newNode.shareB.Add(branch);
                        newNode.numberB.Add(i);
                        newNode.x = P.X;
                        newNode.y = P.Y;
                        newNode.z = P.Z;
                        if (branch.branchType == branch.type.fix)
                        {
                            newNode.nodeType = node.type.fx;
                        }
                        branch.globalIndex[i] = listNode.IndexOf(newNode);
                    }
                }
            }
            //multiqudric surface
            var A=new Rhino.Geometry.Matrix(listPnt.Count,listPnt.Count);
            var z=new Rhino.Geometry.Matrix(listPnt.Count,1);
            for(int i=0;i<listPnt.Count;i++)
            {
                for(int j=0;j<listPnt.Count;j++)
                {
                    var pi=listPnt[i];
                    var pj=listPnt[j];
                    A[i,j]=quadFunc(pi.X,pj.X,pi.Y,pj.Y);
                    z[i,0]=pi.Z;
                }
            }
            A.Invert(0.0);  //this parameter should be 0.0
            var c=A*z;
            globalCoeff=new double[listPnt.Count];
            for(int i=0;i<listPnt.Count;i++)
            {
                globalCoeff[i]=c[i,0];
            }
            targetSrf=new List<Point3d>();
            globalFunc=(xi,yi)=>{
                double Z=0;
                for(int j=0;j<listPnt.Count;j++)
                {
                    Z=Z+globalCoeff[j]*quadFunc(xi,listPnt[j].X,yi,listPnt[j].Y);
                }
                return Z;
                };
            foreach (var leaf in listLeaf)
            {
                var domU = leaf.domU;
                var domV = leaf.domV;
                for (double i = 0; i <= 1.0; i += 0.05)
                {
                    for (double j = 0; j < 1.0; j += 0.05)
                    {
                        double u = domU[0] + i * (domU[1] - domU[0]);
                        double v = domV[0] + j * (domV[1] - domV[0]);
                        Rhino.Geometry.Point3d P;
                        Rhino.Geometry.Vector3d[] V;
                        leaf.srf.Evaluate(u, v, 0, out P, out V);
                        var newP = new Rhino.Geometry.Point3d(P.X, P.Y, globalFunc(P.X, P.Y));
                        targetSrf.Add(newP);
                    }
                }
            }
    }
コード例 #6
0
ファイル: nurbsMasonry.cs プロジェクト: liulei2776/Mothra5
    public bool findCurve(leaf leaf,ref branch target, List<branch> listBranch, NurbsCurve curve)
    {
        var Points = curve.Points;
            var rPoints = curve.Points.Reverse().ToList();

            foreach (var branch in listBranch)
            {
                if (branch.crv.Points[0].Location.DistanceTo(Points[0].Location) < 0.0001)
                {
                    if (branch.crv.Points[1].Location.DistanceTo(Points[1].Location) < 0.0001)
                    {
                        target = branch;
                        if (branch.branchType != branch.type.kink)
                        {
                            branch.target = leaf;
                        }
                        else
                        {
                            if (branch.left == null) branch.left = leaf; else branch.right = leaf;
                        }
                        return false;
                    }
                }
                else if (branch.crv.Points[0].Location.DistanceTo(rPoints[0].Location) < 0.0001)
                {
                    if (branch.crv.Points[1].Location.DistanceTo(rPoints[1].Location) < 0.0001)
                    {
                        target = branch;
                        if (branch.branchType != branch.type.kink)
                        {
                            branch.target = leaf;
                        }
                        else
                        {
                            if (branch.left == null) branch.left = leaf; else branch.right = leaf;
                        }
                        return true;
                    }
                }
            }
            ttt++;
            AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Error, "cannot find:"+ttt.ToString());
            listError.Add(curve);
            return false;
    }
コード例 #7
0
ファイル: nurbsMasonry.cs プロジェクト: liulei2776/Mothra5
    public void tieBranch2(branch branch, leaf leaf)
    {
        int T0 = 0, T1 = 0;

            for (int s = 0; s < 4; s++)
            {
                if (s == 0)
                {
                    T0 = 0; T1 = (leaf.nUelem*leaf.NN) - 1;
                }
                if (s == 1)
                {
                    T0 = (leaf.nUelem*leaf.NN); T1 = (leaf.nUelem + leaf.nVelem)*leaf.NN - 1;
                }
                if (s == 2)
                {
                    T0 = (leaf.nUelem + leaf.nVelem)*leaf.NN; T1 = (leaf.nUelem * 2 + leaf.nVelem)*leaf.NN - 1;
                }
                if (s == 3)
                {
                    T0 = (leaf.nUelem * 2 + leaf.nVelem)*leaf.NN; T1 = (leaf.nUelem * 2 + leaf.nVelem * 2)*leaf.NN - 1;
                }
                if (leaf.branch[s] == branch)//s=0:bottom, s=1:right, s=2:top, s=3:left
                {
                    int N = 0;
                    if (s == 0 || s == 2) N = leaf.nU; else N = leaf.nV;
                    if (N == branch.N)
                    {
                        for (int i = 0; i < branch.nElem*branch.NN; i++)
                        {
                            if (leaf.flip[s])
                            {
                                if (branch.left == leaf)
                                    branch.tuples[i].left = leaf.edgeTuples[T1 - i];
                                if (branch.right == leaf)
                                    branch.tuples[i].right = leaf.edgeTuples[T1 - i];
                                if (branch.target == leaf)
                                    branch.tuples[i].target = leaf.edgeTuples[T1 - i];
                            }
                            else
                            {
                                if (branch.left == leaf)
                                    branch.tuples[i].left = leaf.edgeTuples[T0 + i];
                                if (branch.right == leaf)
                                    branch.tuples[i].right = leaf.edgeTuples[T0 + i];
                                if (branch.target == leaf)
                                    branch.tuples[i].target = leaf.edgeTuples[T0 + i];
                            }
                        }
                    }
                    else { AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Error, "cannot tie"); }
                }
            }
    }