private ContourLine TrackUnclosedContour(int crtTriangle, enumEdgeType crtEdge, double contValue)
        {
            if (_triangleIsUsed.IsTrue(crtTriangle))
            {
                return(null);
            }
            ContourLine cntLine = new ContourLine(contValue);

            UpdateClassIndex(cntLine);
            enumEdgeType firstEdge     = crtEdge;
            int          firstTriangle = crtTriangle;

            enumEdgeType[] otherEdges = new enumEdgeType[2];
            int            edgeIdx    = ToEdgeIndex(crtTriangle, crtEdge);
            bool           edgeUsed   = _edgeIsUsed.IsTrue(edgeIdx);
            PointF         vpt        = TryGetVPoint(crtTriangle, crtEdge, contValue);

            if (vpt.IsEmpty || edgeUsed)
            {
                return(null);
            }
            _edgeIsUsed.SetStatus(edgeIdx, true);
            return(TrackClosedContourFromEdge(crtTriangle, crtEdge, contValue, vpt,
                                              (idx) => { return IsBorderTriangle(idx); }, 2));
        }
        private int GetNextTriangle(int crtTriangle, ref enumEdgeType crtEdge)
        {
            bool isRightTop = crtTriangle % 2 != 0;
            int  span       = (_gridWidth * 2 + 1);

            try
            {
                switch (crtEdge)
                {
                case enumEdgeType.A:
                    if (isRightTop)
                    {
                        crtTriangle = crtTriangle - span;
                    }
                    else
                    {
                        crtTriangle = crtTriangle + span;
                    }
                    break;

                case enumEdgeType.B:
                    if (isRightTop)
                    {
                        crtTriangle = crtTriangle + 1;
                    }
                    else
                    {
                        crtTriangle = crtTriangle - 1;
                    }
                    break;

                case enumEdgeType.C:
                    if (isRightTop)
                    {
                        crtTriangle = crtTriangle - 1;
                    }
                    else
                    {
                        crtTriangle = crtTriangle + 1;
                    }
                    break;
                }
            }
            finally
            {
                if (crtTriangle > _triangleCount - 1 || crtTriangle < 0)
                {
                    crtTriangle = -1;
                }
            }
            return(crtTriangle);
        }
        private int ToEdgeIndex(int crtTriangle, enumEdgeType crtEdge)
        {
            int  pixelRow     = crtTriangle / _triWidth;
            int  pixelCol     = crtTriangle % _triWidth / 2;
            bool isLeftBottom = crtTriangle % 2 == 0;
            int  idx          = 0;

            if (pixelRow == 0)
            {
                idx = _gridWidth + pixelCol * 3;
            }
            else
            {
                idx = pixelRow * (_gridWidth * 3 + 1) + _gridWidth + pixelCol * (_gridWidth - 1);
            }
            if (isLeftBottom)
            {
                switch (crtEdge)
                {
                case enumEdgeType.A:
                    return(idx + 1);

                case enumEdgeType.B:
                    return(idx);

                case enumEdgeType.C:
                    return(idx + 2);
                }
            }
            else
            {
                switch (crtEdge)
                {
                case enumEdgeType.A:
                    if (pixelRow == 0)
                    {
                        return(pixelCol);
                    }
                    else
                    {
                        return(idx - _gridWidth * 3);
                    }

                case enumEdgeType.B:
                    return(idx + 3);

                case enumEdgeType.C:
                    return(idx + 2);
                }
            }
            return(-1);
        }
 private void SetOthterEdges(enumEdgeType crtEdge, ref enumEdgeType[] otherEdges)
 {
     if (crtEdge == enumEdgeType.A)
     {
         otherEdges[0] = enumEdgeType.B;
         otherEdges[1] = enumEdgeType.C;
     }
     else if (crtEdge == enumEdgeType.B)
     {
         otherEdges[0] = enumEdgeType.A;
         otherEdges[1] = enumEdgeType.C;
     }
     else if (crtEdge == enumEdgeType.C)
     {
         otherEdges[0] = enumEdgeType.A;
         otherEdges[1] = enumEdgeType.B;
     }
 }
        /*
         * var factor = (float)((value - edge.P1.Value) / (edge.P2.Value - edge.P1.Value));
         * result.X = edge.P1.X + factor * (edge.P2.X - edge.P1.X);
         * result.Y = edge.P1.Y + factor * (edge.P2.Y - edge.P1.Y);
         */
        protected override PointF GetVPoint(enumEdgeType edgeType, int pixelIdxV1, int pixelIdxV2, double contValue)
        {
            float factor = (float)(contValue - _bandValues[pixelIdxV1]) / (_bandValues[pixelIdxV2] - _bandValues[pixelIdxV1]);
            int   y      = pixelIdxV1 / _width; //row
            int   x      = pixelIdxV1 % _width; //col

            switch (edgeType)
            {
            case enumEdgeType.A:
                return(new PointF(x + factor, y));

            case enumEdgeType.B:
                return(new PointF(x, y + factor));

            case enumEdgeType.C:
                return(new PointF(x + factor, y + factor));
            }
            return(PointF.Empty);
        }
 private bool IsBorderEdge(int idxTriangle, enumEdgeType edge)
 {
     if (idxTriangle % _triWidth == 0 && edge == enumEdgeType.B)                      //left
     {
         return(true);
     }
     else if ((idxTriangle + 1) % _triWidth == 0 && edge == enumEdgeType.B)           //right
     {
         return(true);
     }
     else if (idxTriangle / _triWidth == 0 && edge == enumEdgeType.A)                 //top
     {
         return(true);
     }
     else if (idxTriangle / _triWidth == _gridHeight - 1 && edge == enumEdgeType.A)   //bottom
     {
         return(true);
     }
     return(false);
 }
        private ContourLine TrackClosedContour(int crtTriangle, enumEdgeType crtEdge, double contValue)
        {
            if (_triangleIsUsed.IsTrue(crtTriangle))
            {
                return(null);
            }
            int          edgeIdx       = 0;
            enumEdgeType firstEdge     = crtEdge;
            int          firstTriangle = crtTriangle;

            enumEdgeType[] otherEdges = new enumEdgeType[2] {
                enumEdgeType.B, enumEdgeType.C
            };
            PointF vpt = PointF.Empty;

            vpt     = TryGetVPoint(crtTriangle, crtEdge, contValue);
            edgeIdx = ToEdgeIndex(crtTriangle, crtEdge);
            if (vpt.IsEmpty || _edgeIsUsed.IsTrue(edgeIdx))
            {
                for (int i = 0; i < 2; i++)
                {
                    crtEdge = otherEdges[i];
                    vpt     = TryGetVPoint(crtTriangle, crtEdge, contValue);
                    edgeIdx = ToEdgeIndex(crtTriangle, crtEdge);
                    if (!vpt.IsEmpty && !_edgeIsUsed.IsTrue(edgeIdx))
                    {
                        break;
                    }
                }
            }
            if (vpt.IsEmpty || _edgeIsUsed.IsTrue(edgeIdx))
            {
                //当前三角形三条边均不存在等值点,标记为已使用
                _triangleIsUsed.SetStatus(crtTriangle, true);
                return(null);
            }
            return(TrackClosedContourFromEdge(crtTriangle, crtEdge, contValue, vpt,
                                              (idx) => { return idx == firstTriangle || IsBorderTriangle(idx); }, 6));
        }
 protected abstract PointF GetVPoint(enumEdgeType edgeType, int pixelIdxV1, int pixelIdxV2, double contValue);
        private PointF TryGetVPoint(int crtTriangle, enumEdgeType crtEdge, double contValue)
        {
            int  pixelRow   = crtTriangle / _triWidth;
            int  pixelCol   = crtTriangle % _triWidth / 2;
            bool isRightTop = crtTriangle % 2 != 0;//是右上三角形

            if (isRightTop)
            {
                pixelCol += 1;
            }
            else
            {
                pixelRow += 1;
            }
            int pixelIdx = pixelRow * _width + pixelCol;
            int pixelIdxV1 = pixelIdx, pixelIdxV2 = pixelIdx;

            switch (crtEdge)
            {
            case enumEdgeType.A:
                if (isRightTop)
                {
                    pixelIdxV1 -= 1;
                }
                else
                {
                    pixelIdxV2 += 1;
                }
                break;

            case enumEdgeType.B:
                if (isRightTop)
                {
                    pixelIdxV2 += _width;
                }
                else
                {
                    pixelIdxV1 -= _width;
                }
                break;

            case enumEdgeType.C:
                if (isRightTop)
                {
                    pixelIdxV1 -= 1;
                    pixelIdxV2 += _width;
                }
                else
                {
                    pixelIdxV1 -= _width;
                    pixelIdxV2 += 1;
                }
                break;
            }
            if (!CheckIsContained(_bandValues[pixelIdxV1], _bandValues[pixelIdxV2], ToTValue(contValue)))
            {
                return(PointF.Empty);
            }
            PointF vpt = GetVPoint(crtEdge, pixelIdxV1, pixelIdxV2, contValue);

            //经过采样
            if (_sample > 1)
            {
                vpt.X *= _sample;
                vpt.Y *= _sample;
            }
            return(vpt);
        }
