arx/zrx合并多段线

本文介绍了一种在arx环境中没有现成的join命令情况下,自定义实现合并首尾相连多段线的方法,通过遍历多段线顶点并存储在PointInfo结构中,最后生成合并后的多段线对象。
摘要由CSDN通过智能技术生成

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


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值