CAD日記

AutoCAD,DXF,DWG,SXFなどCADのことから、仮想通貨や投資関係、PC関係、プログラミング、国内海外旅行情報など何でもござれ。@caddiary

DWG ソフト開発

Teigha改めODAでDWGをDXFに変換するプログラムをつくってみよう!【Part.3】

投稿日:

Part.2の続編。今回はODAプロジェクトがどんな構造になっているのかを、逐一つまびらかにこんこんと説明してみる。

【1.MFCプロジェクトの作成】
ファイル⇒新規作成⇒プロジェクトで、MFCアプリケーションを指定。場所は、ODA2019upd2を置いてある場所の一つ上階層を指定。

アプリケーションの種類:ダイアログベース
MFCの使用:共有DLLでMFCを使用する
その他指定は、なるべくシンプルなものとする。

【2.ダイアログテンプレート作成】
「…」ボタンで変換元のdwgファイルを選んで変換実行とすれば、同一パス内にdxfファイルを作るという画面設計。

SampleExeDlg.cppを見れば詳細はわかるが、変換実行ボタンの処理だけここに挙げてみる。ExecDwg2Dxfが本プロジェクトの本質の部分であって、この先明らかにしていく部分となる。

void CSampleExeDlg::OnBnClickedButton2()
{
	CString strSrc, strDst;
	m_edtFile.GetWindowText(strSrc);
	if (strSrc.IsEmpty())
	{
		AfxMessageBox(_T("変換元ファイルが指定されていない。"));
		return;
	}
	int pos = strSrc.ReverseFind('.');
	strDst = strSrc.Left(pos + 1) + _T("dxf");
	CString emsg;
	int stat = FALSE;
//	int stat = ExecDwg2Dxf(&m_svcs, strSrc, strDst, emsg);
	if (stat)
		AfxMessageBox(_T("変換成功"));
	else
	{
		CString msg;
		msg.Format(_T("変換失敗(%s)"), emsg);
		AfxMessageBox(msg);
	}
}

【3.64bitプロジェクトに変更】
VisualSutdio画面の上部ソリューションのプラットフォームがx86になっているので、x64に変えておく。今回ODAのモジュールは64bitしかダウンロードしていないので、x86は対象外とする。x86用のODAモジュールをダウンロードすれば、普通に作れるんだけど、手間がかかるんで今回は64bitのみとする。また、これ以降はDebug版のことについてのみ書いていくので、Release版も同じように作ればいいということで理解しておいてほしい。ODAの参照するフォルダが違う程度で、他は全部同じ。

【4.ExServicesをプロジェクトに追加】
ここからがODA固有の処理。C++はアンマネージドコードなんで、いろいろと難しいことをしなければいけないという一例。ここでは何も考えずに以下の処理をやるべし。
プロジェクト内にExServicesというフォルダを作って後述する14個のファイルをコピーしておく。ソリューションエクスプローラのSampleExeを右クリックして追加⇒新しいフィルターとしてExServicesを作って、14個のファイルを既存項目として追加する。14個のファイルの出元や特徴は以下の通り。
※Kernelにあるのは、ODA2019upd2\Kernel\Extensions\ExServices。
※Drawingにあるのは ODA2019upd2\Drawing\Extensions\ExServices。
ExGiRasterImage.cpp Kernelにあるのをそのまま利用。
ExGiRasterImage.h 〃
ExPrintConsole.cpp 〃
ExPrintConsole.h 〃
ExSystemServices.cpp 〃
ExSystemServices.h 〃
OdFileBuf.cpp 〃
OdFileBuf.h 〃
RxSystemServicesImpl.h 〃
ExTtfFileNameByDescriptor.h Kernelにあるのを使うけど、GetVersionExという最近のVisualStudioで使えないAPIを使っているのでコメントアウト。WindowsNT系以外の場合の判断があるが、今さらWinodws Me以前のOSをサポートする必要はないから。
RxSystemServicesImpl.cpp Kernelにあるのを使うけど、_wgetenvというセキュリティ非対応のAPIを使っているのでセキュリティ対応したwgetenv_sを呼ぶように書き換えた。VC2017でWindowsの環境変数を取得する方法を参照。
ExHostAppServices.cpp Drawingにあるのをそのまま利用。
ExHostAppServices.h Drawingにあるのをそのまま利用。
OdActivationInfo アクティベーションファイルなので自社用のライセンスを取得する。