Exemple #10
0
        private ContourLine TrackClosedContourFromEdge(int crtTriangle, enumEdgeType crtEdge, double contValue, PointF vpt, Func <int, bool> isStop, int minPoints)
        {
            bool        isSharePointed = false;
            bool        edgeUsed       = false;
            ContourLine cntLine        = new ContourLine(contValue);

            UpdateClassIndex(cntLine);
            enumEdgeType[] otherEdges = new enumEdgeType[2];
            int            edgeIdx    = 0;
            bool           isClosed   = false;

            while (true)
            {
                //等值线进入当前三角形
                if (!isSharePointed)
                {
                    cntLine.AddPoint(vpt);
                }
                //查找等值线离开当前三角形的出口点
                SetOthterEdges(crtEdge, ref otherEdges);
                crtEdge  = otherEdges[0];
                edgeIdx  = ToEdgeIndex(crtTriangle, crtEdge);
                edgeUsed = _edgeIsUsed.IsTrue(edgeIdx);
                vpt      = !edgeUsed?TryGetVPoint(crtTriangle, crtEdge, contValue) : PointF.Empty;

                if (vpt.IsEmpty)//该边不包含等值点或者已被使用
                {
                    crtEdge  = otherEdges[1];
                    edgeIdx  = ToEdgeIndex(crtTriangle, crtEdge);
                    edgeUsed = _edgeIsUsed.IsTrue(edgeIdx);
                    vpt      = !edgeUsed?TryGetVPoint(crtTriangle, crtEdge, contValue) : PointF.Empty;

                    if (vpt.IsEmpty)//没有找到出口
                    {
                        break;
                    }
                    else
                    {
                        cntLine.AddPoint(vpt);
                        _edgeIsUsed.SetStatus(edgeIdx, true);
                    }
                }
                else
                {
                    cntLine.AddPoint(vpt);
                    _edgeIsUsed.SetStatus(edgeIdx, true);
                }
                //标记当前三角形已经使用
                _triangleIsUsed.SetStatus(crtTriangle, true);
                //查找当前三角形相连的三角形作为当前三角形
                crtTriangle = GetNextTriangle(crtTriangle, ref crtEdge);
                //退出条件
                if (crtTriangle == -1)
                {
                    break;
                }
                edgeIdx = ToEdgeIndex(crtTriangle, crtEdge);
                _edgeIsUsed.SetStatus(edgeIdx, false);//两个三角形的共享边标记为未使用
                if (isStop(crtTriangle))
                {
                    isClosed = true;
                    _edgeIsUsed.SetStatus(edgeIdx, true);
                    break;
                }
                if (_triangleIsUsed.IsTrue(crtTriangle))
                {
                    break;
                }
                isSharePointed = true;
            }
            if (_isOutputUncompleted)
            {
                return(cntLine.Count >= minPoints ? cntLine : null);
            }
            else
            {
                if (isClosed)
                {
                    return(cntLine.Count >= minPoints ? cntLine : null);
                }
                return(null);
            }
        }