-
-
Notifications
You must be signed in to change notification settings - Fork 150
Jig System
AutoCAD relies on the AcEdJig framework to provide real-time visual feedback while acquiring user input. While powerful, that system separates prompting, preview rendering, and input sampling across multiple overridden methods—often spreading logic across different functions and lifecycle stages. CAD-Viewer reimagines this concept for the web by introducing a unified, TypeScript-driven jig mechanism that integrates seamlessly with prompt input. Instead of managing drag loops or sampler status codes, developers attach a jig directly to prompt options, keeping dynamic preview logic, user input, and final entity creation together in a single, readable workflow.
The Jig system in CAD-Viewer enables interactive previews and dynamic entity creation, offering a workflow similar to AutoCAD’s AcEdJig (ObjectARX). A jig manages a temporary preview entity that updates continuously based on cursor movement or incremental user input.
Use cases include:
- Interactive geometry creation (point, circle, polyline, etc.)
- Live distance or angle measurement
- Real‑time modification of existing entities
However, CAD-Viewer introduces a simpler, more cohesive, and more TypeScript‑friendly design, reducing the structural complexity typically found in AutoCAD jigs.
In AutoCAD, prompts and jigs are separate mechanisms. Jig execution requires overriding sampler(), worldDraw(), and calling drag().
In CAD-Viewer, prompts can directly carry a jig instance:
const opts = new AcEdPromptDistanceOptions('Specify radius:')
opts.jig = new CircleJig(view, center)
const radius = await editor.getDistance(opts)This design:
- Automatically links user input to live preview
- Eliminates manual drag‑loop management
➡️ Result: less boilerplate, more consistency.
As you can see in AutoCAD AcEdJig Sample Code, AutoCAD separates input logic to create one ellipse into multiple places.
-
createEllipse()— acquire ellipse center point -
sampler()— acquire the major axis endpoint and the distance from ellipse center to minor axis endpoint
In CAD-Viewer, the entire dynamic input workflow is expressed sequentially as follows.
const center = await editor.getPoint(pointOpts)
radiusOpts.jig = new CircleJig(view, center)
const radius = await editor.getDistance(radiusOpts)➡️ User input, jig preview, and final geometry are managed in the same block of code.
AcEdPreviewJig<T> is a TypeScript-based class that manages transient preview entities:
| AutoCAD AcEdJig | Web CAD Jig (AcEdPreviewJig) |
|---|---|
sampler() |
update(value: T) |
startJig() |
setEntity() |
drag() |
Controlled externally via JS events |
Features:
- Uses a generic type
Tto handle multiple input types (point, distance, angle, etc.) - Integrates with
AcEdBaseViewto render transient entities - Supports preview entities implementing
onJigUpdate(value: T)for dynamic geometry updates - Allows clean termination of the jig using
end()
Updates the preview entity according to user input. This is the equivalent of AutoCAD's sampler().
Renders the preview entity in the associated view, similar to AutoCAD’s worldDraw().
Clears the transient entity and finalizes the jig session.
Getter for the current preview entity.
You need to create a class extending AcEdPreviewJig<T> for the specific entity. For example, creating a circle jig:
import { AcDbCircle, AcGePoint3dLike } from '@mlightcad/data-model'
import { AcEdPreviewJig, AcEdBaseView } from '@mlightcad/cad-simple-viewer'
export class AcApCircleJig extends AcEdPreviewJig<number> {
private _circle: AcDbCircle
constructor(view: AcEdBaseView, center: AcGePoint3dLike) {
super(view)
this._circle = new AcDbCircle(center, 0)
}
get entity(): AcDbCircle {
return this._circle
}
update(radius: number) {
this._circle.radius = radius
}
}Explanation:
- The jig manages a transient
AcDbCircle. - The
updatemethod dynamically changes the radius based on user input.
You can integrate the jig in a command to interactively create the entity:
import { AcEdCommand, AcApDocManager, AcEdPromptPointOptions, AcEdPromptDistanceOptions } from '@mlightcad/cad-simple-viewer'
import { AcApCircleJig } from './AcApCircleJig'
export class AcApCircleCmd extends AcEdCommand {
async execute(context) {
// Step 2a: Acquire center point
const centerPrompt = new AcEdPromptPointOptions('Specify center of circle:')
const center = await AcApDocManager.instance.editor.getPoint(centerPrompt)
// Step 2b: Acquire radius using Jig
const radiusPrompt = new AcEdPromptDistanceOptions('Specify radius of circle:')
radiusPrompt.jig = new AcApCircleJig(context.view, center)
const radius = await AcApDocManager.instance.editor.getDistance(radiusPrompt)
// Step 2c: Add circle to database
const circle = new AcDbCircle(center, radius)
context.doc.database.tables.blockTable.modelSpace.appendEntity(circle)
}
}Workflow:
- Prompt user for the center of the circle.
- Create a circle jig attached to the center.
- Prompt user for the radius, with interactive preview.
- Commit the finalized circle to the database.
For a complete and up-to-date guide to AcEditor input APIs, prompt options, keyword rules, and prompt result handling, see: