BendTech.cs
BendTech is the central class that orchestrates everything about press-brake bending
for one part: it holds the ordered list of bend operations, the machine setups, the tool
inventory, the simulation state, and the NC output pipeline.
File: Core/Bend/BendTech.cs
Declaration:
public sealed partial class BendTech : Tech, ISheafEditFilter, ISimRoot
It is sealed (no subclasses), partial (additional methods live in companion files),
and implements:
-
Tech— the base class shared byBendTech,FoldTech, andFlatTech; holds thePart Ownerreference and common dirty/save infrastructure -
ISheafEditFilter— controls which settings rows the UI shows and what value ranges are valid for the selected machine -
ISimRoot— marks this as the root of a simulation state machine (drivesSimStage,SimStep,Frame)
1. Construction: Make and the Constructor
1.1. Entry point: BendTech.Make
public static EResult Make (Part part, BendMachine bmc, EDoFlags flags = 0)
File: Core/Bend/BendTech.cs:1322
Make is the public factory. It validates preconditions, then creates a BendTech in
three steps:
-
Checks
part.Model != null(returnsEResult.NeedModelif absent). -
Calls
part.Model.PrepareForBendOrFold()— ensures the model is ready for the bend pipeline (computes colliders, refines faces). -
Creates
new BendTech(part, bmc, flags)— the real work happens in the constructor.
After construction, Make checks guard conditions:
-
If double-sheet bends are present but the drawing is not yet unfolded, a second construction pass is done.
-
If the operation count exceeds
MAXBENDCNT(60) but no sequence has been set, a random sequence is auto-assigned so the user can edit it interactively. -
If all operations are skipped (
EResult.NoValidBends), construction fails.
On success, part.BendTech = bt is set.
1.2. The constructor
BendTech (Part owner, BendMachine bmc, EDoFlags flags = 0) : base(owner)
File: Core/Bend/BendTech.cs:19
The constructor performs seven sequential tasks.
1.2.1. Task 1 — Machine initialisation
Copies machine defaults into the tech’s settings:
-
BTablePosition— if the machine has a retractable support table -
BG1Variant/BG2Variant— back-gauge finger variants -
BGMovePath— how the back-gauge retracts between bends
1.2.2. Task 2 — Hem and flat-bend phase setup
Iterates every E3Flex and assigns PhaseSplits to flexes that need multi-phase
bending:
| Condition | Action |
|---|---|
|
Splits into two phases at |
|
Splits at 0.5 (pre-bend first half, flatten second half) |
|
Resets kind to |
1.2.3. Task 3 — Grouping simultaneous bends
Bends that share the same X-silhouette can be performed in one ram stroke. The constructor finds these groups:
// For each unprocessed flex, collect all other flexes that can be grouped with it
if (flex.CanGroupWith(flex2, pose)) { todo.Add(flex2); flexes[j] = null; }
// Also collect double-sheet partners
if (todo.Any(a => a.CanGroupDoubleSheet(flex2))) { todo.Add(flex2); flexes[j] = null; }
For each resulting group, one BendOp is created per phase:
var bop = new BendOp(this, todo, FX.MakeArray(j, todo.Count));
If a .geo file supplied a PrebendAngle for this flex, that phase split is locked
(bop.IsPrebendLocked = true).
Operations are then ordered with ops.ValidOrder() — the method that ensures no
operation deforms a flange that another operation still needs to access.
1.2.4. Task 4 — Un-grouping degenerate groups
A grouped bend is split back into individual ops when the bounding X-span is more than 100× wider than the sum of the individual bend spans. This handles parts where two nearly-coincident bend lines are separated by a large gap that would require an impractically long tool station.
1.2.5. Task 5 — Manual-only flange-in-hole bends
Bends where all X-spans are short (< 4 mm) and at least one flex has a flange completely inside a hole are moved to a "later" list. These flanges cannot be reached by a standard press-brake tool and must be processed manually. If no other bends remain after this filter, the deferred bends are restored.
1.2.6. Task 6 — Z-bend detection
A Z-bend is a pair of adjacent, parallel, opposite-direction bends close enough to be formed in a single stroke with a special Z-punch and Z-die. The constructor scans all op pairs:
(bool found, BDie zDie) = AnyZBendTools(opA, opB);
AnyZBendTools checks:
-
The two bends are parallel (cosine check, < 1° deviation)
-
They are neighbours in the X-direction (
IsNeighborOf) -
They have opposite fold directions
-
Their deforming lengths are similar (within 25 %)
-
A suitable Z-punch/die exists in the inventory for their angles
-
The inter-bend gap is within
MaxZBendGap(computed from the largest Z-die in inventory × 1.6) -
Hint names on the
E2Bendline(if!Settings.IgnoreBToolHints) are compatible
Matched pairs are grouped into EBendKind.ZBendAirBend or EBendKind.ZBendCoining.
1.2.7. Task 7 — Tool inventory selection
// 1. Try a part-specific .btools file next to the .fx file
Inventory = BToolList.Load(Path.ChangeExtension(srcFile, ".btools"));
// 2. Fall back to the rule-selected tool list
Inventory = BToolLists.SelectFor(Owner, BMachine);
The Inventory (BToolList) is the set of tools the auto-tooler is allowed to use.
2. Core Data Structures
2.1. mOps — the operation list
List<BendOp> mOps = [];
public List<BendOp> Ops => mOps;
This is the ordered list of bend operations — the bend sequence. Each BendOp wraps
one or more E3Flex objects (a group of simultaneous bends), one phase, and all
computed tooling data (punch, die, back-gauge positions, ACB settings).
2.2. Setups — derived from mOps
public IList<BendSetup> Setups {
get {
List<BendSetup> setups = [];
foreach (var setup in mOps.Select(a => a.Setup).NonNull())
if (!setups.Contains(setup)) setups.Add(setup);
return setups;
}
}
A BendSetup is one machine configuration (a specific arrangement of tools clamped on
the beam). Setups are not stored — they are derived by enumerating the unique
BendOp.Setup references in sequence order. When the setup changes between two
consecutive operations, a new NC program segment must be started.
2.3. NCCount
public int NCCount {
get {
BendSetup setup = null;
return Ops.Where(a => a.CanProcess).Count(op => FX.Set(ref setup, op.Setup));
}
}
Counts setup-boundary transitions among the processable operations. Each transition produces a separate NC program file (or a separate program segment on machines that put everything in one file).
2.4. SequenceSign
public string SequenceSign
A compact string encoding the full bend sequence. Grammar:
sequence = op (',' op)*
op = single | group
single = uid ['.' phase]
group = single ('+' single)+
uid = integer (E3Flex.UID)
phase = integer (0-based phase index within the flex's PhaseSplits)
Example: "3, 1+2, 4.0, 4.1" means:
-
Bend flex 3 (single, default phase 0)
-
Bend flex 1 and 2 simultaneously (grouped)
-
Pre-bend flex 4 (phase 0)
-
Complete flex 4 (phase 1)
Setting SequenceSign calls SetSequence, locks the sequence
(IsSequenceLocked = true), and triggers a re-tooling pass.
2.5. EFlags (internal)
| Flag | Bit | Meaning |
|---|---|---|
|
0 |
True after the first successful tooling pass |
|
1 |
User-locked sequence; re-tooling preserves |
|
3 |
Set by |
|
4 |
Suppress GAP strategy adjustments for this tech |
|
5 |
This is one side of a split tandem-machine pair |
|
6 |
Generate BNC with the part in the overbent state (pre-spring-back) |
|
7 |
Any manual edit has been made since construction |
|
8 |
The bend-tech UI has been shown at least once |
|
9 |
Tool changes that would alter the flat drawing are forbidden |
3. Key Properties
3.1. BMachine
The BendMachine this tech was created for. Provides machine geometry (table length,
back-gauge count and surfaces, tool clamping constraints), available NC extensions,
post-processor name, and capability flags (HasACBLaser, HasBendAids, IsTandem,
etc.).
3.2. Inventory
The BToolList (set of available tools). Lazily falls back to _machine.Inventory
(the machine’s default tool list) if no overriding list was set. Changing Inventory
resets _minPunchRadius so the next access recomputes the tightest available tip.
3.3. CodeDirty
public bool CodeDirty { get; set; }
Set to true whenever anything changes that invalidates the generated NC code (tool
assignment, sequence change, machine parameter change). Drives GenAllOutputs to
regenerate output files on the next save.
Side effects when set to true:
-
Clears the private API view-model (
_APIVM) -
Clears the robot cell path cache (
mCell.RobotCode = null) -
Resets all
op.FlexCellGripCS(robot gripper coordinate systems) -
Records the current user as the part author in
Owner.Info.Dict["Author"]
3.4. QStatus
public EQStatus QStatus // OK, Warning, Error, Unknown
Computed on demand by summing WarningCount and ErrorCount across all simulation
stages. A tech with more than one setup always produces at least a Warning (the
operator must re-setup the machine).
3.5. Simulation properties
| Property | Meaning |
|---|---|
|
|
|
The |
|
The |
|
The |
|
The |
|
A separate |
|
Manages back-gauge positions and crash checks during simulation |
3.6. ACB properties
Automatic Crowning / Bend-angle compensation:
| Property | Meaning |
|---|---|
|
At least one ACB system is available on the machine |
|
Classic or wireless disk-based ACB ( |
|
Laser-based ACB ( |
|
|
|
BendGuard as angle-measurement system (IRIS-based) |
3.7. Back-gauge surfaces
public IReadOnlyList<BGSurfDef[]> BGSurfaces
Returns one array of BGSurfDef per physical back-gauge, respecting the active
BG1Variant / BG2Variant. Each BGSurfDef is either a FlatBGSurfDef (a flat
stop surface) or a FingerBGSurfDef (a finger stop). EnumBGSurf iterates over all
(gauge, surface) combinations for a given BendOp, handling tandem-machine side
selection automatically.
4. Key Methods
4.1. SetSequence(string)
File: Core/Bend/BendTech.cs:1503
Parses a SequenceSign string and rebuilds mOps:
-
Splits on
,to get per-op tokens. -
Splits on
+to get per-flex tokens within a group. -
Parses
uid.phaseor justuidfor each flex. -
Re-uses existing
BendOpobjects when the sign matches (avoids recreating objects and losing computed gauging data). -
Calls
SetSequence(IEnumerable<BendOp>)to apply and callResetStages().
4.2. SetSequence(IEnumerable<BendOp>)
File: Core/Bend/BendTech.cs:1428
The core resequencing method:
-
Saves
OldSequence(used byGetResequenceRange()). -
Calls
Unload()on ops being removed. -
Re-assigns
SeqNo(0-based). -
Handles robotic regrip rebinding — if ops are reshuffled within one regrip bin, the regrip operation is rebound to its new successor.
-
Calls
ResetStages()to clear the cached_stagesarray, forcing re-computation.
4.3. Group and Ungroup
Group(IList<BendOp>) — merges multiple ops into one simultaneous stroke by encoding
them as "uid1+uid2+…" in the sequence string, then calling SetSequence.
Ungroup(BendOp) — splits a grouped op back into individual ops. For groups with more
than three sub-flexes, it tries to find the largest gap between flex spans and splits
there rather than creating an explosion of individual ops.
4.4. AddPreBend / RemovePreBend
AddPreBend(BendOp) splits an existing single-phase op into two adjacent ops — a
pre-bend (phase 0) and a final-bend (phase 1). The split ratio defaults to 0.8
for obtuse bends (≥ 135°) or 2/3 otherwise.
RemovePreBend(BendOp) reverses this: merges the two phase ops back into one
single-phase op and clears PhaseSplits on the paired E3Flex.
4.5. ApplyToPoseSheet
File: Core/Bend/BendTech.cs:960
public void ApplyToPoseSheet(int nBend, double fLie, PoseSheet sheet, ...)
Given a bend index and a lie value (0 = flat, 1 = fully bent), sets the deformation
state of every E3Flex in the PoseSheet. Used both by the simulation renderer and
by the collision checker.
For bend i (0 … nBend−1): flex lie = 1.0 (fully bent).
For the current bend nBend: flex lie = flex.GetOverallLie(phase, fLie).
Bends after nBend remain at 0.
4.6. Rebind
File: Core/Bend/BendTech.cs:1366
After a GAP adjustment replaces the Model3 with a slightly modified version, Rebind
re-links each BendOp.Flexes to the new E3Flex objects using their UIDs, and marks
all ops dirty (pose-sheets and simulation steps must be recomputed).
4.7. UpdateFlexKFactors
When a die V-width changes, the K-factor changes, which changes the flat-pattern
geometry. UpdateFlexKFactors coalesces multiple rapid calls via LazyCall and
triggers BendGAPAdjust to re-unfold the part and re-compute gauging positions.
Suppressed during auto-tooling, tool previewing, manual sequencing, and diagnostic
runs.
4.8. SplitTandems / SplitTandem
Tandem press-brakes consist of two half-machines working in sync. Before generating NC
code, SplitTandems saves the part twice — once with ESaveFX.Tandem for the left
half, once for the right — loads each back, and calls SplitTandem(left) on each:
-
Switches
BMachineto the left or right half-machine definition. -
Translates all
MappingPt.Xvalues by±(tableLength + gap)/2. -
Removes mounts that lie entirely in the other half.
-
Remaps gauges from 4 per op to 2 per op.
4.9. GenAllOutputs
File: Core/Bend/BendTech.cs:1106
The top-level output trigger. Guards with CodeDirty || forceGen and
BMachine.IsNCAllowed:
-
Sorts mount pieces on each setup (
SortMounts). -
Stops any in-progress manual sequencing.
-
Generates a setup-sheet report (HTML or PDF) for each NC program index, using the template path from
Settings.Outputs.BendRepTemplate. -
Generates NC code files via
ProgOutput.GenBendCode. -
Optionally attaches the report to the NC file (
BendRepAttachToNC).
4.10. GenerateNCCode
public object GenerateNCCode(int nSetup)
File: Core/Bend/BendTech.cs:1192
Sets NCIndex = nSetup, ensures the drawing exists (DoUnfold if needed), sorts
mounts, and delegates to Hub.GenerateNC(Owner, postname) which dispatches to the
machine-specific post-processor class (e.g. BNCWriter, DLDWriter).
4.11. SaveSummary
internal void SaveSummary(TextWriter tw)
Appends a [Bending] section to the part’s Summary entry in the .fx ZIP:
[Bending]
MCID=trubend5170
MCName=TruBend 5170
Count=4
Setups=2
4.12. Dump
A diagnostic text dump of the entire bend-tech state. Written to a TextWriter and
used heavily in unit tests. Covers:
-
Material, thickness, machine
-
Sequence signature
-
Per-setup tool mount table
-
Per-bend-op: back-gauge vectors, ACB mode, flip, mapping point, status flags, robot routing instructions
5. Simulation Stages and EBPhase
The simulation timeline is a flat array of IBSimStage objects built by ResetStages.
Each stage has an array of IBSimStep steps, each associated with a phase from the
EBPhase enum. BendTech navigates through this array using:
| Method | Effect |
|---|---|
|
Move ±1 stage in the sequence |
|
Jump to a specific |
|
Navigate edges between stages (handles regrip transitions) |
Key EBPhase values for a normal press-brake bend:
| Phase | Value | Meaning |
|---|---|---|
|
0 |
Part placed against back-gauge, ram at top-dead-center |
|
1 |
Ram descends rapidly to the mute point (lightcurtain zone) |
|
2 |
Ram descends slowly to pinch point (contacts the sheet) |
|
3 |
Back-gauge retracts while ram holds at pinch |
|
4 |
Ram descends to bottom-dead-center, sheet deforms |
|
5 |
Dwell at BDC |
|
6 |
Ram rises slowly to decompression point |
|
7 |
Ram rises fully to open position |
|
8 |
Operator removes part |
|
9 |
Operator rotates part for next bend |
|
10 |
Overbend cycle (spring-back compensation) |
|
13 |
Compress spring-loaded hemming die |
For robotic cells, additional phases cover approach, lateral insert, catch-after-bend, and post-bend safe points.
6. Collision Detection Infrastructure
BendTech provides the geometry needed for the crash checker (NBendCrash) and the
status checker (BCrashState):
-
GetFullEntCollider(n)— returns a detailed (un-simplified) collider for entityn. For flexes, the collider is computed in the flat state. -
GetBedCollider(iAxis)— returns the die-rail and die-bed colliders, updating the die-rail’s I-axis position if it has changed. -
TableCollider— the support table collider (only for machines with table variants). -
Collider bias constants ensure grazing contacts do not produce false alarms:
ColliderBias = 0.1 mm,PunchColliderBias = 0.5 mm,ZBendColliderBias = 2.5 mm.
7. ISheafEditFilter — Settings UI Control
BendTech implements ISheafEditFilter to customize the settings panel shown in the
bend-tech UI:
-
IsSubtreeValid(path)— hides the cell subsection (.Bend.Cell) and shows only.Infoand.Bend.*. -
GetRange(sh, ref min, ref max)— delegates value ranges toBMachine.GetRange. -
GetState(sh, path)— hides machine-specific rows that are irrelevant for the current machine (e.g. hides ACB laser settings when the machine has no laser, hides robot options when there is no cell).
8. Relationships to Other Classes
BendTech
│
├── BendMachine machine geometry, tool constraints, post-processor name
├── BToolList (Inventory) set of tools available for this part
│
├── List<BendOp> mOps ordered bend sequence
│ └── BendOp
│ ├── E3Flex[] the 3D bend entities being processed
│ ├── BendSetup the machine configuration for this stroke
│ │ └── BendMount[] physical tool positions on the beam
│ ├── BGPos[] back-gauge vectors and surfaces
│ └── ACBSettings angle-correction settings
│
├── BCellTech (Cell) robot cell — pickup, regrip, deposit stages
│
├── Mechanism SimMechanism full visual machine model for on-screen simulation
├── Mechanism CheckMech separate model for status checking (no visual side effects)
└── BGMinder back-gauge trajectory and crash checking
9. Key Files
| File | Responsibility |
|---|---|
|
This file — main class: construction, sequence management, output, simulation navigation |
|
Partial class — |
|
|
|
GAP (Geometry Adjustment for Processing) — re-unfolds and adjusts K-factor after tool changes |
|
|
|
|
|
|
|
|
|
|