需求概述

使用SolidWorks和C#开发一个装配体整体缩放功能,需要结合SolidWorks API和C#编程。该功能允许用户选择装配体中的零部件,并按照指定比例进行缩放。以下是实现步骤和代码示例。

AI的方案:

开发环境准备

确保安装SolidWorks和Visual Studio。SolidWorks版本需支持API调用,建议使用2018或更高版本。安装SolidWorks API SDK,通常随SolidWorks安装包提供。

在Visual Studio中创建新的C#类库项目,添加对SolidWorks的引用。引用包括SolidWorks.Interop.sldworksSolidWorks.Interop.swconstSolidWorks.Interop.swpublished

实现步骤

1. 连接SolidWorks

通过COM接口连接到正在运行的SolidWorks实例。使用Marshal.GetActiveObject方法获取SolidWorks应用对象。

using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;

public class SolidWorksScaleUtility
{
    private ISldWorks swApp;

    public bool ConnectToSolidWorks()
    {
        try
        {
            swApp = (ISldWorks)Marshal.GetActiveObject("SldWorks.Application");
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Failed to connect to SolidWorks: " + ex.Message);
            return false;
        }
    }
}

2. 获取当前活动装配体

检查SolidWorks当前打开的文档是否为装配体。如果不是,提示用户打开装配体。

public IAssemblyDoc GetActiveAssembly()
{
    if (swApp == null)
    {
        Console.WriteLine("SolidWorks not connected.");
        return null;
    }

    ModelDoc2 doc = swApp.ActiveDoc;
    if (doc == null)
    {
        Console.WriteLine("No active document.");
        return null;
    }

    if (doc.GetType() != (int)swDocumentTypes_e.swDocASSEMBLY)
    {
        Console.WriteLine("Active document is not an assembly.");
        return null;
    }

    return (IAssemblyDoc)doc;
}

3. 选择零部件并缩放

遍历装配体中的零部件,获取其引用并应用缩放变换。使用GetComponents方法获取所有组件。

public void ScaleAssembly(IAssemblyDoc assembly, double scaleFactor)
{
    if (assembly == null)
    {
        Console.WriteLine("Assembly is null.");
        return;
    }

    object[] components = (object[])assembly.GetComponents(false);
    if (components == null)
    {
        Console.WriteLine("No components in assembly.");
        return;
    }

    foreach (IComponent2 component in components)
    {
        ScaleComponent(component, scaleFactor);
    }
}

private void ScaleComponent(IComponent2 component, double scaleFactor)
{
    if (component == null)
    {
        Console.WriteLine("Component is null.");
        return;
    }

    ModelDoc2 componentDoc = component.GetModelDoc();
    if (componentDoc == null)
    {
        Console.WriteLine("Failed to get component document.");
        return;
    }

    // 获取当前变换矩阵
    MathTransform transform = component.Transform2;
    if (transform == null)
    {
        Console.WriteLine("Failed to get component transform.");
        return;
    }

    // 创建缩放矩阵
    double[] scaleMatrix = new double[16];
    scaleMatrix[0] = scaleFactor;  // X轴缩放
    scaleMatrix[5] = scaleFactor;  // Y轴缩放
    scaleMatrix[10] = scaleFactor; // Z轴缩放
    scaleMatrix[15] = 1.0;

    MathUtility mathUtils = (MathUtility)swApp.GetMathUtility();
    MathTransform scaleTransform = mathUtils.CreateTransform(scaleMatrix);

    // 应用新的变换矩阵
    component.Transform2 = (MathTransform)transform.Multiply(scaleTransform);
}

4. 用户界面集成

创建简单的Windows窗体应用,提供缩放比例输入和执行按钮。使用System.Windows.Forms库。

using System.Windows.Forms;

public class ScaleForm : Form
{
    private TextBox scaleFactorTextBox;
    private Button scaleButton;

    public ScaleForm()
    {
        InitializeComponents();
    }

    private void InitializeComponents()
    {
        scaleFactorTextBox = new TextBox();
        scaleFactorTextBox.Location = new System.Drawing.Point(10, 10);
        scaleFactorTextBox.Text = "1.0";

        scaleButton = new Button();
        scaleButton.Location = new System.Drawing.Point(10, 40);
        scaleButton.Text = "Scale Assembly";
        scaleButton.Click += ScaleButton_Click;

        Controls.Add(scaleFactorTextBox);
        Controls.Add(scaleButton);
    }

    private void ScaleButton_Click(object sender, EventArgs e)
    {
        if (!double.TryParse(scaleFactorTextBox.Text, out double scaleFactor))
        {
            MessageBox.Show("Invalid scale factor.");
            return;
        }

        SolidWorksScaleUtility utility = new SolidWorksScaleUtility();
        if (!utility.ConnectToSolidWorks())
        {
            MessageBox.Show("Failed to connect to SolidWorks.");
            return;
        }

        IAssemblyDoc assembly = utility.GetActiveAssembly();
        if (assembly == null)
        {
            MessageBox.Show("No active assembly.");
            return;
        }

        utility.ScaleAssembly(assembly, scaleFactor);
        MessageBox.Show("Assembly scaled successfully.");
    }
}

测试与调试

运行Windows窗体应用,确保SolidWorks已打开装配体。输入缩放比例后点击按钮,检查装配体是否按预期缩放。如果出现错误,检查SolidWorks API调用是否成功,并确保所有组件均可访问。

