feat: линейный массив (linear_pattern) — ksMeshCopyDefinition o3d_meshCopy
- CoordinateAxis enum + CoordinateAxes.ToObj3dType/Parse (X/Y/Z → o3d_axisO*) - SketchGeometry.RequireMin; PartModeler.RequireFeature (источник по id из _features) - LinearPatternAsync: SetAxis1 + SetCopyParamAlongAxis(true,0,count,step,false), count2=1 - инструмент linear_pattern; unit-тесты (RequireMin, Parse), интеграционный тест (3 экз. ±5%) - эмпирически: count включает исходный, step мм между соседними, count2=1 выключает 2D
This commit is contained in:
@@ -331,6 +331,46 @@ public sealed partial class PartModeler
|
||||
return id;
|
||||
}, ct);
|
||||
|
||||
/// <summary>Линейный массив (по сетке вдоль одной координатной оси): размножить операции
|
||||
/// featureIds вдоль оси axis, count экземпляров всего (включая исходный, ≥2), шаг step (мм)
|
||||
/// между соседними. geometric=true — быстрое геометрическое копирование. Возвращает id операции.</summary>
|
||||
public Task<int> LinearPatternAsync(IReadOnlyList<int> featureIds, CoordinateAxis axis, int count, double step, bool geometric = false, CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(featureIds);
|
||||
var ids = featureIds.Distinct().ToList();
|
||||
if (ids.Count == 0) throw new ArgumentException("Нужна хотя бы одна операция для массива.", nameof(featureIds));
|
||||
SketchGeometry.RequireMin(count, 2, nameof(count)); // count включает исходный
|
||||
SketchGeometry.RequirePositive(step, nameof(step)); // ловит и NaN
|
||||
|
||||
// Собираем источники до мутации модели (проверка существования всех id).
|
||||
var features = ids.Select(RequireFeature).ToList();
|
||||
|
||||
var part = GetTopPart();
|
||||
var axisEntity = part.GetDefaultEntity((short)CoordinateAxes.ToObj3dType(axis)) as ksEntity
|
||||
?? throw new InvalidOperationException("Не удалось получить координатную ось.");
|
||||
|
||||
var entity = part.NewEntity((short)Obj3dType.o3d_meshCopy) as ksEntity
|
||||
?? throw new InvalidOperationException("NewEntity(o3d_meshCopy) вернул null.");
|
||||
var def = entity.GetDefinition() as ksMeshCopyDefinition
|
||||
?? throw new InvalidOperationException("GetDefinition() массива вернул не ksMeshCopyDefinition.");
|
||||
def.SetAxis1(axisEntity);
|
||||
def.SetCopyParamAlongAxis(true, 0, count, step, false); // ось 1: angle=0, factor=false (шаг между соседними)
|
||||
def.count2 = 1; // второе направление выключено (1D-массив)
|
||||
def.geomArray = geometric;
|
||||
var arr = def.OperationArray() as ksEntityCollection
|
||||
?? throw new InvalidOperationException("OperationArray() массива вернул не ksEntityCollection.");
|
||||
foreach (var f in features) arr.Add(f);
|
||||
|
||||
if (!entity.Create())
|
||||
throw new InvalidOperationException(
|
||||
"Create() линейного массива вернул FALSE (копии самопересекаются или несовместимая геометрия?).");
|
||||
|
||||
var id = _nextId++;
|
||||
_features[id] = entity;
|
||||
return id;
|
||||
}, ct);
|
||||
|
||||
/// <summary>Перестроить документ.</summary>
|
||||
public Task RebuildAsync(CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() =>
|
||||
|
||||
Reference in New Issue
Block a user