solidworks 按partdox包围框改零件名字 c#

csharp 复制代码
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace SolidWorksAddinStudy
{
    internal static class NameSizeMatchService
    {
        internal readonly struct NameSizeMatchResult
        {
            public NameSizeMatchResult(int parsedCount, int mismatchCount, int replacedCount, int replaceFailCount)
            {
                ParsedCount = parsedCount;
                MismatchCount = mismatchCount;
                ReplacedCount = replacedCount;
                ReplaceFailCount = replaceFailCount;
            }

            public int ParsedCount { get; }
            public int MismatchCount { get; }
            public int ReplacedCount { get; }
            public int ReplaceFailCount { get; }
        }

        public static NameSizeMatchResult Run(ModelDoc2 rootAssemblyModel)
        {
            int parsedCount = 0;
            int mismatchCount = 0;
            int replacedCount = 0;
            int replaceFailCount = 0;
            var visitedAssemblies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

            ProcessAssembly(
                rootAssemblyModel,
                ref parsedCount,
                ref mismatchCount,
                ref replacedCount,
                ref replaceFailCount,
                visitedAssemblies);

            return new NameSizeMatchResult(parsedCount, mismatchCount, replacedCount, replaceFailCount);
        }

        private static void ProcessAssembly(
            ModelDoc2 assemblyModel,
            ref int parsedCount,
            ref int mismatchCount,
            ref int replacedCount,
            ref int replaceFailCount,
            HashSet<string> visitedAssemblies)
        {
            if (assemblyModel == null || assemblyModel.GetType() != (int)swDocumentTypes_e.swDocASSEMBLY)
            {
                return;
            }

            string asmKey = assemblyModel.GetPathName();
            if (string.IsNullOrWhiteSpace(asmKey))
            {
                asmKey = assemblyModel.GetTitle();
            }

            if (!visitedAssemblies.Add(asmKey))
            {
                return;
            }

            AssemblyDoc swAssembly = (AssemblyDoc)assemblyModel;
            // 只获取当前层级组件,递归时再进入子装配体,避免重复全量遍历导致卡顿
            object[] components = (object[])swAssembly.GetComponents(true);
            if (components == null || components.Length == 0)
            {
                return;
            }

            const double tolerance = 0.5; // mm

            foreach (object compObj in components)
            {
                Component2 comp = (Component2)compObj;
                ModelDoc2 compModel = null;

                try
                {
                    compModel = (ModelDoc2)comp.GetModelDoc2();
                }
                catch
                {
                    compModel = null;
                }

                if (compModel != null && compModel.GetType() == (int)swDocumentTypes_e.swDocASSEMBLY)
                {
                    ProcessAssembly(
                        compModel,
                        ref parsedCount,
                        ref mismatchCount,
                        ref replacedCount,
                        ref replaceFailCount,
                        visitedAssemblies);
                    continue;
                }

                string originalComponentName = comp.Name2 ?? string.Empty;
                string rawName = NormalizeComponentName(originalComponentName);

                if (!TryParseSizeFromName(rawName, out double[] nameDims))
                {
                    continue;
                }

                parsedCount++;

                if (!TryGetComponentDimensionsMm(comp, out double[] boxDims))
                {
                    Console.WriteLine($"[跳过] {rawName} -> 无法获取GetBox尺寸");
                    continue;
                }

                if (AreDimensionsClose(nameDims, boxDims, tolerance))
                {
                    continue;
                }

                mismatchCount++;
                string targetSizeToken = FormatDims(boxDims);
                string updatedComponentName = ReplaceSizeTokenInName(originalComponentName, targetSizeToken);

                if (string.Equals(updatedComponentName, originalComponentName, StringComparison.Ordinal))
                {
                    replaceFailCount++;
                    Console.WriteLine($"[不匹配-未替换] {rawName} | 名称:{FormatDims(nameDims)} | GetBox:{targetSizeToken}");
                    continue;
                }

                bool renamed = TryRenameComponent(assemblyModel, comp, updatedComponentName, targetSizeToken, out string renameMessage);
                if (renamed)
                {
                    replacedCount++;
                    Console.WriteLine($"[已替换] {rawName} | 名称:{FormatDims(nameDims)} -> {targetSizeToken}");
                }
                else
                {
                    replaceFailCount++;
                    Console.WriteLine($"[不匹配-替换失败] {rawName} | 目标:{targetSizeToken} | 原因:{renameMessage}");
                }
            }
        }

        private static bool TryRenameComponent(ModelDoc2 assemblyModel, Component2 comp, string updatedComponentName, string targetSizeToken, out string message)
        {
            message = string.Empty;
            if (assemblyModel == null)
            {
                message = "装配体文档为空";
                return false;
            }

            string targetLeafName = ExtractLeafComponentName(updatedComponentName);
            if (string.IsNullOrWhiteSpace(targetLeafName))
            {
                message = "目标名称为空";
                return false;
            }

            // 使用官方 RenameDocument 时不手动拼实例后缀,由 SW 自动处理重名实例。
            string renameTarget = targetLeafName;
            if (TryStripInstanceSuffix(targetLeafName, out string strippedTargetName))
            {
                renameTarget = strippedTargetName;
            }

            if (string.IsNullOrWhiteSpace(renameTarget))
            {
                message = "目标名称为空";
                return false;
            }

            string finalName = comp.Name2 ?? string.Empty;
            try
            {
                bool selected = comp.Select4(false, null, false);
                if (!selected)
                {
                    message = "组件选择失败";
                    return false;
                }

                ModelDocExtension modelExt = assemblyModel.Extension;
                if (modelExt == null)
                {
                    message = "ModelDocExtension 为空";
                    return false;
                }

                int renameError = modelExt.RenameDocument(renameTarget);
                finalName = comp.Name2 ?? string.Empty;
                if (renameError == (int)swRenameDocumentError_e.swRenameDocumentError_None)
                {
                    return true;
                }

                message = $"RenameDocument失败: error={renameError}, 目标[{renameTarget}], 当前[{finalName}]";
                return false;
            }
            catch (Exception ex)
            {
                message = $"RenameDocument异常: {ex.Message}";
                return false;
            }
        }

        private static bool IsRenameApplied(string currentComponentName, string targetInstanceName, string targetSizeToken, double[] targetDims)
        {
            string currentLeafName = ExtractLeafComponentName(currentComponentName ?? string.Empty);
            if (string.Equals(currentLeafName, targetInstanceName, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }

            string normalizedCurrentName = NormalizeComponentName(currentLeafName);
            if (!string.IsNullOrWhiteSpace(normalizedCurrentName))
            {
                if (!string.IsNullOrWhiteSpace(targetSizeToken) &&
                    normalizedCurrentName.IndexOf(targetSizeToken, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    return true;
                }

                if (targetDims != null &&
                    targetDims.Length == 3 &&
                    TryParseSizeFromName(normalizedCurrentName, out double[] currentDims) &&
                    AreDimensionsClose(currentDims, targetDims, 0.001))
                {
                    return true;
                }
            }

            return false;
        }

        private static string NormalizeComponentName(string componentName)
        {
            if (string.IsNullOrWhiteSpace(componentName))
            {
                return string.Empty;
            }

            int slashIndex = componentName.LastIndexOf('/');
            if (slashIndex >= 0 && slashIndex < componentName.Length - 1)
            {
                componentName = componentName.Substring(slashIndex + 1);
            }

            int lastDashIndex = componentName.LastIndexOf('-');
            if (lastDashIndex > 0 && lastDashIndex < componentName.Length - 1)
            {
                string suffix = componentName.Substring(lastDashIndex + 1);
                if (int.TryParse(suffix, out _))
                {
                    componentName = componentName.Substring(0, lastDashIndex);
                }
            }

            return componentName;
        }

        private static string ExtractLeafComponentName(string componentName)
        {
            if (string.IsNullOrWhiteSpace(componentName))
            {
                return string.Empty;
            }

            int slashIndex = componentName.LastIndexOf('/');
            if (slashIndex >= 0 && slashIndex < componentName.Length - 1)
            {
                return componentName.Substring(slashIndex + 1);
            }

            return componentName;
        }

        private static bool TryGetInstanceSuffix(string componentName, out string suffix)
        {
            suffix = string.Empty;
            string leaf = ExtractLeafComponentName(componentName);
            int lastDashIndex = leaf.LastIndexOf('-');
            if (lastDashIndex > 0 && lastDashIndex < leaf.Length - 1)
            {
                string possibleSuffix = leaf.Substring(lastDashIndex + 1);
                if (int.TryParse(possibleSuffix, out _))
                {
                    suffix = possibleSuffix;
                    return true;
                }
            }

            return false;
        }

        private static bool HasInstanceSuffix(string componentName)
        {
            return TryGetInstanceSuffix(componentName, out _);
        }

        private static bool TryStripInstanceSuffix(string componentName, out string nameWithoutSuffix)
        {
            nameWithoutSuffix = string.Empty;
            string leaf = ExtractLeafComponentName(componentName);
            int lastDashIndex = leaf.LastIndexOf('-');
            if (lastDashIndex > 0 && lastDashIndex < leaf.Length - 1)
            {
                string possibleSuffix = leaf.Substring(lastDashIndex + 1);
                if (int.TryParse(possibleSuffix, out _))
                {
                    nameWithoutSuffix = leaf.Substring(0, lastDashIndex);
                    return true;
                }
            }

            return false;
        }

        private static bool TryParseSizeFromName(string name, out double[] dims)
        {
            dims = Array.Empty<double>();
            if (string.IsNullOrWhiteSpace(name))
            {
                return false;
            }

            var match = Regex.Match(name, @"(\d+(?:\.\d+)?)\s*[xX×]\s*(\d+(?:\.\d+)?)\s*[xX×]\s*(\d+(?:\.\d+)?)");
            if (!match.Success)
            {
                return false;
            }

            if (!double.TryParse(match.Groups[1].Value, out double d1) ||
                !double.TryParse(match.Groups[2].Value, out double d2) ||
                !double.TryParse(match.Groups[3].Value, out double d3))
            {
                return false;
            }

            dims = new[] { d1, d2, d3 };
            Array.Sort(dims);
            return true;
        }

        private static bool TryGetComponentDimensionsMm(Component2 comp, out double[] dims)
        {
            dims = Array.Empty<double>();
            object boxObj = comp.GetBox(false, false);
            if (boxObj == null || !(boxObj is double[]))
            {
                return false;
            }

            double[] box = (double[])boxObj;
            if (box.Length < 6)
            {
                return false;
            }

            double length = Math.Abs(box[3] - box[0]) * 1000.0;
            double width = Math.Abs(box[4] - box[1]) * 1000.0;
            double height = Math.Abs(box[5] - box[2]) * 1000.0;

            dims = new[] { length, width, height };
            Array.Sort(dims);
            return true;
        }

        private static bool AreDimensionsClose(double[] a, double[] b, double tolerance)
        {
            if (a == null || b == null || a.Length != 3 || b.Length != 3)
            {
                return false;
            }

            return Math.Abs(a[0] - b[0]) <= tolerance &&
                   Math.Abs(a[1] - b[1]) <= tolerance &&
                   Math.Abs(a[2] - b[2]) <= tolerance;
        }

        private static string FormatDims(double[] dims)
        {
            if (dims == null || dims.Length != 3)
            {
                return "-";
            }

            return $"{dims[0]:0.###}x{dims[1]:0.###}x{dims[2]:0.###}";
        }

        private static string ReplaceSizeTokenInName(string name, string replacementSizeToken)
        {
            if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(replacementSizeToken))
            {
                return name;
            }

            const string sizePattern = @"(\d+(?:\.\d+)?)\s*[xX×]\s*(\d+(?:\.\d+)?)\s*[xX×]\s*(\d+(?:\.\d+)?)";
            var regex = new Regex(sizePattern);
            return regex.Replace(name, replacementSizeToken, 1);
        }
    }
}
相关推荐
solidwork_s12 天前
SOLIDWORKS格式处理干货:STEP、IGS、X_T 优化技巧
solidworks
njsgcs21 天前
导出glb可视化让vlm看图找面 自己配合
智能制造·solidworks
花开月满西楼22 天前
零基础速学SolidWorks2026【曲面】曲面缝合
3d建模·solidworks·机械设计·机械绘图绘制
花开月满西楼22 天前
零基础速学SolidWorks2026【曲面】删除面
3d建模·solidworks·机械设计·机械绘图绘制
花开月满西楼22 天前
零基础速学SolidWorks2026【曲面】加厚曲面
3d建模·solidworks·机械设计·机械绘图绘制
花开月满西楼25 天前
零基础速学SolidWorks2026【曲面】边界曲面和等距曲面
3d建模·solidworks·机械设计·机械绘图绘制
花开月满西楼25 天前
零基础速学SolidWorks2026【曲面】平面区域和填充曲面
3d建模·solidworks·机械设计·机械绘图绘制
蓝悦无人机1 个月前
SOLIDWORKS高级应用之方程
solidworks·参数化建模·if 判断语句
花开月满西楼1 个月前
零基础速学SolidWorks2026【曲面】分割线
3d建模·solidworks·机械设计·机械绘图绘制
花开月满西楼1 个月前
零基础速学SolidWorks2026【曲面】建模核心基础
solidworks·机械设计·机械绘图绘制