VC++开发GIS系统(285)判断拓扑关系类的设计及实现

本文创建一个判断点、线、面(区)间拓扑关系的类,用于GIS中拓扑分析的相关操作。其演示如下:

GIS系统拓扑操作类的定义

在 _malaAnalysis.h 中定义GIS拓扑分析的类,代码如下:

/*
* 拓扑分析
*/
class malaanalysisdll CmalaTopo :public CmalaMouseAction
{
public:
  CmalaTopo(CView* mView, malaScreen *pScreen, CString &fileFullPath, int topoType);
  virtual ~CmalaTopo();
  static vector<malaTopoCell> m_TopoObject;
  void topoAnalysis(vector<malaTopoCell>TopoObject);
  void LButtonDown(UINT nFlags, malaPoint point);
  void LButtonUp(UINT nFlags, malaPoint point);
  void  MouseMove(UINT nFlags, malaPoint point);
private:

  malaScreen *mScreen;
  CString mPath;//文件路径
  bool m_Selected;
  CmalaPointsSelect m_SelectPnt;
  CmalaLinesSelect m_SelectLine;
  CmalaPolysSelect m_SelectePoly;
  int m_SelectStyle;
};
  • @ *mScreen 屏幕坐标
  • @ mPath 文件路径
  • @ m_Selected 控制要素是否被选中
  • @ m_SelectPnt 选择的点
  • @ m_SelectLine 选择的线
  • @ m_SelectePoly 选择的面
  • @ m_SelectStyle 选择的类型(1选点2选线3选面)

类的实现

在 _malaAnalysis.cpp 中实现上述类的定义,代码如下:

vector<malaTopoCell> CmalaTopo::m_TopoObject;

CmalaTopo::CmalaTopo(CView* mView, malaScreen *pScreen, CString &fileFullPath, int topoType)
{

  mBaseView = mView;
  mPath = fileFullPath;
  mScreen = pScreen;

  CmalaPointsSelect obj1(mBaseView,mScreen, mPath);
  m_SelectPnt = obj1;

  CmalaLinesSelect obj2(mBaseView, mScreen, mPath);
  m_SelectLine = obj2;

  CmalaPolysSelect obj3(mBaseView, mScreen, mPath);
  m_SelectePoly = obj3;

  m_Selected = FALSE;
  m_SelectStyle = topoType;
}

CmalaTopo::~CmalaTopo()
{

}

void CmalaTopo::LButtonDown(UINT nFlags, malaPoint point)
{
  switch (m_SelectStyle)
  {
  case 1:
    if (!m_Selected)
      m_SelectPnt.LButtonDown(nFlags, point);
    break;
  case 2:
    if (!m_Selected)
      m_SelectLine.LButtonDown(nFlags, point);
    break;
  case 3:
    if (!m_Selected)
      m_SelectePoly.LButtonDown(nFlags, point);
    break;
  default:
    break;
  }
}

void CmalaTopo::LButtonUp(UINT nFlags, malaPoint point)
{
  vector<malaPoint>MyPoint;
  malaTopoCell topo;
  switch (m_SelectStyle)
  {
  case 1:
    if (!m_Selected)
      m_SelectPnt.LButtonUp(nFlags, point);
    m_Selected = m_SelectPnt.m_Selected;
    if (m_Selected)
    {
      MyPoint.push_back(m_SelectPnt.m_pnt);
      topo.index = 1;
      topo.Object = MyPoint;
      m_TopoObject.push_back(topo);
      if (m_TopoObject.size() == 2)
      {
        topoAnalysis(m_TopoObject);
        m_TopoObject.clear();
      }

      m_Selected = FALSE;
      m_SelectPnt.m_Selected = FALSE;
    }
    break;
  case 2:
    if (!m_Selected)
      m_SelectLine.LButtonUp(nFlags, point);
    m_Selected = m_SelectLine.m_Selected;
    if (m_Selected)
    {
      topo.index = 2;
      topo.Object = m_SelectLine.mLine;

      m_TopoObject.push_back(topo);
      if (m_TopoObject.size() == 2)
      {
        topoAnalysis(m_TopoObject);
        m_TopoObject.clear();
      }

      m_Selected = FALSE;
      m_SelectLine.m_Selected = FALSE;
    }
    break;
  case 3:
    if (!m_Selected)
      m_SelectePoly.LButtonUp(nFlags, point);
    m_Selected = m_SelectePoly.m_Selected;
    if (m_Selected)
    {
      topo.index = 3;
      topo.Object = m_SelectePoly.mSPoly;

      m_TopoObject.push_back(topo);
      if (m_TopoObject.size() == 2)
      {
        topoAnalysis(m_TopoObject);
        m_TopoObject.clear();
      }

      m_Selected = FALSE;
      m_SelectePoly.m_Selected = FALSE;
    }
    break;
  default:
    break;
  }
}

