SharpNeat.View.Graph.IOGraphPainter.PaintBackConnection C# (CSharp) Метод

PaintBackConnection() приватный Метод

private PaintBackConnection ( Pen pen, Point srcPos, Point tgtPos, ConnectionPointInfo srcInfo, ConnectionPointInfo tgtInfo, PaintState state ) : void
pen System.Drawing.Pen
srcPos Point
tgtPos Point
srcInfo ConnectionPointInfo
tgtInfo ConnectionPointInfo
state PaintState
Результат void
        private void PaintBackConnection(Pen pen,
                                         Point srcPos, 
                                         Point tgtPos,
                                         ConnectionPointInfo srcInfo,
                                         ConnectionPointInfo tgtInfo,
                                         PaintState state)
        {
            const float SlopeInit = 0.25f;
            const float SlopeIncr = 0.23f;

            // This is the maximum slope value we get before exceeding the slope threshold of 1.
            float slopeMax = SlopeInit + (SlopeIncr * (float)Math.Floor((1f-SlopeInit) / SlopeIncr));

            // Back connection is described by the line ABCDEF. A = srcPos and F = tgtPos.
            int srcConIdx, tgtConIdx;
            int srcSide, tgtSide;

            // If the source and target nodes are close on the X-axis then connect to the same side on both
            // nodes. Otherwise connect nodes on their facing sides.
            if(Math.Abs(tgtPos.X - srcPos.X) <= NodeDiameterModel) {
                srcConIdx = srcInfo._lowerLeft++;
                tgtConIdx = tgtInfo._upperLeft++;
                srcSide = -1;
                tgtSide = -1;
            }
            else if(tgtPos.X > srcPos.X) {
                srcConIdx = srcInfo._lowerRight++;
                tgtConIdx = tgtInfo._upperLeft++;
                srcSide = 1;
                tgtSide = -1;
            } else {
                srcConIdx = srcInfo._lowerLeft++;
                tgtConIdx = tgtInfo._upperRight++;
                srcSide = -1;
                tgtSide = 1;
            }

        //--- Point B.
            // The line AB is a connection leg emerging from the base of a node. To visually separate multiple legs
            // the first leg has a gentle gradient (almost horizontal) and each successive leg has a steeper gradient.
            // Once a vertical gradient has been reached each successive leg is made longer.
            // Calculate leg slope: 0=horizontal, 1=vertical. Hence this is value is not a gradient.
            // Slope pre-trimming back to maximum of 1.0.
            float slopePre = SlopeInit + (SlopeIncr * srcConIdx);

            // Leg length.
            float lenAB = state._backConnectionLegLength;
            float slope = slopePre;
            if(slope > slopeMax)  
            {   // Increase length in fractions of _backConnectionLegLength.
                lenAB += (slopePre-slopeMax) * state._backConnectionLegLength;
                slope = 1f;
            }

            // Calculate position of B as relative to A. 
            // Note. Length is taken to be L1 length (Manhattan distance). This means that the successive B positions 
            // describe a straight line (rather than the circle you get with L2/Euclidean distance) which in turn 
            // ensures that the BC segments of successive connections are evenly spaced out.
            int xDelta = (int)(lenAB * (1f - slope)) * srcSide;
            int yDelta = (int)(lenAB * slope);
            Point b = new Point(srcPos.X + xDelta, srcPos.Y + yDelta);

        //--- Point C.
            // Line BC is a horizontal line from the end of the leg AB.
            int lenBC = (int)(2f * slopePre * state._backConnectionLegLength);
            xDelta = lenBC * srcSide;
            Point c = new Point(b.X + xDelta, b.Y);

        //--- Point E. Equivalent to point B but emerging from the target node.
            slopePre = SlopeInit + (SlopeIncr * tgtConIdx);

            // Leg length.
            float lenEF = state._backConnectionLegLength;
            slope = slopePre;
            if(slope > slopeMax)  
            {   // Increase length in fractions of _backConnectionLegLength.
                lenEF += (slopePre-slopeMax) * state._backConnectionLegLength;
                slope = 1f;
            }

            xDelta = (int)(lenEF * (1f - slope)) * tgtSide;
            yDelta = -(int)(lenEF * slope);
            Point e = new Point(tgtPos.X + xDelta, tgtPos.Y + yDelta);

        //--- Point D. Equivalent to point C but on the target end of the connection.
            int lenDE = (int)(2f * slopePre * state._backConnectionLegLength);
            xDelta = lenDE * tgtSide;
            Point d = new Point(e.X + xDelta, e.Y);

            state._g.DrawLines(pen, new Point[]{srcPos,b,c,d,e,tgtPos});
        }