arx/zrx合并多段线

cad中可以通过join命令合并多条首尾相连的多段线,但是arx中却没有提供相应方法,这为arx二次开发增加了一些困难。在此提供本人写的合并多段线的方法,以供参考。

主要思路为遍历要合并的多段线,获取起点、终点、以及其它所有顶点,然后存放到以起点和终点为key的multimap中,value为PointInfo结构的数据,PointInfo中存放有该起点或终点对应的多段线id以及多段线的所有顶点。

接下来就是查找multimap中相同的key,排除同一条多段线,就可以找到与多段线的起点或终点连在一起的另一条多段线,然后就把找到的多段线的所有顶点添加到AcGePoint2dArray中。

依次找下去,直到无法找到key值相同的多段线,再反向查找另一边的。

如此一来,AcGePoint2dArray中就是要合并的多段线从一端到另一端的所有顶点数据,根据AcGePoint2dArray生成合并的多段线即可。

关键代码如下:

#include "StdAfx.h"
#include "Common/Common.h"

struct PointInfo
{
	PointInfo() = default;
	PointInfo(const PointInfo&) = default;
	PointInfo& operator=(const PointInfo&) = default;

	PointInfo(const AcDbObjectId& id, const AcGePoint2dArray& ptArray)
		:m_id(id), m_ptArray(ptArray) {}

	AcDbObjectId m_id;
	AcGePoint2dArray m_ptArray;
};

struct AcGePoint3d_Less
{
	bool operator()(const AcGePoint3d& pt1, const AcGePoint3d& pt2) const
	{
		if (CMathUtil::IsLess(pt1.x, pt2.x))
		{
			return true;
		}
		else if (CMathUtil::IsEqual(pt1.x, pt2.x))
		{
			if (CMathUtil::IsLess(pt1.y, pt2.y))
			{
				return true;
			}
			else if (CMathUtil::IsEqual(pt1.y, pt2.y))
			{
				if (CMathUtil::IsLess(pt1.z, pt2.z))
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
};

AcDbObjectIdArray MergePolyline(const AcDbObjectIdArray& idArray, bool bRetainMergedMembers = true)
{
	AcDbObjectIdArray idsPline;
	std::multimap<AcGePoint3d, PointInfo, AcGePoint3d_Less> mmapPt2PointInfo;
	for (const auto& id : idArray)
	{
		AcDbObjectPointer<AcDbPolyline> pPline(id);
		if (pPline)
		{
			if (pPline->isClosed())
			{
				idsPline.append(id);
				continue;
			}

			AcGePoint3d ptStart, ptEnd;
			pPline->getStartPoint(ptStart);
			pPline->getEndPoint(ptEnd);

			AcGePoint2dArray ptArray;
			for (uint nIndex = 0; nIndex < pPline->numVerts(); nIndex++)
			{
				AcGePoint2d ptVertex;
				pPline->getPointAt(nIndex, ptVertex);
				ptArray.append(ptVertex);
			}

			mmapPt2PointInfo.emplace(ptStart, PointInfo(id, ptArray));
			mmapPt2PointInfo.emplace(ptEnd, PointInfo(id, ptArray.reverse()));
		}
	}
	if (!mmapPt2PointInfo.size())
	{
		return idsPline;
	}

	while (mmapPt2PointInfo.size())
	{
		AcGePoint2dArray ptArray;
		std::set<AcDbObjectId> setId;
		auto iterFind = mmapPt2PointInfo.begin();
		for (int iCount = 2; iCount > 0 && mmapPt2PointInfo.size(); --iCount)
		{
			// 反向添加另一边的多段线
			ptArray.reverse();

			if (ptArray.length())
			{
				iterFind = mmapPt2PointInfo.find(CConvertUtil::ToPoint3d(ptArray.last()));
			}
			while (iterFind != mmapPt2PointInfo.end())
			{
				if (setId.find(iterFind->second.m_id) == setId.end())
				{
					ptArray.append(iterFind->second.m_ptArray);
				}

				setId.insert(iterFind->second.m_id);
				mmapPt2PointInfo.erase(iterFind);
				iterFind = mmapPt2PointInfo.find(CConvertUtil::ToPoint3d(ptArray.last()));
			}

			// 删除已经添加点的线段
			for (iterFind = mmapPt2PointInfo.begin(); iterFind != mmapPt2PointInfo.end(); )
			{
				if (setId.find(iterFind->second.m_id) != setId.end())
				{
					iterFind = mmapPt2PointInfo.erase(iterFind);
				}
				else
				{
					iterFind++;
				}
			}
		}

		if (setId.size() == 1)
		{
			// 未合并的多段线也需要返回
			idsPline.append(*setId.begin());
		}
		else
		{
			AcDbObjectId idPline = CPolylineUtil::Add(ptArray);
			if (!idPline.isNull())
			{
				idsPline.append(idPline);
			}
			if (ptArray.first() == ptArray.last())
			{
				AcDbObjectPointer<AcDbPolyline> pPline(idPline, AcDb::kForWrite);
				if (pPline)
				{
					pPline->setClosed(true);
				}
			}
			if (!bRetainMergedMembers)
			{
				CEntityUtil::Erase(setId);
			}
		}
	}

	return idsPline;
}

demo代码:
https://github.com/ChiuqiuA/ArxSample.git


  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个基于C++的表格绘制实现类,支持表格合并: ```cpp #include <iostream> #include <vector> using namespace std; // 定义表格中的单元格 struct Cell { int row; int col; int rowSpan; int colSpan; string content; }; // 定义表格类 class Table { public: Table(int rows, int cols) { this->rows = rows; this->cols = cols; // 初始化表格 for (int i = 0; i < rows; i++) { vector<Cell> row; for (int j = 0; j < cols; j++) { Cell cell = {i, j, 1, 1, ""}; row.push_back(cell); } cells.push_back(row); } } // 设置单元格内容 void setContent(int row, int col, string content) { cells[row][col].content = content; } // 合并单元格 void mergeCells(int row, int col, int rowSpan, int colSpan) { cells[row][col].rowSpan = rowSpan; cells[row][col].colSpan = colSpan; // 清空被合并的单元格 for (int i = row; i < row + rowSpan; i++) { for (int j = col; j < col + colSpan; j++) { if (i != row || j != col) { cells[i][j].row = -1; cells[i][j].col = -1; } } } } // 绘制表格 void drawTable() { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { Cell cell = cells[i][j]; if (cell.row == -1 && cell.col == -1) { // 被合并的单元格不输出 continue; } if (cell.row == i && cell.col == j) { // 表格左上角的单元格输出 cout << cell.content << "\t"; } } cout << endl; } } private: int rows; int cols; vector<vector<Cell>> cells; // 存储表格中的单元格 }; int main() { Table table(3, 3); table.setContent(0, 0, "A"); table.setContent(0, 1, "B"); table.setContent(0, 2, "C"); table.setContent(1, 0, "D"); table.setContent(1, 1, "E"); table.mergeCells(1, 1, 2, 2); table.setContent(2, 2, "F"); table.drawTable(); return 0; } ``` 在这个表格实现类中,我们使用一个二维数组存储表格中的单元格,每个单元格都有行、列、行跨度、列跨度和内容等属性。在绘制表格时,我们通过遍历单元格数组,判断每个单元格是否需要输出内容,并输出表格。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值