CAD日記

主にAutoCADのことについて書いているけど、近頃は投資系ネタに注力している。自動売買、仮想通貨、PC関係、プログラミングなど。@caddiary

ソフト開発 DWG

ハッチングの境界データのスプラインをポリラインに分解する方法

投稿日:

dwgにおけるハッチングの表現はややこしくて、boundary(境界)オブジェクトが多階層化している。境界オブジェクトには大きく2つあって、1つの閉じたポリラインか複数のその他図形群かとなる。1つのポリラインであれば何てことはなくて、bulge(ふくらみ)によって途中に円弧があるかもしれないねくらいの話で済むが、その他図形群がタイヘンなことであり、線(Line)か円・円弧(Circle or Arc)か楕円・楕円弧(Ellipe or Ellipe arc)か曲線(Nurbs Curve)かという選択になる。線、円、楕円なんてところはわけないので省略して、曲線の場合のラビリンスから抜け出せたので、以下で詳細に解説しよう。なお、以下はTeigha改めODAによってハッチングオブジェクト内容の境界図形を解析するという話であり、一般性が低いことを先に伝えておく。

境界オブジェクトがその他図形群の場合に現れる曲線タイプのクラスがOdGeNurbCurve2d。OdDbSplineだったらexplodeGeometryでポリラインになるから一発解決なんだけど、OdGeNurbCurve2dってのは何だってこと。NURBS曲線であることは字面からわかる。Bスプライン、ベジェ曲線を一般化したものだそうだ。NURBSが非一様有理Bスプラインであるのに対し、ベジェ曲線は一様非有理Bスプライン。。いや、よくわからんよ。興味あるならWikipediaのNURBSでも読んでくれ。

OdGeNurbCurve2dクラスにはexplode系関数がない。継承元のOdGeCurve2dにexplode関数があったから試してみたが例外エラー発生。explode系関数はOdDbEntityクラスにあるものなんで、OdDbEntityクラスを継承しているOdDbSplineにする必要がありそうなことは薄々わかっていた。そこで難関だったのはNURBS系情報の受け渡し。

OdGeCurve2d::getDefinitionDataでGETして、OdDbSpline::setNurbsDataでSETする。この関数の引数が微妙に違っていることに苦労した。コードを以下に貼りける。ちょっとした違いがある。

// OdGeNurbCurve2d* pNurbをOdDbSpline pDstに変換する処理
bool closed = false;
DPOINT pnt1 = { pNurb->startPoint().x, pNurb->startPoint().y };
DPOINT pnt2 = { pNurb->endPoint().x, pNurb->endPoint().y };
double dist = GeoGetDis(&pnt1, &pnt2);
if (dist <= ZERO * 100)  // つながってる
	closed = true;
int degree = 0;
bool rational = false, periodic = false;
OdGeKnotVector knots;
OdGePoint2dArray controlPoints;
OdGeDoubleArray weights;
pNurb->getDefinitionData(degree, rational, periodic, knots, controlPoints, weights);

OdDbSplinePtr pDst = OdDbSpline::createObject();
double controlPtTol = 0, knotTol = 0;
OdGePoint3dArray controlPoints3d;
for (int j = 0; j < (int)controlPoints.size(); j++)
{
	OdGePoint3d pnt(controlPoints[j].x, controlPoints[j].y, 0);
	controlPoints3d.append(pnt);
}
OdGeDoubleArray knots2;
for (int j = 0; j < knots.length(); j++)
{
	const double* pPtr = knots.getPtr();
	knots2.append(pPtr[j]);
}
pDst->setNurbsData(degree, rational, closed, periodic, controlPoints3d, knots2, weights, controlPtTol, knotTol);

