fix(assembly): part number suffix incorrectly incremented when inserting duplicate parts #327

Closed
opened 2026-02-24 18:56:16 +00:00 by forbes · 0 comments
Owner

Description

When parts with structured part numbers (e.g., P03-0001) are inserted into an assembly multiple times, the auto-deduplication logic increments the trailing numeric portion of the part number itself, producing P03-0002, P03-0003, etc. This corrupts the part number — the user expects instance suffixes like P03-0001-1, P03-0001-2.

Current Behavior

  1. Insert P03-0001 → label is P03-0001
  2. Insert P03-0001 again → label becomes P03-0002 (wrong)
  3. Insert P03-0001 again → label becomes P03-0003 (wrong)

Expected Behavior

  1. Insert P03-0001 → label is P03-0001-1
  2. Insert P03-0001 again → label becomes P03-0001-2
  3. Insert P03-0001 again → label becomes P03-0001-3

Or alternatively, the first instance keeps its original label and only subsequent duplicates get the -N suffix.

Root Cause

The UniqueNameManager::decomposeName() method (src/Base/UniqueNameManager.cpp:33-48) scans backwards from the end of the name for trailing digits, then treats them as the "unique suffix" to increment:

Input:  "P03-0001"
Result: prefix="P03-", digits="0001", suffix=""

When Document::makeUniqueLabel() (src/App/Document.cpp:1962) calls makeUniqueName("P03-0001", 3), the manager sees that "0001" is already registered under base name "P03-", so it increments to "0002""P03-0002".

This is correct behavior for FreeCAD's default naming convention (e.g., BodyBody001Body002) but is wrong for structured part numbers where the digits are semantically meaningful, not auto-generated instance counters.

Proposed Approach

For assembly contexts (and possibly globally), when a duplicate label is detected, append an instance suffix (e.g., -1, -2) rather than incrementing the trailing digits. Options:

  1. Assembly-specific override: In the assembly module, override the label deduplication to append -N instead of using UniqueNameManager::makeUniqueName(). The AssemblyLink class already has allowDuplicateLabel() returning true (src/Mod/Assembly/App/AssemblyLink.cpp:758-761) — this could be extended with a custom deduplication strategy.

  2. UniqueNameManager subclass: Create a derived UniqueNameManager that overrides getNameSuffixStartPosition() to treat the entire name (including trailing digits) as a fixed base, then appends a -N separator + instance number. This preserves the existing behavior for default FreeCAD objects while enabling part-number-aware behavior for assemblies.

  3. Separator-aware decomposition: Teach decomposeName() to recognize that digits preceded by - in a structured name (e.g., P03-0001) are part of the base name, not a uniquifying suffix. This is more invasive but would fix the problem globally.

Files Involved

  • src/Base/UniqueNameManager.h — base class with virtual getNameSuffixStartPosition()
  • src/Base/UniqueNameManager.cppdecomposeName() and makeUniqueName() logic
  • src/App/Document.cpp:1962makeUniqueLabel() calls makeUniqueName(modelLabel, 3)
  • src/Mod/Assembly/App/AssemblyLink.cppallowDuplicateLabel() already returns true
  • tests/src/Base/UniqueNameManager.cpp — unit tests to update/extend
## Description When parts with structured part numbers (e.g., `P03-0001`) are inserted into an assembly multiple times, the auto-deduplication logic increments the trailing numeric portion of the part number itself, producing `P03-0002`, `P03-0003`, etc. This corrupts the part number — the user expects instance suffixes like `P03-0001-1`, `P03-0001-2`. ## Current Behavior 1. Insert `P03-0001` → label is `P03-0001` 2. Insert `P03-0001` again → label becomes `P03-0002` (wrong) 3. Insert `P03-0001` again → label becomes `P03-0003` (wrong) ## Expected Behavior 1. Insert `P03-0001` → label is `P03-0001-1` 2. Insert `P03-0001` again → label becomes `P03-0001-2` 3. Insert `P03-0001` again → label becomes `P03-0001-3` Or alternatively, the first instance keeps its original label and only subsequent duplicates get the `-N` suffix. ## Root Cause The `UniqueNameManager::decomposeName()` method (`src/Base/UniqueNameManager.cpp:33-48`) scans backwards from the end of the name for trailing digits, then treats them as the "unique suffix" to increment: ``` Input: "P03-0001" Result: prefix="P03-", digits="0001", suffix="" ``` When `Document::makeUniqueLabel()` (`src/App/Document.cpp:1962`) calls `makeUniqueName("P03-0001", 3)`, the manager sees that `"0001"` is already registered under base name `"P03-"`, so it increments to `"0002"` → `"P03-0002"`. This is correct behavior for FreeCAD's default naming convention (e.g., `Body` → `Body001` → `Body002`) but is wrong for structured part numbers where the digits are semantically meaningful, not auto-generated instance counters. ## Proposed Approach For assembly contexts (and possibly globally), when a duplicate label is detected, append an instance suffix (e.g., `-1`, `-2`) rather than incrementing the trailing digits. Options: 1. **Assembly-specific override**: In the assembly module, override the label deduplication to append `-N` instead of using `UniqueNameManager::makeUniqueName()`. The `AssemblyLink` class already has `allowDuplicateLabel()` returning `true` (`src/Mod/Assembly/App/AssemblyLink.cpp:758-761`) — this could be extended with a custom deduplication strategy. 2. **UniqueNameManager subclass**: Create a derived `UniqueNameManager` that overrides `getNameSuffixStartPosition()` to treat the entire name (including trailing digits) as a fixed base, then appends a `-N` separator + instance number. This preserves the existing behavior for default FreeCAD objects while enabling part-number-aware behavior for assemblies. 3. **Separator-aware decomposition**: Teach `decomposeName()` to recognize that digits preceded by `-` in a structured name (e.g., `P03-0001`) are part of the base name, not a uniquifying suffix. This is more invasive but would fix the problem globally. ## Files Involved - `src/Base/UniqueNameManager.h` — base class with virtual `getNameSuffixStartPosition()` - `src/Base/UniqueNameManager.cpp` — `decomposeName()` and `makeUniqueName()` logic - `src/App/Document.cpp:1962` — `makeUniqueLabel()` calls `makeUniqueName(modelLabel, 3)` - `src/Mod/Assembly/App/AssemblyLink.cpp` — `allowDuplicateLabel()` already returns `true` - `tests/src/Base/UniqueNameManager.cpp` — unit tests to update/extend
forbes added the bug label 2026-02-24 18:56:16 +00:00
forbes added the high-priority label 2026-02-24 20:59:18 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/create#327