【5.ODAへの参照設定】
1)プロジェクトのプロパティで各種設定を変更。
・全般⇒出力ディレクトリ
$(SolutionDir)$(Platform)\$(Configuration)\となっているので、その後に「bin\」を追加。ビルドした結果のexeとODA用バイナリをbinフォルダに整理して入れるための対処。
・C/C++⇒全般⇒追加のインクルードディレクトリ
../ODA2019upd2/Kernel/Include
../ODA2019upd2/Drawing/Include
ExServices
・C/C++⇒プリプロセッサ⇒プリプロセッサの定義
_TOOLKIT_IN_DLL_
・C/C++⇒詳細設定⇒指定の警告を無効にする
4819
・リンカー⇒全般⇒追加のライブラリディレクトリ
../ODA2019upd2/lib/vc15_amd64dlldbg
・リンカー⇒入力⇒追加の依存ファイル
TD_Alloc.lib
TD_Db.lib
TD_Ge.lib
TD_Root.lib
TD_DbRoot.lib
TD_DbCore.lib
TD_key.lib
2)個別cppのプリコンパイル済みヘッダーを変更
・C/C++⇒プリコンパイル済みヘッダー⇒プリコンパイル済みヘッダーを「使用しない」にする。対象cppは、ExGiRasterImage.cppとExPrintConsole.cppの2つ。

以上の設定が終えてビルドすれば、エラーなくビルドができるはず。でも、実行しようとするとODAバイナリがないからということでエラーが出ちゃう。

【6.ODAバイナリのコピー】
ODA2019upd2\exe\vc15_amd64dlldbgの中の以下ファイルをSampleExe\x64\Debug\binにコピーする。
ACCAMERA_19.12_15.tx
AcMPolygonObj15_19.12_15.tx
ATEXT_19.12_15.tx
ISM_19.12_15.tx
RasterProcessor_19.12_15.tx
RecomputeDimBlock_19.12_15.tx
RText_19.12_15.tx
SCENEOE_19.12_15.tx
TD_Alloc_19.12_15.dll
TD_Db_19.12_15.dll
TD_DbCore_19.12_15.dll
TD_DbEntities_19.12_15.tx
TD_DbIO_19.12_15.tx
TD_DbRoot_19.12_15.dll
TD_Ge_19.12_15.dll
TD_Gi_19.12_15.dll
TD_Root_19.12_15.dll
TD_SpatialIndex_19.12_15.dll
WipeOut_19.12_15.tx
※ここに挙げたdllとtxファイルは、自分で書くコードによっては増やす必要あり。5の1)で指定したlibもしかり。

これでやっとデバッグ実行ができるようになる。SampleExe.exeを実行して終了するだけでメモリーリークが出ているのは、ODA側のバグだろう。あとでその対策を行う。

【7.DWGをDXFに変換するコードを挿入】
※ここで挙げているソースコードはファイル名しか書いてなくて、ソースコードの中身は明示していない。知りたい人がいれば、本記事のコメントで連絡されたし。
1)変換部の追加
以下ファイルをプロジェクトフォルダにコピーして、ソースファイルとヘッダーファイルに既存項目として追加する。
OdaServices.cpp(h) ODAのベースクラスで、ExSystemServicesとExHostAppServicesを継承した独自クラスを作るってこと。サンプルOdaMfcAppのOdaMfcApp.hのようなことをやればよい。
exec.cpp(h) DWGをDXFに変換する実行部(下記の8でコードを一部引用)
Futy.cpp(h) ファイルの存在チェックと削除(ファイル操作しているだけなんで、別になくてもよい)
2)SampleExeDlg.cpp修正
・以下の実行部呼び出し箇所を有効化

int stat = ExecDwg2Dxf(&m_svcs, strSrc, strDst, emsg);

・上部のヘッダー呼び出しに以下3行追加

