// #define NOMINMAX

#include "stdafx.h"
#include <malloc.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
#include <iostream>
#include "RastrTool.h"

typedef struct _tag_DSCR_CHECKED_POLY
{
  long *pListCrd;
  long iCurPnt;
  long nmbPnt;
} DSCR_CHECKED_POLY;

int NextPointInPoly (long *pX, long *pY, void* pParam)
{
  DSCR_CHECKED_POLY *pDscrPoly = (DSCR_CHECKED_POLY *)pParam;
  if (pDscrPoly->iCurPnt >= pDscrPoly->nmbPnt)
    return 0;
  *pX = pDscrPoly->pListCrd[pDscrPoly->iCurPnt * 2];
  *pY = pDscrPoly->pListCrd[pDscrPoly->iCurPnt * 2 + 1];
  pDscrPoly->iCurPnt++;
  return 1;
}

inline double _len(double dx, double dy)
{
  if (fabs(dx) < 0.0001 && fabs(dy) < 0.0001)
    return 0;
  return sqrt(dx * dx + dy * dy);
}

CRastrTool::CRastrTool()
{
  m_pDscrSeg = NULL;
  m_nmbDscrSeg = 0;
  m_pStarts = NULL;
  m_nmbStarts = 0;
  m_pPoints = NULL;
  m_nmbPoints = 0;
  m_pPolys = NULL;
  m_nmbPolys = 0;
  m_bNewLine = true;
  m_pOutPnt = NULL;
  m_pOutPolys = NULL;
  m_pInfoPolyList = NULL;
  m_sostScan = SCAN_EMPTY;
  m_iBegDscr1 = 0;
  m_iBegDscr2 = 0;
  m_iBegDscr3 = 0;
}

CRastrTool::~CRastrTool()
{
  Reset();
}

void CRastrTool::Reset()
{
  ::free(m_pDscrSeg);
  m_pDscrSeg = NULL;
  ::free(m_pStarts);
  m_pStarts = NULL;
  ::free(m_pPoints);
  m_pPoints = NULL;
  ::free(m_pPolys);
  m_pPolys = NULL;
  ::free(m_pOutPnt);
  m_pOutPnt = NULL;
  ::free(m_pOutPolys);
  m_pOutPolys = NULL;
  ::free(m_pInfoPolyList);
  m_pInfoPolyList = NULL;

  m_bNewLine = true;
  m_nmbDscrSeg = 0;
  m_nmbStarts = 0;
  m_nmbPoints = 0;
  m_nmbPolys = 0;
};

TYPE_CROSSES CRastrTool::GetTypeCrs(long x1, long x2, long x1l, long x2l)
{
  if (x1 < x1l)
  {
    if (x2 <= x1l)
      return CRS_LEFT_LESS_RIGHT_LESS;
    if (x2 <= x2l)
      return CRS_LEFT_LESS_RIGHT_INSIDE;
    return CRS_LEFT_LESS_RIGHT_MORE;
  }
  if (x1 >= x2l)
    return  CRS_LEFT_MORE_RIGHT_MORE;
  if (x2 <= x2l)
    return CRS_LEFT_INSIDE_RIGHT_INSIDE;
  return CRS_LEFT_INSIDE_RIGHT_MORE;
}

