}     // protected void collectWayToGoalLinear()

    //protected float differChangeRateBetweenVec3(Vector3 v3Way0, Vector3 v3Way1, Vector3 v3Way2)
    protected float differChangeRateBetweenVec3(Vector3 v3Edge01, Vector3 v3Edge02)
    {
        Vector2 v2Edge01 = CMATH.ConvertToV2_Y(v3Edge01);
        Vector2 v2Edge02 = CMATH.ConvertToV2_Y(v3Edge02);

        Vector2 v2Change01 = new Vector2(v2Edge01.sqrMagnitude, v3Edge01.y * v3Edge01.y);
        Vector2 v2Change02 = new Vector2(v2Edge02.sqrMagnitude, v3Edge02.y * v3Edge02.y);

        float fChangeRate01 = v2Change01.x / v2Change01.y;
        float fChangeRate02 = v2Change02.x / v2Change02.y;

        return(Mathf.Abs(fChangeRate02 - fChangeRate01));
    } // protected float differChangeRateBetweenVec3(Vector3 v3Way0, Vector3 v3Way1, Vector3 v3Way2)
    } // public bool intersectRay_inAdjs(int iSeqCell, Vector3 v3RayOrigin, Vector3 v3RayDir, ref Vector3 posIntersected_out)

    //@ Organize shortest way block edges only Current cell
    public bool setNaviPortal_forShortestWay(Vector2[] arrv2PntObjBoundary, ref CNAVICELL cellWayStart)
    {
        if (true == cellWayStart.useWaytoPortal)
        {
            return(true);
        }

        List <CNAVICELL> listSequenceCell = new List <CNAVICELL>();

        collectWayToGoalLinear(m_arrNavicells, cellWayStart, ref listSequenceCell, ref m_computeEdgeBlock);
        if (listSequenceCell.Count < 2)
        {
            return(true);
        }


        Vector3 v3PntPrev = new Vector3();
        Vector3 v3PntCurr = new Vector3();
        Vector3 v3PntNext = new Vector3();

        int       iLenSeq = listSequenceCell.Count;
        int       iSeqIteration = 0;
        CNAVICELL cellGOAL = listSequenceCell[iLenSeq - 1];
        CNAVICELL cellNext, cellPrev;

        bool bCrosswithBlock       = false;
        bool bSetNewPortalPosition = false;

        Vector3[] arrv3Pnt_Cell_start = new Vector3[cellWayStart.m_arrv3PT.Length];
        Array.Copy(cellWayStart.m_arrv3PT, arrv3Pnt_Cell_start, cellWayStart.m_arrv3PT.Length);
        CMATH.rescaleVertices(ref arrv3Pnt_Cell_start, DFLT_ADJUST_SCALE_FOR_VISIBLECHECK);

        foreach (CNAVICELL cellCurr in listSequenceCell)
        {
            int iSeqCurr = iSeqIteration++;

            if (0 == iSeqCurr)
            {
                continue;
            }

            if (cellGOAL == cellCurr)
            {
                cellWayStart.SetPortalPosition(cellGOAL.seqCell, cellGOAL.getPos_cellCenter());
                bSetNewPortalPosition = true;
                break;
            }

            cellPrev = listSequenceCell[iSeqCurr - 1];
            cellNext = listSequenceCell[iSeqCurr + 1];

            cellCurr.getPos_BestWay_onEdge(ref v3PntCurr);
            cellNext.getPos_BestWay_onEdge(ref v3PntNext);
            cellPrev.getPos_BestWay_onEdge(ref v3PntPrev);

            bCrosswithBlock = false;
            foreach (Vector3 v3PntCell in arrv3Pnt_Cell_start)
            {
                if (m_computeEdgeBlock.crossBlockIteration(v3PntCell, v3PntNext))
                {
                    bCrosswithBlock = true;
                    break;
                }
            }

            //@ Set Portal
            if (true == bCrosswithBlock)
            {
                cellWayStart.SetPortalPosition(cellCurr.seqCell, v3PntCurr);

                bSetNewPortalPosition = true;
                break;
            }

            Vector2 v2PntNext = CMATH.ConvertToV2_Y(v3PntNext);
            foreach (Vector2 v2PntObj in arrv2PntObjBoundary)
            {
                //@ Cross At least 1 mo
                if (true == m_computeEdgeBlock.crossBlockIteration(v2PntObj, v2PntNext))
                {
                    bCrosswithBlock = true;
                    break;
                }
            }

            //@ Set Portal -2
            if (true == bCrosswithBlock)
            {
                cellWayStart.SetPortalPosition(cellCurr.seqCell, v3PntCurr);

                bSetNewPortalPosition = true;
                break;
            }
        } // foreach (CNAVICELL cellCurr in listSequenceCell)

        listSequenceCell.Clear();
        listSequenceCell = null;

        return(bSetNewPortalPosition);
    } // public bool setNaviPortal_forShortestWay(int iSeqCell)