C#でAutoCADCHATBOT動作確認に成功!
の記事の続編。
F#はVB.net同様、手動でのパス通しをする羽目になった。
open Autodesk.AutoCAD.Runtime
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
type MyCommands() =
interface IExtensionApplication with
member this.Initialize() =
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nMyCommands initialized")
member this.Terminate() =
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nMyCommands terminated")
[<CommandMethod("bot")>]
member this.ProcessUserInput() =
let doc = Application.DocumentManager.MdiActiveDocument
let ed = doc.Editor
ed.WriteMessage("\nProcessUserInput called")
let userInput = this.GetStringFromUserInput("CAD", "何をしましょうか?")
if userInput.Contains("直線") then
this.CreateLine()
elif userInput.Contains("円") then
this.CreateCircle()
else
ed.WriteMessage("\nそのような操作はできません。")
member private this.CreateLine() =
let doc = Application.DocumentManager.MdiActiveDocument
let ed = doc.Editor
let start_x = this.GetDoubleFromUserInput("始点のX座標を入力してください。")
let start_y = this.GetDoubleFromUserInput("始点のY座標を入力してください。")
let end_x = this.GetDoubleFromUserInput("終点のX座標を入力してください。")
let end_y = this.GetDoubleFromUserInput("終点のY座標を入力してください。")
this.DrawLine(start_x, start_y, end_x, end_y)
member private this.CreateCircle() =
let doc = Application.DocumentManager.MdiActiveDocument
let ed = doc.Editor
let center_x = this.GetDoubleFromUserInput("中心のX座標を入力してください。")
let center_y = this.GetDoubleFromUserInput("中心のY座標を入力してください。")
let radius = this.GetDoubleFromUserInput("半径を入力してください。")
this.DrawCircle(center_x, center_y, radius)
member private this.GetDoubleFromUserInput(prompt: string) : double =
let ed = Application.DocumentManager.MdiActiveDocument.Editor
let mutable result = ed.GetDouble(prompt)
while result.Status <> PromptStatus.OK do
ed.WriteMessage("\n数値を入力してください。")
result <- ed.GetDouble(prompt)
result.Value
member private this.GetStringFromUserInput(title: string, prompt: string) : string =
let ed = Application.DocumentManager.MdiActiveDocument.Editor
(ed.GetString(prompt)).StringResult
member private this.DrawLine(startX: double, startY: double, endX: double, endY: double) =
let doc = Application.DocumentManager.MdiActiveDocument
let db = doc.Database
use tr = db.TransactionManager.StartTransaction()
let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
let btr = tr.GetObject(bt.[BlockTableRecord.ModelSpace], OpenMode.ForWrite) :?> BlockTableRecord
let startPoint = Point3d(startX, startY, 0.0)
let endPoint = Point3d(endX, endY, 0.0)
let line = new Line(startPoint, endPoint)
btr.AppendEntity(line) |> ignore
tr.AddNewlyCreatedDBObject(line, true) |> ignore
tr.Commit()
member private this.DrawCircle(centerX: double, centerY: double, radius: double) =
let doc = Application.DocumentManager.MdiActiveDocument
let db = doc.Database
use tr = db.TransactionManager.StartTransaction()
let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
let btr = tr.GetObject(bt.[BlockTableRecord.ModelSpace], OpenMode.ForWrite) :?> BlockTableRecord
let centerPoint = Point3d(centerX, centerY, 0.0)
let circle = new Circle(centerPoint, Vector3d.ZAxis, radius)
btr.AppendEntity(circle) |> ignore
tr.AddNewlyCreatedDBObject(circle, true) |> ignore
tr.Commit()
ACETUCS-BUTTON
というコマンドが勝手に呼び出され、ロード中・・・と表示されたままフリーズ・
誰もACETUCS-BUTTONなんていうコマンドを入力した覚えがないんだけど。
F#は使えない言語ということでソッコー没!
次はC++でためしてみることになった。
どうなるかわからんが、とりあえずChatGPTの吐いたソースコードをここに投げておこう。
#include "acutads.h"
#include "acedads.h"
#include "acdocman.h"
#include "dbents.h"
#include "dbmain.h"
#include "dbsymtb.h"
#include "dbapserv.h"
#include "geassign.h"
#include "acarray.h"
class MyCommands
{
public:
static void ProcessUserInput()
{
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTable* pBlockTable;
AcDbBlockTableRecord* pBlockTableRecord;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();
ACHAR szPrompt[512];
acutPrintf(_T("\nCAD、何をしましょうか?: "));
acedGetString(0, szPrompt);
CString userInput = szPrompt;
if (userInput.Find(_T("直線")) != -1)
{
CreateLine(pBlockTableRecord);
}
else if (userInput.Find(_T("円")) != -1)
{
CreateCircle(pBlockTableRecord);
}
else
{
acutPrintf(_T("\nそのような操作はできません。"));
}
pBlockTableRecord->close();
}
private:
static void CreateLine(AcDbBlockTableRecord* pBlockTableRecord)
{
double start_x = GetDoubleFromUserInput(_T("始点のX座標を入力してください。"));
double start_y = GetDoubleFromUserInput(_T("始点のY座標を入力してください。"));
double end_x = GetDoubleFromUserInput(_T("終点のX座標を入力してください。"));
double end_y = GetDoubleFromUserInput(_T("終点のY座標を入力してください。"));
AcDbLine* pLine = new AcDbLine(AcGePoint3d(start_x, start_y, 0), AcGePoint3d(end_x, end_y, 0));
pBlockTableRecord->appendAcDbEntity(pLine);
pLine->close();
}
static void CreateCircle(AcDbBlockTableRecord* pBlockTableRecord)
{
double center_x = GetDoubleFromUserInput(_T("中心のX座標を入力してください。"));
double center_y = GetDoubleFromUserInput(_T("中心のY座標を入力してください。"));
double radius = GetDoubleFromUserInput(_T("半径を入力してください。"));
AcDbCircle* pCircle = new AcDbCircle(AcGePoint3d(center_x, center_y, 0), AcGeVector3d::kZAxis, radius);
pBlockTableRecord->appendAcDbEntity(pCircle);
pCircle->close();
}
static double GetDoubleFromUserInput(const ACHAR* prompt)
{
double value;
ACHAR szPrompt[512];
acutPrintf(prompt);
acedInitGet(0, _T("Cancel"));
if (RTNORM != acedGetReal(szPrompt, &value))
{
acutPrintf(_T("\n数値を入力してください。"));
acutPrintf(_T("\n操作をキャンセルしました。"));
acedGetPoint(nullptr, _T("\n続行するにはリターン キーを押してください。"));
acutPrintf(_T("\n"));
return -1.0;
}
return value;
}
};
extern "C" AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
switch (msg)
{
case AcRx::kInitAppMsg:
acrxDynamicLinker->unlockApplication(pkt);
acrxRegisterAppMDIAware(pkt);
break;
case AcRx::kUnloadAppMsg:
// Do nothing
break;
}
return AcRx::kRetOK;
}
extern "C" void
ProcessUserInput()
{
MyCommands::ProcessUserInput();
}