bool CRastrTool::AddDscrSeg(long y, long xLeft, long xRight)
{
  if (xLeft >= xRight)
    return false;
  if ((m_nmbDscrSeg % 100) == 0)
    m_pDscrSeg = (DSCR_SEGMENT *)::realloc(m_pDscrSeg, sizeof(DSCR_SEGMENT) * (100 + m_nmbDscrSeg)); 
  long iDscr = m_nmbDscrSeg++;
  bool bNewLine = m_bNewLine;
  m_bNewLine = false;
  m_pDscrSeg[iDscr].y = y;

  m_pDscrSeg[iDscr].pntL.x = xLeft;
  m_pDscrSeg[iDscr].pntL.iFrom = -1;
  m_pDscrSeg[iDscr].pntL.iTo = -1;
  m_pDscrSeg[iDscr].pntL.bRightFrom = false;
  m_pDscrSeg[iDscr].pntL.bRightTo = false;
  m_pDscrSeg[iDscr].pntL.bProc = false;

  m_pDscrSeg[iDscr].pntR.x = xRight;
  m_pDscrSeg[iDscr].pntR.iFrom = -1;
  m_pDscrSeg[iDscr].pntR.iTo = -1;
  m_pDscrSeg[iDscr].pntR.bRightFrom = false;
  m_pDscrSeg[iDscr].pntR.bRightTo = false;
  m_pDscrSeg[iDscr].pntR.bProc = false;

  switch (m_sostScan)
  {
    case SCAN_EMPTY:
    {
      m_iBegDscr1 = -1;
      m_iBegDscr2 = -1;
      m_iBegDscr3 = iDscr;
      m_sostScan = SCAN_FIRST_LINE;
    } break;
    case SCAN_FIRST_LINE:
    {
      if (!bNewLine && m_pDscrSeg[iDscr].y == m_pDscrSeg[m_iBegDscr3].y)
      {
        if (m_pDscrSeg[iDscr - 1].pntR.x >= xLeft)
          return false;
        return true;
      }
      m_iBegDscr1 = m_iBegDscr2;
      m_iBegDscr2 = m_iBegDscr3;
      m_iBegDscr3 = iDscr; 
      for (long i = m_iBegDscr2; i < iDscr; i++)
      {
        m_pDscrSeg[i].pntR.iTo = i;
        m_pDscrSeg[i].pntR.bRightTo = false;
        m_pDscrSeg[i].pntL.iFrom = i;
        m_pDscrSeg[i].pntL.bRightFrom = true;
      }
      m_sostScan = SCAN_OTHER_LINES;
    } break;
    case SCAN_OTHER_LINES:
    {
      if (!bNewLine && m_pDscrSeg[iDscr].y == m_pDscrSeg[m_iBegDscr3].y)
      {
        if (m_pDscrSeg[iDscr - 1].pntR.x >= xLeft)
          return false;
        return true;
      }
      m_iBegDscr1 = m_iBegDscr2;
      m_iBegDscr2 = m_iBegDscr3;
      m_iBegDscr3 = iDscr; 
      ProcScan();
    } break;
  }
  return true;
}

bool CRastrTool::Split()
{
  if (m_sostScan != SCAN_OTHER_LINES)
    return false;

  m_iBegDscr1 = m_iBegDscr2;
  m_iBegDscr2 = m_iBegDscr3;
  m_iBegDscr3 = m_nmbDscrSeg; 
  ProcScan();
  for (long iDscr = m_iBegDscr2; iDscr < m_iBegDscr3; iDscr++)
  {
    m_pDscrSeg[iDscr].pntL.iTo = iDscr;
    m_pDscrSeg[iDscr].pntL.bRightTo = true;
    m_pDscrSeg[iDscr].pntR.iFrom = iDscr;
    m_pDscrSeg[iDscr].pntR.bRightFrom = false;
    AddStart(iDscr, false);
  }
  m_sostScan = SCAN_EMPTY;
  m_bNewLine = true;
  return true;
}