注意事项

  • 缩放操作会影响装配体的物理属性,如质量和重心。
  • 某些特殊类型的组件可能不支持直接缩放,需单独处理。
  • 操作前建议保存装配体,避免数据丢失。

扩展功能

  • 支持选择性缩放,允许用户选择特定组件进行缩放。
  • 添加撤销功能,允许用户回滚缩放操作。
  • 提供预览功能,显示缩放后的效果。

通过以上步骤,可以实现一个基本的SolidWorks装配体缩放工具。根据需求进一步扩展功能,提升用户体验。

人工方案:

客户要求是整个装配体等比例缩放,还期望是图纸能够继续 使用。

那么:

  • 不能只管外形,具体的配合关系也要能变化 。(所以不能直接转个step,整体缩放)
  • 新模型的明细表,信息要正确,包括质量,规格。
  • 保持配合的情况下,零件改变大小后,如何变化。

所以就可以列一个这样的功能图表:

在这里插入图片描述

缩放的核心代码,这是使用多配置方案,来尽量保持模型的关联,同时来缩放模型。

		private void btnAssemblyScale_Click(object sender, EventArgs e)
		{



			double scValue = 1 / 6.0;
			string scName = "1-6";

			SldWorks swApp = Utility.ConnectToSolidWorks();

			if (swApp != null)
			{
				ScaleAsmmelby(swApp, scName, scValue);
			}

			swApp.IActiveDoc2.ForceRebuild3(false);
		}
	private static void ScaleAsmmelby(SldWorks swApp, string scName, double scValue)
	{
		ModelDoc2 swModel = (ModelDoc2)swApp.ActiveDoc;

		Configuration swConf = (Configuration)swModel.GetActiveConfiguration();


		var swAsm = swModel as AssemblyDoc;


		if (swAsm != null)
		{
			//增加缩放配置
			var allComps = (object[])swAsm.GetComponents(true);
			for (var index = 0; index < allComps.Length; index++)
			{
				var comp = allComps[index];
				var tempComp = comp as Component2;

				var partPath = tempComp.GetPathName();


				if (partPath.ToUpper().EndsWith("SLDPRT"))
				{
					swApp.ActivateDoc(partPath);

					var modelPart = swApp.IActiveDoc2;


					if (modelPart != null)
					{
						modelPart.Extension.BreakAllExternalFileReferences2(true);
						var existFeat = (modelPart as PartDoc).FeatureByName(scName + "Auto_Create");

						if (existFeat == null)
						{
							bool boolstatus =
								modelPart.AddConfiguration2(scName, "", "", true, false, false, true, 256);

							swModel.ShowConfiguration2(scName);

							var myFeature =
								modelPart.FeatureManager.InsertScale(0, true, scValue, scValue, scValue);
							myFeature.Name = scName + "Auto_Create";
							if (myFeature == null)
							{
							}

							modelPart.Save();
						}


						swApp.CloseDoc(partPath);
					}
				}
				else if (partPath.ToUpper().EndsWith("SLDASM"))
				{

					swApp.ActivateDoc(partPath);

					ScaleAsmmelby(swApp, scName, scValue);

			 
				}
			}


			//新加装配配置
			swModel.AddConfiguration2(scName, "", "", true, false, false, true, 256);


			var swFeat = (Feature)swModel.FirstFeature();

			Feature swMateFeat = null;
			Feature swSubFeat = default(Feature);
			Mate2 swMate = default(Mate2);
			Component2 swComp = default(Component2);
			MateEntity2[] swMateEnt = new MateEntity2[3];
			//string fileName = null;
			//int errors = 0;
			//int warnings = 0;
			int i = 0;
			double[] entityParameters = new double[8];

			//从特征树中查找配合文件夹 Iterate over features in FeatureManager design tree

			while ((swFeat != null))
			{
				if ("MateGroup" == swFeat.GetTypeName())
				{
					swMateFeat = (Feature)swFeat;
					break;
				}

				swFeat = (Feature)swFeat.GetNextFeature();
			}

			Debug.Print("  " + swMateFeat.Name);
			Debug.Print("");

			//获取第一个子配合特征 Get first mate, which is a subfeature
			swSubFeat = (Feature)swMateFeat.GetFirstSubFeature();
			while ((swSubFeat != null))
			{
				swMate = (Mate2)swSubFeat.GetSpecificFeature2();
				if ((swMate != null))
				{
					if (swMate.Type == (int)swMateType_e.swMateDISTANCE)
					{
						Dimension dimension = (Dimension)swModel.Parameter($@"D1@{swSubFeat.Name}");
						dimension.SetValue3(dimension.Value * scValue, (int)swSetValueInConfiguration_e.swSetValue_InThisConfiguration,"");

						//dimension.SystemValue = dimension.SystemValue * scValue; //0.001英寸
					}
				}

				// 从配合组中遍历 下一个配合 Get the next mate in MateGroup
				swSubFeat = (Feature)swSubFeat.GetNextSubFeature();
			}


			allComps = (object[])swAsm.GetComponents(false);

			for (var index = 0; index < allComps.Length; index++)
			{
				var comp = allComps[index];
				var tempComp = comp as Component2;

				tempComp.ReferencedConfiguration = scName;
			}

			swModel.Save();

		}
	}