OdDbSplineに変換できたからexplodeGeometoryすればいいわけだが、その結果現れたのがOdDb2dPolylineというのがミソ。OdDb2dPolylineにはふくらみがあるのは当然として、なんとスプラインが含まれていることもある。元がNURB曲線で、スプラインにして、ポリラインにして、分解したらスプラインって。。いやいや、スプラインを分解したポリラインにスプラインなんて含まれているわけないと断定。よって、以下の通り、頂点(Vertex)情報だけ拾い出して、DPOINTの配列にAddした。

CArray<DPOINT, DPOINT> ary;
OdRxObjectPtrArray oary;
OdResult err = pDst->explodeGeometry(oary);
if (err != eOk)
	return FALSE;
for (UINT k = 0; k < oary.size(); k++)
{
	OdDbEntityPtr pExp = OdDbEntity::cast(oary.getAt(k));
	int type = ElmGetType(pExp.get());
	if (type == _ENT_PLINE2D)
	{
		OdDb2dPolylinePtr pPoly = pExp;
		OdDbObjectIteratorPtr pIter = pPoly->vertexIterator();
		for (; !pIter->done(); pIter->step())
		{
			OdDb2dVertexPtr pVs = pIter->entity();
			if (!pVs.get())
				continue;
			OdGePoint3d pos = pVs->position();
			DPOINT pnt = { pos.x, pos.y };
			ary.Add(pnt);
		}
		if (pPoly->isClosed())
			ary.Add(ary.GetAt(0));
	}
}

サクッとかいた閉じたスプラインに対して上記処理を行ったところ、52個の頂点だったのでそこそこの精度でポリライン変換できたことになる。もちろん、ふくらみもスプラインも現れなかった。
ポリラインの点列ができれば、ライトウェイトポリライン(OdDbPolyline)として仕立てて、いろんな編集ができるってもの。

こんなことができて何がうれしいかって?塗りつぶしハッチングをビューポートでぶった切った状態をモデル空間の図形に変換できるようになる。塗りつぶしでないハッチングであれば分解して線の集まりにしてまえば見た目を維持できるが、塗りつぶしとなればハッチング要素として維持しなくてはならず、輪郭オブジェクトとしてのOdGeNurbCurve2dがクリッピングできなかったという話。上記で頂点列にすることができたから、クリッピング処理に流すことができるようになった。そして、塗りつぶしハッチングの境界データのスプライン部分をポリラインに分解してクリッピングができたという次第。

ハッチングの境界データが閉じてないとハッチングとして成り立たないから閉じてやったり、境界データを普通の図形に変換してやったり、境界データをクリッピングするなんてことは、AutoCADや互換CADのアドオンツールとして成り立ちそうな気がしてきた。切り出して、単独ツールとしてみるのもよいだろう。

-ソフト開発, DWG

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

ソフトウェアの品質管理とは何か?

今日も酒なしで退屈なんで、今日仕事をしていた中で印象深かったテーマでたらたらと文章を書いてみよう。 年に一度のバージョンアップ版リリースに向けて品質確認レビューなるものを3月の1カ月間ほどやっている。 …

Vectorに作者登録の申し込みをしてみた

Vectorとはフリーウェア、シェアウェアのダウンロードサイト。最近はあまり使わなくなった。もちろんフリーソフトはよく使っているんだけど、マイナーなものはあまり使わなくなってきていて、メジャーどころは …

no image

ペーパーモデル化ツール3

3年半の沈黙を経て、ペーパーモデル化ツールのバージョンアップが行われた。 とりあえずはVectorにアップロードされただけであり、販促活動はこれから 本格的に行われていくはずだ。 興味がある人は、以下 …

no image

DWGdirectの迷走

DWGdirect Version 1.14.01が出たのが、去年の12月半ばですから、もう2ヶ月も経ちました。最初の頃はみんな静観していたようですが、近頃バグ報告が多発しているようです。サポート掲示 …

PDFiumViewerのソースコード

GitHubで公開されているPDFiumViewerのソースコードをダウンロードして、PDFiumそのものの使い勝手を調査いていたが、なかなか困難な取り組みであり、頓挫しているところ。 PDFiumV …