void CRastrTool::ProcScan()
{
  long iDscrCur1 = m_iBegDscr1;
  long iDscrCur2 = m_iBegDscr2;
  long iDscrEnd1 = m_iBegDscr2;
  long iDscrEnd2 = m_iBegDscr3;
  long iDscrOpen1 = -1;
  long iDscrOpen2 = -1;
  do
  {
    TYPE_CROSSES typeCrs = GetTypeCrs(m_pDscrSeg[iDscrCur2].pntL.x, m_pDscrSeg[iDscrCur2].pntR.x,
                                      m_pDscrSeg[iDscrCur1].pntL.x, m_pDscrSeg[iDscrCur1].pntR.x);
    switch (typeCrs)
    {
      case CRS_LEFT_LESS_RIGHT_LESS:
      {
        if (iDscrOpen1 == -1)
        {
          m_pDscrSeg[iDscrCur2].pntR.iTo = iDscrCur2;
          m_pDscrSeg[iDscrCur2].pntR.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur2;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = true;
        }
        else
        {
          m_pDscrSeg[iDscrCur2].pntR.iTo = iDscrOpen1;
          m_pDscrSeg[iDscrCur2].pntR.bRightTo = true;
          m_pDscrSeg[iDscrOpen1].pntR.iFrom = iDscrCur2;
          m_pDscrSeg[iDscrOpen1].pntR.bRightFrom = true;
          iDscrOpen1 = -1;
        }
        iDscrCur2++;
      } break;
      case CRS_LEFT_LESS_RIGHT_INSIDE:    
      {
        if (iDscrOpen1 == -1)
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur2;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = false;
        }
        else
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrOpen1;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = true;
          m_pDscrSeg[iDscrOpen1].pntR.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrOpen1].pntR.bRightFrom = false;
          AddStart(iDscrCur1, false);
          iDscrOpen1 = -1;
        }
        iDscrOpen2 = iDscrCur2++;
      } break;
      case CRS_LEFT_LESS_RIGHT_MORE:      
      {
        if (iDscrOpen1 == -1)
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur2;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = false;
        }
        else
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrOpen1;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = true;
          m_pDscrSeg[iDscrOpen1].pntR.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrOpen1].pntR.bRightFrom = false;
          AddStart(iDscrCur1, false);
        }
        iDscrOpen1 = iDscrCur1++;
      } break;
      case CRS_LEFT_INSIDE_RIGHT_MORE:     
      {
        if (iDscrOpen2 == -1)
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur2;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = false;
        }
        else
        {
          m_pDscrSeg[iDscrOpen2].pntR.iTo = iDscrCur2;
          m_pDscrSeg[iDscrOpen2].pntR.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrOpen2;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = true;
          iDscrOpen2 = -1;
        }
        iDscrOpen1 = iDscrCur1++;
      } break;
      case CRS_LEFT_INSIDE_RIGHT_INSIDE:  
      {
        if (iDscrOpen2 == -1)
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur2;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = false;
        }
        else
        {
          m_pDscrSeg[iDscrOpen2].pntR.iTo = iDscrCur2;
          m_pDscrSeg[iDscrOpen2].pntR.bRightTo = false;
          m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrOpen2;
          m_pDscrSeg[iDscrCur2].pntL.bRightFrom = true;
        }
        iDscrOpen2 = iDscrCur2++;
      } break;
      case CRS_LEFT_MORE_RIGHT_MORE:
      {
        if (iDscrOpen2 != -1)
        {
          m_pDscrSeg[iDscrOpen2].pntR.iTo = iDscrCur1;
          m_pDscrSeg[iDscrOpen2].pntR.bRightTo = true;
          m_pDscrSeg[iDscrCur1].pntR.iFrom = iDscrOpen2;
          m_pDscrSeg[iDscrCur1].pntR.bRightFrom = true;
          iDscrOpen2 = -1;
        }
        else
        {
          m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur1;
          m_pDscrSeg[iDscrCur1].pntL.bRightTo = true;
          m_pDscrSeg[iDscrCur1].pntR.iFrom = iDscrCur1;
          m_pDscrSeg[iDscrCur1].pntR.bRightFrom = false;
          AddStart(iDscrCur1, false);
        }
        iDscrCur1++;
      } break;
    }  
  } while (iDscrCur1 < iDscrEnd1 && iDscrCur2 < iDscrEnd2);
  if (iDscrOpen1 != -1)
  {
    m_pDscrSeg[iDscrCur2].pntR.iTo = iDscrOpen1;
    m_pDscrSeg[iDscrCur2].pntR.bRightTo = true;
    m_pDscrSeg[iDscrOpen1].pntR.iFrom = iDscrCur2;
    m_pDscrSeg[iDscrOpen1].pntR.bRightFrom = true;
    iDscrCur2++;
  }
  if (iDscrOpen2 != -1)
  {
    m_pDscrSeg[iDscrOpen2].pntR.iTo = iDscrCur1;
    m_pDscrSeg[iDscrOpen2].pntR.bRightTo = true;
    m_pDscrSeg[iDscrCur1].pntR.iFrom = iDscrOpen2;
    m_pDscrSeg[iDscrCur1].pntR.bRightFrom = true;
    iDscrCur1++;
  }
  while (iDscrCur1 < iDscrEnd1)
  {
    m_pDscrSeg[iDscrCur1].pntL.iTo = iDscrCur1;
    m_pDscrSeg[iDscrCur1].pntL.bRightTo = true;
    m_pDscrSeg[iDscrCur1].pntR.iFrom = iDscrCur1;
    m_pDscrSeg[iDscrCur1].pntR.bRightFrom = false;
    AddStart(iDscrCur1, false);
    iDscrCur1++;
  }
  while (iDscrCur2 < iDscrEnd2)
  {
    m_pDscrSeg[iDscrCur2].pntR.iTo = iDscrCur2;
    m_pDscrSeg[iDscrCur2].pntR.bRightTo = false;
    m_pDscrSeg[iDscrCur2].pntL.iFrom = iDscrCur2;
    m_pDscrSeg[iDscrCur2].pntL.bRightFrom = true;
    iDscrCur2++;
  }
}