#include "exec.h"
#include "OdaCommon.h"
#include "OdaServices.h"

・OnInitDialogに処理追加

	// ODA初期化
	try
	{
		odInitialize(&m_svcs);
	}
	catch (OdError& e)
	{
		OdString err = m_svcs.getErrorDescription(e.code());
		AfxMessageBox(_T("ODAエラー:") + err);
		return FALSE;
	}

・デストラクタとして処理追加

CSampleExeDlg::~CSampleExeDlg()
{
	odUninitialize();
}

3)SampleExeDlg.h修正
・ヘッダー呼び出しに以下2行を追加

#include "OdaCommon.h"
#include "OdaServices.h"

・コンストラクションのところに追加

~CSampleExeDlg();

・publicに追加

OdRxObjectImpl m_svcs;

以上で実装が完了なので、ビルドしてデバッグ実行してみる。そのままSampleExe.exeを終了させてもメモリーリークは出ない。m_svcsのodInitialize()とodUninitialize()を、exeの実行と終了時に必ず行うようにしたためと思われる。ExServicesとして追加したコードをプロジェクトに入れただけで、実際の利用をしていない状態だと問題があるのだろう。詳しくはわからんが、このあたりにこだわる必要もないだろう。

【8.DWGをDXFに変換してみる】
デバッグ実行したSampleExe.exeから「…」ボタンを押して適当なdwgファイルを選択。変換実行とすれば、dwgと同じ場所にdxfファイルができる。実際にやっていることは、以下の通りdwgファイルを読み込んで、dwgと同じバージョンでdxfとして書き込んでいるだけ。

pDb = pSvcs->readFile(pSrc, false, false, Oda::kShareDenyNo);
if (!pDb.isNull())
{
	OdWrFileBuf fb(pDst);
	OdDb::SaveType st = OdDb::kDxf;
	pDb->writeFile(&fb, st, pDb->originalFileVersion(), true);
	stat = TRUE;
}

応用として、バージョンを任意のものにしたりdwgで保存するようにすることは容易にできる。また、dwgやdxfのようなファイルそのものだけでなく、ファイル内のブロックやエンティティセクションから特定オブジェクトを読み込んで情報取得したり、削除追加が可能。こうやってAutoCADのデータを読み書きすることは、AutoCADデータを何かに利用したい人には有益なこと。その第一歩をここから学んでくれる人がいたならば、おいらとしても喜ばしい限りだ。

全3回で書いてきた記事は以下の通り。
Teigha改めODAでDWGをDXFに変換するプログラムをつくってみよう!【Part.1】
Teigha改めODAでDWGをDXFに変換するプログラムをつくってみよう!【Part.2】
Teigha改めODAでDWGをDXFに変換するプログラムをつくってみよう!【Part.3】 ※本記事

-DWG, ソフト開発

執筆者:


comment

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

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

関連記事

no image

DWG TrueView

 フリーのDWGビューアです。もちろんDXFも見れます。印刷もできます。いつの間にかAutodeskからリリースされてました。  ここ最近はDWGのビューアを有料にしてたのですけど、ここへきて方針変更 …

no image

受託開発

パッケージソフトの開発にメンバーとして関わって10年、そこそこの売り上げを継続でき、よい結果を出していると思います。ここ最近、少しジリ貧なので、ちょっと厳しいですけど、それはともかく... 近頃、受託 …

no image

TeighaのPDFサポート

AutoCADがPDFアンダーレイ(PDFUNDERLAY)を配置できるように なったのは、AutoCAD2010からだった。 CAD図面の下書きとして、ラスターイメージ(JPEGやTIFF)を配置す …

no image

いたちごっこ1

ソフト開発者とクラッカー。その果てしない戦いの日々をここに記します。現在進行形のその戦いに終止符を打つべく、努力を重ねている今、臨場感をもって伝えられれば、と思います。 その前に、「いたちごっこ」とい …

no image

環境変数TEMPトラブルについて振り返る

プログラムから環境変数TEMPで指定されたフォルダにファイルが作れないことがわかった時点で、この問題は解決したも同じだった。TEMPの値を「%USERPROFILE%\AppData\Local\Te …