Multi-Entity Interactive Placement & Dynamic Dimensioning with DrawJig and EntityJig (dev-cookbook-25)
Master EntityJig and DrawJig in GstarCAD 2027 C# .NET to build interactive rubber-band previews for structural trusses, pipe assemblies, and dynamic angular dimensions.
1. Choosing Between `EntityJig` and `DrawJig` in GstarCAD `.NET`
Interactive graphical placement—where geometry dynamically stretches, rotates, and displays live dimensional feedback at 60 FPS as the engineer moves the crosshair—is powered by the Jig Engine (`Gssoft.GstarCAD.EditorInput`) in GstarCAD 2027. The SDK provides two abstract base classes tailored to different geometric cardinalities:
EntityJig(Single Database Entity): Wraps exactly one memory-resident `Entity` instance (such as a single `BlockReference`, `Polyline`, or custom `AcDbEntity`). It supports built-in Dynamic Input (`DIMINPUT`) dimensional heads-up boxes via `DynamicDimensionDataCollection`.DrawJig(Multi-Entity Assemblies & Procedural Previews): Does not bind to a single entity. Instead, its `WorldDraw(WorldDraw draw)` override allows you to render dozens of synchronized primitives—such as a complete steel portal frame (two columns, two rafters, haunch stiffeners, and live span labels)—simultaneously during mouse drag before appending them to Model Space in a single transaction.
2. C# .NET Implementation: Multi-Entity Structural Portal Frame `DrawJig`
The C# `DrawJig` below prompts the engineer for a base point, tracks the cursor via `Prompts.AcquirePoint()`, suppresses micro-jitter below `1e-4` mm, and renders a live multi-member steel frame preview before committing the entities to the database:
using System;
using Gssoft.GstarCAD.Runtime;
using Gssoft.GstarCAD.ApplicationServices;
using Gssoft.GstarCAD.DatabaseServices;
using Gssoft.GstarCAD.EditorInput;
using Gssoft.GstarCAD.Geometry;
using Gssoft.GstarCAD.GraphicsInterface;
namespace GstarCadSamples.JigEngine
{
public class PortalFrameDrawJig : DrawJig
{
private readonly Point3d _basePt;
private Point3d _cursorPt;
private readonly double _columnHeight;
public PortalFrameDrawJig(Point3d basePt, double columnHeight)
{
_basePt = basePt;
_cursorPt = basePt + new Vector3d(6000.0, 0, 0);
_columnHeight = columnHeight;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions opts = new JigPromptPointOptions("
Specify right column base point: ")
{
BasePoint = _basePt,
UseBasePoint = true,
Cursor = CursorType.RubberBand,
UserInputControls = UserInputControls.Accept3dCoordinates
};
PromptPointResult res = prompts.AcquirePoint(opts);
if (res.Status != PromptStatus.OK) return SamplerStatus.Cancel;
// Prevent redundant WorldDraw calls when mouse hasn't moved
if (_cursorPt.DistanceTo(res.Value) < 1e-4)
return SamplerStatus.NoChange;
_cursorPt = res.Value;
return SamplerStatus.OK;
}
protected override bool WorldDraw(WorldDraw draw)
{
Vector3d spanVec = _cursorPt - _basePt;
if (spanVec.Length < 500.0) return true;
Point3d eaveLeft = _basePt + new Vector3d(0, _columnHeight, 0);
Point3d eaveRight = new Point3d(_cursorPt.X, _basePt.Y + _columnHeight, 0);
Point3d apexPt = new Point3d((_basePt.X + _cursorPt.X) * 0.5, _basePt.Y + _columnHeight + (Math.Abs(spanVec.X) * 0.15), 0);
WorldGeometry geo = draw.Geometry;
geo.WorldLine(_basePt, eaveLeft); // Left Column
geo.WorldLine(new Point3d(_cursorPt.X, _basePt.Y, 0), eaveRight); // Right Column
geo.WorldLine(eaveLeft, apexPt); // Left Rafter
geo.WorldLine(apexPt, eaveRight); // Right Rafter
return true;
}
}
}
3. Critical Jig Memory & Disposal Discipline in `.NET`
Inside `DrawJig.WorldDraw()`, if you instantiate temporary in-memory `Entity` objects (such as `new MText()` or `new Hatch()`) and pass them to `draw.Geometry.Draw(tempEnt)`, you **must** wrap those temporary non-database-resident entities inside a `using (...)` block so their underlying C++ `AcDbObject` wrappers are deterministically disposed on every mouse frame. Failing to dispose non-DBRO entities inside a 60 Hz Jig loop leaks unmanaged heap memory and can trigger garbage-collection pauses mid-drag.
4. Adding Interactive Keyword Switching (`[Flip/SectionSize/PinBase]`) Inside `Sampler()`
To let the engineer switch steel profile sizes or flip frame orientation mid-drag without exiting the `DrawJig`, register keywords on your `JigPromptPointOptions` via `opts.Keywords.Add("Flip")` and `opts.Keywords.Add("Profile")` before calling `prompts.AcquirePoint(opts)`.
When the user presses `F` or clicks `Flip` on the command line, `res.Status` returns `PromptStatus.Keyword` and `res.StringResult` contains `"Flip"`. Toggle your internal boolean `_isFlipped = !_isFlipped` and return `SamplerStatus.OK` so `WorldDraw()` immediately redraws the mirrored portal frame on the very next frame.
Validate This Workflow in GstarCAD 2027
Engineered by Suzhou Gstarsoft Co., Ltd. (SSE: 688657), GstarCAD 2027 delivers 100% native AC1032 DWG binary fidelity, perpetual licensing sovereignty, and zero-day AutoCAD command parity.