bool CRastrTool::GetPolyPolygon(int *pPolys, int **ppListPoly, long **ppListXYCoords, int *pTotalCoords)
{
  *pPolys = 0;
  *pTotalCoords = 0;
  m_iBegDscr1 = m_iBegDscr2;
  m_iBegDscr2 = m_iBegDscr3;
  m_iBegDscr3 = m_nmbDscrSeg; 
  ProcScan();
  for (long iDscr = m_iBegDscr2; iDscr < m_iBegDscr3; iDscr++)
  {
    m_pDscrSeg[iDscr].pntL.iTo = iDscr;
    m_pDscrSeg[iDscr].pntL.bRightTo = true;
    m_pDscrSeg[iDscr].pntR.iFrom = iDscr;
    m_pDscrSeg[iDscr].pntR.bRightFrom = false;
    AddStart(iDscr, false);
  }
  for (long i = 0; i < m_nmbStarts; i++)
  {
    long iD = m_pStarts[i].iDscr;
    bool bRight = m_pStarts[i].bRight;
    bool bOn = (bRight) ? m_pDscrSeg[iD].pntR.bProc : m_pDscrSeg[iD].pntL.bProc;
    if (bOn)
      continue;
    long iCurPoly = AddPoly();
    long xPrev, yPrev;
    bool bPrevXY = false;
    long iPrev = -1;
    while (true)
    {
      long x, y = m_pDscrSeg[iD].y;
      bool bProc;
      if (bRight)
      {
        x = m_pDscrSeg[iD].pntR.x;
        bRight = m_pDscrSeg[iD].pntR.bRightTo;
        bProc = m_pDscrSeg[iD].pntR.bProc;
        m_pDscrSeg[iD].pntR.bProc = true;
        iD = m_pDscrSeg[iD].pntR.iTo;
      }
      else
      {
        x = m_pDscrSeg[iD].pntL.x;
        bRight = m_pDscrSeg[iD].pntL.bRightTo;
        bProc = m_pDscrSeg[iD].pntL.bProc;
        m_pDscrSeg[iD].pntL.bProc = true;
        iD = m_pDscrSeg[iD].pntL.iTo;
      }
      if (iPrev == -1 || x != xPrev || y != yPrev)
      {
        iPrev = AddPoint(x, y, iPrev);
        m_pPolys[iCurPoly].nmbPnt++;
        xPrev = x;
        yPrev = y;
      }
      if (bProc)
        break;      
    }
  }
  m_pOutPolys = (int *)::realloc(m_pOutPolys, sizeof(long) * m_nmbPolys);
  long j;
  for (j = 0; j < m_nmbPolys; j++)
  {
    m_pOutPolys[j] = m_pPolys[j].nmbPnt;
    bool bWasDeleted;
    do
    {
      bWasDeleted = false;      
      long iPnt = m_pPolys[j].indPnt;
      while (iPnt != -1)
      {
        if (TryToDelete(iPnt))
        {
          bWasDeleted = true;
          m_pOutPolys[j]--;
          iPnt = m_pPoints[iPnt].iNext;
          iPnt = m_pPoints[iPnt].iNext;
        }
        else
          iPnt = m_pPoints[iPnt].iNext;
      }
    } while (bWasDeleted);
  }
  m_pInfoPolyList = (POLY_INFO *)::realloc(m_pInfoPolyList, sizeof(POLY_INFO) * m_nmbPolys);
  long nmbPnt = 0;
  for (j = 0; j < m_nmbPolys; j++)
  {
    nmbPnt += m_pOutPolys[j];
    m_pInfoPolyList[j].min.x = 0x7FFFFFFF;
    m_pInfoPolyList[j].min.y = 0x7FFFFFFF;
    m_pInfoPolyList[j].max.x = 0x80000000;
    m_pInfoPolyList[j].max.y = 0x80000000;
    m_pInfoPolyList[j].nmbYmax = 0;
    m_pInfoPolyList[j].bExtrn  = false;
    m_pInfoPolyList[j].nmbHoles = 0;
    m_pInfoPolyList[j].nxtExt  = -1;
    m_pInfoPolyList[j].nxtInt  = -1;
    m_pInfoPolyList[j].iBegPnt = 0;
  }
  m_pOutPnt = (long *)::realloc(m_pOutPnt, sizeof(long) * nmbPnt * 2);

  long iP = 0;
  long iPolyP = 0;
  
  for (j = 0; j < m_nmbPolys; j++)
  {
    long iPnt = m_pPolys[j].indPnt;
    while (iPnt != -1)
    {
      if (iP >= nmbPnt)
        return false;
      m_pOutPnt[iP * 2] = m_pPoints[iPnt].x;
      m_pOutPnt[iP * 2 + 1] = m_pPoints[iPnt].y;

      m_pInfoPolyList[j].min.x = __min(m_pInfoPolyList[j].min.x, m_pPoints[iPnt].x);
      m_pInfoPolyList[j].min.y = __min(m_pInfoPolyList[j].min.y, m_pPoints[iPnt].y);
      m_pInfoPolyList[j].max.x = __max(m_pInfoPolyList[j].max.x, m_pPoints[iPnt].x);
      if (m_pPoints[iPnt].y > m_pInfoPolyList[j].max.y)
      {
        m_pInfoPolyList[j].max.y    = m_pPoints[iPnt].y;
        m_pInfoPolyList[j].nmbYmax = iP - iPolyP;
      }
      iPnt = m_pPoints[iPnt].iNext;
      iP++;
    }
    iPolyP += m_pOutPolys[j];
  }  
  *pPolys = m_nmbPolys;
  *ppListPoly = m_pOutPolys; 
  *ppListXYCoords = m_pOutPnt;
  *pTotalCoords = nmbPnt;
  return true;
}

