Architecture Plugin
Architecture Plugin
The Architecture Plugin (architecture-plugin) provides WebCAD with a complete set of architectural floor plan drawing tools, including axis grid, columns, walls, doors, windows, staircases, balconies, room annotations, architectural symbols, and more, complying with GB/T 50001-2017 and GB/T 50104-2010 national standards.
Feature Overview
| Category | Command | Description |
|---|---|---|
| Axis Grid | BINDRAWAXISGRID | Draw straight axis grid (input horizontal and vertical spacing) |
| Axis Grid | BINLABELAXIS | Axis labeling (auto-numbering 1,2,3... / A,B,C...) |
| Column | BINDRAWCOLUMN | Draw columns (rectangular/circular, supports batch placement along axis grid) |
| Column | BINCOLUMNTOAXIS | Align columns to axis grid (place columns at all axis intersections) |
| Wall | BINDRAWWALL | Draw walls (continuous drawing, supports undo/close) |
| Wall | BINWALLFROMAXIS | Generate walls from axis (auto-generate walls from axis grid) |
| Wall | BINEDITWALL | Edit wall |
| Door | BININSERTDOOR | Insert door (single/double/sliding, auto-associate with wall) |
| Window | BININSERTWINDOW | Insert window (standard/bay, auto-associate with wall) |
| Staircase | BINDRAWSTAIR | Draw staircase (straight run/double run) |
| Balcony | BINDRAWBALCONY | Draw balcony |
| Room | BINSEARCHROOM | Room search (click to place room annotation) |
| Room | BINLABELROOM | Room annotation (name + area) |
| Symbol | BINELEVMARK | Elevation symbol |
| Symbol | BINSECTIONMARK | Section symbol |
| Symbol | BINNORTHARROW | North arrow |
| Symbol | BININDEXMARK | Index symbol |
| Dimension | BINARCHDIM | Architectural dimension annotation |
| Dimension | BINAXISDIM | Axis grid dimension |
| Tools | BINARCHTOOLBAR | Open architecture floating toolbar |
| Tools | BINDEMOFLOORPLAN | One-click generate sample floor plan |
Installation and Loading
Method 1: loadByName (Recommended)
const pm = PluginManager.getInstance();
// Load by package name, skip if already loaded, wait if loading in progress
await pm.loadByName('vcad-plugin-architecture');loadByName automatically loads from ./plugins/vcad-plugin-architecture.js, or you can customize the path:
await pm.loadByName('vcad-plugin-architecture', {
baseUrl: '/static/plugins/'
});Method 2: loadFromUrl
const pm = PluginManager.getInstance();
await pm.loadFromUrl('./plugins/vcad-plugin-architecture.js');Method 3: MainView Configuration
const cadView = new MainView({
plugins: [
{ url: './plugins/vcad-plugin-architecture.js' }
]
});Create Architectural Entities via SDK API
After the plugin is loaded, you can obtain architectural entity classes via window.vjcadArchEntities and create architectural entities directly using the SDK API.
Get Entity Classes
await pm.loadByName('vcad-plugin-architecture');
const {
AxisGridEnt, ColumnEnt, WallEnt,
DoorEnt, WindowEnt, StairEnt, BalconyEnt,
ElevationMarkEnt, SectionMarkEnt,
} = window.vjcadArchEntities;Create Axis Grid
// Horizontal spacing 3600, 3900, 5700mm, vertical spacing 4200, 2100, 4200mm
const grid = AxisGridEnt.create(
new Point2D(0, 0), // Origin
[3600, 3900, 5700], // Horizontal spacing array
[4200, 2100, 4200] // Vertical spacing array
);
Engine.addEntities([grid]);Create Wall
// From (0,0) to (13200,0), wall thickness 240mm, centerline alignment
const wall = WallEnt.create(
new Point2D(0, 0), // Start point
new Point2D(13200, 0), // End point
240 // Wall thickness (mm)
);
Engine.addEntities([wall]);Create Door/Window and Associate with Wall
The association between doors/windows and walls is the core feature of the Architecture Plugin. After association:
- Walls automatically open at door/window positions
- Doors/windows can only move along the wall centerline
- Doors/windows follow when the wall moves
- Walls automatically restore when doors/windows are deleted
// Create door
const door = DoorEnt.create(
new Point2D(5000, 0), // Position (on wall)
'single', // Type: single/double/sliding
900 // Door width (mm)
);
door.rotation = 0; // Align with wall direction
door.wallThickness = 240; // Wall thickness
// Create window
const window = WindowEnt.create(
new Point2D(2000, 0),
'standard', // Type: standard/bay
1500 // Window width (mm)
);
window.rotation = 0;
window.wallThickness = 240;
// Add to canvas first (to obtain entity ID)
Engine.addEntities([wall, door, window]);
// Establish bidirectional association
door.wallHandle = String(wall.id);
wall.doorWindowHandles = [String(door.id), String(window.id)];
window.wallHandle = String(wall.id);
// Trigger wall redraw (display opening effect)
wall.setModified();Complete Example
Online Example
Architecture Plugin SDK API Example{target="_blank"}
Technical Design
Custom Entity System
All architectural components in the Architecture Plugin inherit from CustomEntityBase, decomposing complex architectural graphics into basic primitives (LineEnt, ArcEnt, PolylineEnt, etc.) via the buildNestEnts() method:
CustomEntityBase
├── AxisGridEnt → LineEnt[] + CircleEnt + TextEnt (axis lines + axis labels)
├── ColumnEnt → PolylineEnt + HatchEnt (rectangular/circular fill)
├── WallEnt → LineEnt[] (double-line wall, supports openings)
├── DoorEnt → LineEnt + ArcEnt (door leaf + arc)
├── WindowEnt → PolylineEnt + LineEnt[] (rectangular frame + glass lines)
├── StairEnt → LineEnt[] + PolylineEnt (steps + outline + arrow)
├── BalconyEnt → PolylineEnt + LineEnt (U-shaped outline + railing)
├── ElevationMarkEnt → LineEnt[] + TextEnt (triangle + elevation value)
└── SectionMarkEnt → LineEnt[] + TextEnt (section line + arrow + number)Each entity implements:
getSnapPoints()— Object snap pointsgetGripPoints()— Grip edit pointsgripEdit()— Grip move handlinggetPropertyInfo()— Property panel displayclone()/move()/rotate()/scale()/mirror()— Geometric transformsgetEntityData()/setEntityData()/fromDb()— Serialization
Wall-Door/Window Association
This is the most core technical design of the Architecture Plugin.
Data Model
WallEnt:
doorWindowHandles: string[] ← List of associated door/window entity IDs
DoorEnt / WindowEnt:
wallHandle: string ← Associated wall entity IDBidirectional references are established via entity IDs (entity.id).
Association Reaction Flow
Wall Auto-Opening Algorithm
Core logic in WallEnt.buildNestEnts():
- Iterate
doorWindowHandles, look up each door/window entity inEngine.currentSpace.items - Project door/window position onto wall centerline, compute parameter
t(0~1) along wall direction - Compute opening range
[tStart, tEnd]from door/window width - Merge all opening ranges and wall intersection gaps
- Draw wall lines in segments, skipping opening segments
// Simplified opening algorithm
const openings = collectOpeningRanges(); // [{tStart, tEnd}, ...]
openings.sort((a, b) => a.tStart - b.tStart);
const segments = [];
let cursor = 0;
for (const op of openings) {
if (op.tStart > cursor) segments.push({ tStart: cursor, tEnd: op.tStart });
cursor = Math.max(cursor, op.tEnd);
}
if (cursor < 1) segments.push({ tStart: cursor, tEnd: 1 });
// Draw wall lines only within segments
for (const seg of segments) {
drawWallLine(seg.tStart, seg.tEnd);
}Door/Window Constrained Movement Along Wall
In DoorEnt.gripEdit() and WindowEnt.gripEdit():
// When center grip moves, constrain to wall centerline
if (this._wallHandle) {
const wall = findWallById(this._wallHandle);
if (wall) {
const proj = projectPointOnSegment(newPos, wall.startPoint, wall.endPoint);
const dToStart = dist(proj, wall.startPoint);
const dToEnd = dist(proj, wall.endPoint);
// Ensure door/window does not exceed wall bounds
if (dToStart >= halfWidth && dToEnd >= halfWidth) {
this._position = proj;
}
}
}Event Listening Mechanism (WallService)
WallService starts event listeners when the plugin activates:
| Event | Handling |
|---|---|
EntityAdded | Process topology when wall is added; auto-associate nearest wall when door/window is added |
EntityModified | Re-associate when door/window is modified; update associated door/window positions when wall is modified |
EntitiesErasing | Remove association from wall before door/window deletion; clear door/window wallHandle before wall deletion |
Entity Lifecycle and isAlive Guard
Engine entity deletion flow: EntitiesErasing → set isAlive=false → setModified() → EntitiesErased.
Step 3 queues an EntityModified event; when resumeEvents runs, modifiedHandler may execute associateDoorWindow on already-dead entities, re-associating zombie references to the wall. Therefore, WallService checks isAlive on these critical paths:
// modifiedHandler: Skip deleted entities, prevent zombie re-association
if ((entity as any).isAlive === false) return;
// associateDoorWindow: Do not associate deleted doors/windows
if ((entity as any).isAlive === false) return;
// collectOpeningRanges: Do not generate openings for deleted doors/windows
if ((ent as any).isAlive === false) break;
// updateDoorWindowsOnWallChange: Do not update deleted doors/windows
if ((ent as any).isAlive === false) continue;Complete event chain for wall auto-restore after door/window deletion:
1. User deletes door/window → Engine triggers EntitiesErasing
2. erasingHandler → dissociateDoorWindow:
- Remove door/window ID from wall.doorWindowHandles
- wall.setModified() mark wall for redraw
3. Engine sets entity.isAlive = false
4. Engine calls entity.setModified() → queues EntityModified event
5. modifiedHandler detects isAlive===false → skip (no re-association)
6. Wall buildNestEnts → collectOpeningRanges:
- doorWindowHandles already cleared (or entity for residual ID has isAlive=false and is skipped)
- Returns empty opening range → wall lines drawn completelyWall Topology Processing
When multiple walls intersect, WallService.processWallTopology() automatically handles wall line cleanup at intersections:
| Intersection Type | Handling |
|---|---|
| L-type (two wall endpoints meet) | Remove end cap lines, wall lines meet naturally |
| T-type (one wall endpoint meets another wall mid-point) | Continuous wall opens gap at intersection, terminating wall removes end cap |
| Cross-type (two walls meet at mid-points) | Both walls open gaps at intersection |
Automatic Layer Management
All architectural entities automatically create and use national standard layers; colors follow layers via ByLayer (color=256):
| Layer | Color | Purpose |
|---|---|---|
| A_AXIS | Red (1) | Axis lines |
| A_COLU | Yellow (2) | Columns |
| A_WALL | White (7) | Walls |
| A_DOOR | Cyan (4) | Doors |
| A_WIND | Cyan (4) | Windows |
| A_STRS | Green (3) | Staircases |
| A_ROOM | Magenta (6) | Rooms |
| A_BALC | Green (3) | Balconies |
| A_DIMS | White (7) | Dimensions |
| A_SYMB | Red (1) | Symbols |
Plugin Structure
architecture-plugin/
├── src/
│ ├── index.ts # Plugin entry (register entities/commands/UI)
│ ├── icons.ts # SVG icons
│ ├── constants.ts # Architectural specification constants
│ ├── utils/
│ │ ├── ArchLayerUtils.ts # Automatic layer management
│ │ └── ArchGeomUtils.ts # Architectural geometry calculations
│ ├── entities/
│ │ ├── AxisGridEnt.ts # Axis grid
│ │ ├── WallEnt.ts # Wall (including opening logic)
│ │ ├── DoorEnt.ts # Door (including wall constraint)
│ │ ├── WindowEnt.ts # Window (including wall constraint)
│ │ └── ... # Other entities
│ ├── commands/ # Interactive drawing commands
│ │ ├── axis/ # Axis grid commands
│ │ ├── wall/ # Wall commands
│ │ ├── door/ # Door commands
│ │ ├── window/ # Window commands
│ │ └── ...
│ └── services/
│ ├── WallService.ts # Wall association management + topology + event listening
│ └── AxisService.ts # Axis grid query serviceRibbon and Menu
The plugin creates an "Architecture" tab in the Ribbon with the following groups:
| Group | Display Mode | Buttons |
|---|---|---|
| Axis Grid & Columns | large | Draw axis grid, Draw column + More (axis labeling, align columns to axis) |
| Walls | large | Draw wall, Generate wall from axis + More (edit wall) |
| Doors & Windows | large | Insert door, Insert window |
| Stairs & Others | compact | Draw staircase, Balcony |
| Rooms | compact | Room search, Room annotation |
| Symbols & Dimensions | small-icons | Elevation, Section, North arrow, Index, Architectural dimension, Axis dimension |
| Tools | large | Sample floor plan, Architecture toolbar |
It also creates an "Architecture" top-level menu and a floating toolbar (5x3 layout covering the most common operations).