void CmalaTopo::MouseMove(UINT nFlags, malaPoint point)
{

  switch (m_SelectStyle)
  {
  case 1:
    if (!m_Selected)
      m_SelectPnt.MouseMove(nFlags, point);
    break;
  case 2:
    if (!m_Selected)
      m_SelectLine.MouseMove(nFlags, point);
    break;
  case 3:
    if (!m_Selected)
      m_SelectePoly.MouseMove(nFlags, point);
    break;
  default:
    break;
  }

}

void CmalaTopo::topoAnalysis(vector<malaTopoCell>TopoObject)
{
  malaLogic math;
  vector<malaPoint> Topo1;
  vector<malaPoint> Topo2;
  int index1;//index=1表示点;等于2表示线;等于3表示面
  int index2;
  Topo1 = TopoObject[0].Object;
  index1 = TopoObject[0].index;
  Topo2 = TopoObject[1].Object;
  index2 = TopoObject[1].index;
  //点与点关系
  if (index1 == 1 && index2 == 1)
  {
    if (math.isPointEqPoint(Topo1[0], Topo2[0]))
      MessageBox(mBaseView->m_hWnd, L"两点重合", L"点与点拓扑关系", MB_OK | MB_ICONINFORMATION);
    else
      MessageBox(mBaseView->m_hWnd, L"点与点相离", L"点与点拓扑关系", MB_OK | MB_ICONINFORMATION);
  }

  //点与线
  if (index1 == 1 && index2 == 2)
  {
    if (math.isPointInPolyLine(Topo1[0], Topo2))
      MessageBox(mBaseView->m_hWnd, L"点在线上", L"点与线拓扑关系", MB_OK | MB_ICONINFORMATION);
    else
      MessageBox(mBaseView->m_hWnd, L"点不在线上", L"点与线拓扑关系", MB_OK | MB_ICONINFORMATION);
  }

  if (index1 == 2 && index2 == 1)
  {
    if (math.isPointInPolyLine(Topo2[0], Topo1))
      MessageBox(mBaseView->m_hWnd, L"点在线上", L"点与线拓扑关系", MB_OK | MB_ICONINFORMATION);
    else
      MessageBox(mBaseView->m_hWnd, L"点不在线上", L"点与线拓扑关系", MB_OK | MB_ICONINFORMATION);
  }

  //点与面

  switch (index1)
  {
  case 1:
    if (index2 == 3)
    {
      if (math.isPointInPolygon(Topo1[0], Topo2))
        MessageBox(mBaseView->m_hWnd, L"点在区内", L"点与面拓扑关系", MB_OK | MB_ICONINFORMATION);
      else
        MessageBox(mBaseView->m_hWnd, L"点在区外", L"点与面拓扑关系", MB_OK | MB_ICONINFORMATION);
    }
    break;

  case 3:
    if (index2 == 1)
    {
      if (math.isPointInPolygon(Topo2[0], Topo1))
        MessageBox(mBaseView->m_hWnd, L"点在区内", L"点与面拓扑关系", MB_OK | MB_ICONINFORMATION);
      else
        MessageBox(mBaseView->m_hWnd, L"点在区外", L"点与面拓扑关系", MB_OK | MB_ICONINFORMATION);
    }
    break;
  default:
    ;
  }

  //线与线
  if (index1 == 2 && index2 == 2)
  {
    //相等返回1;相交返回2;相离返回3
    int index = math.lineAndLine(Topo1, Topo2);
    switch (index)
    {
    case 1:
      MessageBox(mBaseView->m_hWnd, L"两条线相等", L"线与线拓扑关系", MB_OK | MB_ICONINFORMATION);
      break;
    case 2:
      MessageBox(mBaseView->m_hWnd, L"两条线相交", L"线与线拓扑关系", MB_OK | MB_ICONINFORMATION);
      break;
    case 3:
      MessageBox(mBaseView->m_hWnd, L"两条线相离", L"线与线拓扑关系", MB_OK | MB_ICONINFORMATION);
    default:
      ;
    }
  }

  //线与面
  //相离返回1,相交返回2,在区内返回3
  int LinePolygon;
  switch (index1)
  {
  case 2:
    if (index2 == 3)
    {
      LinePolygon = math.polyLineAndPolygon(Topo1, Topo2);
      if (LinePolygon == 1)
        MessageBox(mBaseView->m_hWnd, L"线与区相离", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
      else if (LinePolygon == 2)
        MessageBox(mBaseView->m_hWnd, L"线与区相交", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
      else
        MessageBox(mBaseView->m_hWnd, L"线在区内", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
    }
    break;

  case 3:
    if (index2 == 2)
    {
      LinePolygon = math.polyLineAndPolygon(Topo2, Topo1);
      if (LinePolygon == 1)
        MessageBox(mBaseView->m_hWnd, L"线与区相离", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
      else if (LinePolygon == 2)
        MessageBox(mBaseView->m_hWnd, L"线与区相交", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
      else
        MessageBox(mBaseView->m_hWnd, L"线在区内", L"线与区拓扑关系", MB_OK | MB_ICONINFORMATION);
    }
    break;

  default:
    ;
  }

  //面与面
  //相等返回1,相交返回2,内含返回3,相离返回4
  if (index1 == 3 && index2 == 3)
  {
    int PolygonPolygon = math.polygonAndPolygon(Topo2, Topo1);
    if (PolygonPolygon == 1)
      MessageBox(mBaseView->m_hWnd, L"区与区相等", L"区与区的拓扑", MB_OK | MB_ICONINFORMATION);
    if (PolygonPolygon == 2)
      MessageBox(mBaseView->m_hWnd, L"区与区相交", L"区与区的拓扑", MB_OK | MB_ICONINFORMATION);
    if (PolygonPolygon == 3)
      MessageBox(mBaseView->m_hWnd, L"区内含", L"区与区的拓扑", MB_OK | MB_ICONINFORMATION);
    if (PolygonPolygon == 4)
      MessageBox(mBaseView->m_hWnd, L"区与区相离", L"区与区的拓扑", MB_OK | MB_ICONINFORMATION);
    if (PolygonPolygon == 5)
      MessageBox(mBaseView->m_hWnd, L"区覆盖区", L"区与区的拓扑", MB_OK | MB_ICONINFORMATION);
  }
}

首先利用一个全局变量 m_TopoObject 记录拓扑分析的两个元素,当其容量为2时,调用topoAnalysis函数,根据要素类型调用相应的拓扑分析函数。

详细代码可以参考:GitHub

VC++开发GIS系统(284)判断面元素之间的拓扑关系 VC++开发GIS系统(286)判断拓扑关系菜单响应及实现

作者:,GIS爱好者。
分享本文,请您带上本文链接
分享到:

发表评论