bool CRastrTool::CalcDirect(long x1, long y1, long x2, long y2, long x3, long y3)
{
  long dy1 = y1 - y2;
  long dy3 = y3 - y2;
  long dx1 = x1 - x2;
  long dx3 = x3 - x2;
  if (dy1 == 0)
    return dx1 > 0;
  if (dy3 == 0)
    return dx3 < 0;
  long dx3n = (long)((double)dy1 * (double)dx3 / (double)dy3);
  return dx1 > dx3n;
}

void CRastrTool::AddStart(long iDscr, bool bRight)
{
  if ((m_nmbStarts % 100) == 0)
    m_pStarts = (DSCR_START *)::realloc(m_pStarts, sizeof(DSCR_START) * (100 + m_nmbStarts)); 
  m_pStarts[m_nmbStarts].iDscr = iDscr;
  m_pStarts[m_nmbStarts++].bRight = bRight;
}

long CRastrTool::AddPoly()
{
  if ((m_nmbPolys % 100) == 0)
    m_pPolys = (DSCR_POLY *)::realloc(m_pPolys, sizeof(DSCR_POLY) * (100 + m_nmbPolys));
  m_pPolys[m_nmbPolys].nmbPnt = 0;
  m_pPolys[m_nmbPolys].indPnt = m_nmbPoints;
  return m_nmbPolys++;
}

long CRastrTool::AddPoint(long x, long y, long iPrev)
{
  if ((m_nmbPoints % 100) == 0)
    m_pPoints = (DSCR_OUT_PNT *)::realloc(m_pPoints, sizeof(DSCR_OUT_PNT) * (100 + m_nmbPoints));
  m_pPoints[m_nmbPoints].x = x;
  m_pPoints[m_nmbPoints].y = y;
  m_pPoints[m_nmbPoints].iNext = -1;
  m_pPoints[m_nmbPoints].iPrev = iPrev;
  if (iPrev != -1)
    m_pPoints[iPrev].iNext = m_nmbPoints;
  return m_nmbPoints++;
}

bool CRastrTool::TryToDelete(long iPnt)
{
/// !!!!!!!!!!!! !!!!!!!!!!
    return false;


  long iNext = m_pPoints[iPnt].iNext;
  long iPrev = m_pPoints[iPnt].iPrev;
  if (iNext == -1 || iPrev == -1)
    return false;
  long dx = m_pPoints[iNext].x - m_pPoints[iPrev].x;
  long dy = m_pPoints[iNext].y - m_pPoints[iPrev].y;
  if (dx == 0 && dy == 0)
    return false;

  if (abs(dx) > abs(dy))
  {
    long calcedDy = (long)((double)(m_pPoints[iPnt].x - m_pPoints[iPrev].x) * dy / dx);
    if (abs(calcedDy - (m_pPoints[iPnt].y - m_pPoints[iPrev].y)) > 1)
      return false;
  }
  else
  {
    long calcedDx = (long)((double)(m_pPoints[iPnt].y - m_pPoints[iPrev].y) * dx / dy);
    if (abs(calcedDx - (m_pPoints[iPnt].x - m_pPoints[iPrev].x)) > 1)
      return false;
  }
  m_pPoints[iPrev].iNext = iNext;
  m_pPoints[iNext].iPrev = iPrev;
  return true;
}
////////////////////////////////////////////////////////////////
bool  RgnData2Poly (LPRGNDATA pRgnData, CRastrTool * pRastrTool
                   )
{
  bool bRes = false;
  try 
  { 
  do 
  {
    if (pRgnData == NULL)
      break;
    if (pRastrTool == NULL)
      break;

    LPRECT pRect = (RECT* )pRgnData->Buffer;
    bool   bErr  = false;
    long   yPrev;
    DWORD  iStart = 0;
	enum POLYSTATE
	{
		START,
		TOP,
		BOTTOM
	} state = START;
    DWORD i = 0;
    for (; i < pRgnData->rdh.nCount; ++i)
    {
	  std::cout << "i=" << i << std::endl;
      switch (state)
      {
      case START:
        {
		  std::cout << "START" << std::endl;
          pRastrTool->NewLine();
          if (!pRastrTool->AddDscrSeg(pRect[i].top, pRect[i].left, pRect[i].right))
            bErr = true;
          yPrev = pRect[i].top;
          iStart = i;
          state = TOP;
        } break;
      case TOP:
        {
		  std::cout << "TOP" << std::endl;
          if (yPrev == pRect[i].top)
          {
            if (!pRastrTool->AddDscrSeg(pRect[i].top, pRect[i].left, pRect[i].right))
              bErr = true;
            yPrev = pRect[i].top;
          }
          else
          {
            i = iStart;
            pRastrTool->NewLine();
            if (!pRastrTool->AddDscrSeg(pRect[i].bottom, pRect[i].left, pRect[i].right))
              bErr = true;
            yPrev = pRect[i].bottom;
            state = BOTTOM;
          }
        } break;
      case BOTTOM:
        {
		  std::cout << "BOTTOM" << std::endl;
          if (yPrev == pRect[i].bottom)
          {
            if (!pRastrTool->AddDscrSeg(pRect[i].bottom, pRect[i].left, pRect[i].right))
              bErr = true;
            yPrev = pRect[i].bottom;
          }
          else
          {
            iStart = i;
            if (yPrev == pRect[i].top)
              pRastrTool->NewLine();
            else
              pRastrTool->Split();
            if (!pRastrTool->AddDscrSeg(pRect[i].top, pRect[i].left, pRect[i].right))
              bErr = true;
            yPrev = pRect[i].top;
            state = TOP;
          }
        } break;
      }
    }
    pRastrTool->NewLine();

    for (i = iStart; i < pRgnData->rdh.nCount; i++)
    {
      if (!pRastrTool->AddDscrSeg(pRect[i].bottom, pRect[i].left, pRect[i].right))
        bErr = true;
    }
    if (pRgnData->rdh.nCount == 0)
      break;
    if (bErr)
      break;
    bRes = true;

  } while(0); 
  } 
  catch(...) { bRes = false; }
  return bRes;
}
