using WinFormsFont = System.Drawing.Font;
using WinFormsSize = System.Drawing.Size;
using WinFormsPoint = System.Drawing.Point;
using WinFormsFontStyle = System.Drawing.FontStyle;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using SysException = System.Exception;
using AcadException = Autodesk.AutoCAD.Runtime.Exception;
using Point = System.Drawing.Point;
using Size = System.Drawing.Size;
using Label = System.Windows.Forms.Label;
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using WinFormsDialogResult = System.Windows.Forms.DialogResult;
namespace BeamSectionPlugin
{
#region 参数类
public class BeamParameters
{
public int Thickness { get; set; } = 15;
public BeamBottomSetting BeamBottom { get; set; } = new BeamBottomSetting();
public BeamSideSetting BeamSide { get; set; } = new BeamSideSetting();
public SlabSetting Slab { get; set; } = new SlabSetting();
}
public class BeamBottomSetting
{
public string SecondaryMaterial { get; set; } = "木方";
public string SecondarySpec { get; set; } = "40x90";
public string SecondaryDirection { get; set; } = "横向";
public string SecondarySpacing { get; set; } = "@200";
public string PrimaryMaterial { get; set; } = "木方";
public string PrimarySpec { get; set; } = "100x100";
public string PrimaryDirection { get; set; } = "纵向";
public string PrimarySpacing { get; set; } = "";
}
public class BeamSideSetting
{
public bool Enabled { get; set; } = false;
public string SecondaryMaterial { get; set; } = "木方";
public string SecondarySpec { get; set; } = "40x90";
public string SecondaryDirection { get; set; } = "垂直";
public string SecondarySpacing { get; set; } = "@200";
public string PrimaryMaterial { get; set; } = "木方";
public string PrimarySpec { get; set; } = "100x100";
public string PrimaryLayout { get; set; } = "双拼";
public double BoltDiameter { get; set; } = 12;
public double BoltStartHeight { get; set; } = 50;
public double BoltSlabHeight { get; set; } = 250;
public double BoltSpacing { get; set; } = 500;
}
public class SlabSetting
{
public string SecondaryMaterial { get; set; } = "木方";
public string SecondarySpec { get; set; } = "40x90";
public string SecondaryDirection { get; set; } = "横向";
public double SecondarySpacing { get; set; } = 200;
public string PrimaryMaterial { get; set; } = "木方";
public string PrimarySpec { get; set; } = "100x100";
public string PrimaryDirection { get; set; } = "纵向";
public int SteelCount { get; set; } = 1; // 顶托内方钢数量
}
public class SlabParams
{
public double Thickness { get; set; } = 250;
public double Offset { get; set; } = 0;
}
public class BeamSegment
{
public Point3d Start { get; set; }
public Point3d End { get; set; }
public double Height { get; set; }
public SlabParams Slab { get; set; }
}
#endregion
#region WinForms 窗体
public class BeamSectionForm : Form
{
// 材料库数据
private readonly Dictionary<string, List<string>> materialLib = new Dictionary<string, List<string>>
{
{"木方", new List<string>{"40x90", "50x100", "100x100"}},
{"钢管", new List<string>{"Φ48x2.5", "Φ48x2.7", "Φ48x3"}},
{"方钢", new List<string>{"40x40x1.5", "50x50x1.5", "50x100x3"}},
{"工字钢", new List<string>{"I8", "I10", "I12", "I14", "I16"}}
};
// UI 控件声明
private TabControl mainTabControl;
private Button btnDraw;
private TextBox txtThickness;
private ComboBox cmbBeamBottomSecMaterial, cmbBeamBottomSecSpec, cmbBeamBottomSecDirection;
private TextBox txtBeamBottomSecSpacing, txtBeamBottomPriSpacing;
private ComboBox cmbBeamBottomPriMaterial, cmbBeamBottomPriSpec, cmbBeamBottomPriDirection;
private CheckBox chkBeamSideEnabled;
private ComboBox cmbBeamSideSecMaterial, cmbBeamSideSecSpec, cmbBeamSideSecDirection;
private TextBox txtBeamSideSecSpacing;
private ComboBox cmbBeamSidePriMaterial, cmbBeamSidePriSpec, cmbBeamSidePriLayout;
private TextBox txtBoltDiameter, txtBoltStartHeight, txtBoltSlabHeight, txtBoltSpacing;
private ComboBox cmbSlabSecMaterial, cmbSlabSecSpec, cmbSlabSecDirection;
private TextBox txtSlabSecSpacing;
private ComboBox cmbSlabPriMaterial, cmbSlabPriSpec, cmbSlabPriDirection;
private TextBox txtSlabPriSteelCount; // 顶托内方钢数量
public BeamSectionForm()
{
InitializeComponents();
}
private void InitializeComponents()
{
try
{
// 窗体设置 (更紧凑)
this.Size = new WinFormsSize(650, 300);
this.Text = "梁板剖面图参数设置";
this.StartPosition = FormStartPosition.CenterScreen;
this.Font = new WinFormsFont("Microsoft YaHei UI", 9F);
// 主选项卡
mainTabControl = new TabControl
{
Location = new WinFormsPoint(10, 40),
Size = new WinFormsSize(620, 480),
Font = new WinFormsFont("Microsoft YaHei UI", 9F)
};
this.Controls.Add(mainTabControl);
// 创建选项卡
CreateBeamBottomTab();
CreateSlabTab();
// 模板厚度设置
Label lblThickness = new Label
{
Text = "梁板统一模板厚(mm):",
Location = new WinFormsPoint(20, 15),
AutoSize = true
};
txtThickness = new TextBox
{
Location = new WinFormsPoint(150, 12),
Width = 50,
Text = "15"
};
this.Controls.Add(lblThickness);
this.Controls.Add(txtThickness);
// 绘制按钮
btnDraw = new Button
{
Text = "开始绘制",
Location = new WinFormsPoint(280, 530),
Size = new WinFormsSize(100, 35),
Font = new WinFormsFont("Microsoft YaHei UI", 9.75F, WinFormsFontStyle.Bold)
};
btnDraw.Click += BtnDraw_Click;
this.Controls.Add(btnDraw);
}
catch (SysException ex)
{
MessageBox.Show($"窗体初始化错误: {ex.Message}\n{ex.StackTrace}", "严重错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreateBeamBottomTab()
{
try
{
TabPage tabBeam = new TabPage("梁下及梁侧设置");
mainTabControl.TabPages.Add(tabBeam);
// 梁下次龙骨设置
GroupBox gbBeamBottomSecondary = new GroupBox
{
Text = "梁下次龙骨设置",
Location = new Point(10, 10),
Size = new Size(700, 60)
};
tabBeam.Controls.Add(gbBeamBottomSecondary);
int yPos = 25;
AddMaterialControls(gbBeamBottomSecondary, ref yPos,
out cmbBeamBottomSecMaterial, out cmbBeamBottomSecSpec,
out cmbBeamBottomSecDirection, out txtBeamBottomSecSpacing, true);
// 梁下主龙骨设置
GroupBox gbBeamBottomPrimary = new GroupBox
{
Text = "梁下主龙骨设置",
Location = new Point(10, 100),
Size = new Size(700, 60)
};
tabBeam.Controls.Add(gbBeamBottomPrimary);
yPos = 25;
AddMaterialControls(gbBeamBottomPrimary, ref yPos,
out cmbBeamBottomPriMaterial, out cmbBeamBottomPriSpec,
out cmbBeamBottomPriDirection, out txtBeamBottomPriSpacing, true);
// 梁侧设置
GroupBox gbBeamSide = new GroupBox
{
Text = "梁侧龙骨设置",
Location = new Point(10, 180),
Size = new Size(700, 150)
};
tabBeam.Controls.Add(gbBeamSide);
// 启用梁侧设置
chkBeamSideEnabled = new CheckBox
{
Text = "启用梁侧设置",
Location = new Point(20, 25),
Checked = false
};
chkBeamSideEnabled.CheckedChanged += ChkBeamSideEnabled_CheckedChanged;
gbBeamSide.Controls.Add(chkBeamSideEnabled);
// 梁侧次龙骨
GroupBox gbBeamSideSecondary = new GroupBox
{
Text = "次龙骨",
Location = new Point(20, 50),
Size = new Size(660, 40)
};
gbBeamSide.Controls.Add(gbBeamSideSecondary);
int subYPos = 15;
AddMaterialControls(gbBeamSideSecondary, ref subYPos,
out cmbBeamSideSecMaterial, out cmbBeamSideSecSpec,
out cmbBeamSideSecDirection, out txtBeamSideSecSpacing, true);
// 梁侧主龙骨 (移除间距输入框)
GroupBox gbBeamSidePrimary = new GroupBox
{
Text = "主龙骨",
Location = new Point(20, 100),
Size = new Size(660, 40)
};
gbBeamSide.Controls.Add(gbBeamSidePrimary);
subYPos = 15;
// 材料选择
Label lblPriMaterial = new Label
{
Text = "材料:",
Location = new Point(20, subYPos),
AutoSize = true
};
gbBeamSidePrimary.Controls.Add(lblPriMaterial);
cmbBeamSidePriMaterial = new ComboBox
{
Location = new Point(60, subYPos),
Width = 80,
DropDownStyle = ComboBoxStyle.DropDownList
};
cmbBeamSidePriMaterial.Items.AddRange(new object[] { "木方", "钢管", "方钢", "工字钢" });
cmbBeamSidePriMaterial.SelectedIndex = 0;
cmbBeamSidePriMaterial.SelectedIndexChanged += Material_SelectedIndexChanged;
gbBeamSidePrimary.Controls.Add(cmbBeamSidePriMaterial);
// 规格选择
Label lblPriSpec = new Label
{
Text = "规格:",
Location = new Point(150, subYPos),
AutoSize = true
};
gbBeamSidePrimary.Controls.Add(lblPriSpec);
cmbBeamSidePriSpec = new ComboBox
{
Location = new Point(190, subYPos),
Width = 80
};
UpdateSpecOptions(cmbBeamSidePriMaterial, cmbBeamSidePriSpec);
gbBeamSidePrimary.Controls.Add(cmbBeamSidePriSpec);
// 布置方式
Label lblPriLayout = new Label
{
Text = "布置方式:",
Location = new Point(300, subYPos),
AutoSize = true
};
gbBeamSidePrimary.Controls.Add(lblPriLayout);
cmbBeamSidePriLayout = new ComboBox
{
Location = new Point(370, subYPos),
Width = 80
};
cmbBeamSidePriLayout.Items.AddRange(new object[] { "双拼", "单根" });
cmbBeamSidePriLayout.SelectedIndex = 0;
gbBeamSidePrimary.Controls.Add(cmbBeamSidePriLayout);
// 对拉螺栓设置
GroupBox gbBolts = new GroupBox
{
Text = "对拉螺栓设置",
Location = new Point(10, 350),
Size = new Size(700, 80)
};
tabBeam.Controls.Add(gbBolts);
// 螺栓参数
int xPos = 20;
int yBoltPos = 25;
AddBoltControl(gbBolts, "螺栓直径(mm):", ref xPos, yBoltPos, out txtBoltDiameter, "12");
AddBoltControl(gbBolts, "底部距梁底高(mm):", ref xPos, yBoltPos, out txtBoltStartHeight, "50");
xPos = 20;
yBoltPos = 55;
AddBoltControl(gbBolts, "板底距螺栓高(mm):", ref xPos, yBoltPos, out txtBoltSlabHeight, "250");
AddBoltControl(gbBolts, "螺栓间距(mm):", ref xPos, yBoltPos, out txtBoltSpacing, "500");
}
catch (SysException ex)
{
MessageBox.Show($"创建梁下选项卡错误: {ex.Message}\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreateSlabTab()
{
try
{
TabPage tabSlab = new TabPage("板下设置");
mainTabControl.TabPages.Add(tabSlab);
// 板下次龙骨设置
GroupBox gbSlabSecondary = new GroupBox
{
Text = "板下次龙骨设置",
Location = new Point(10, 20),
Size = new Size(700, 100)
};
tabSlab.Controls.Add(gbSlabSecondary);
int yPos = 25;
AddMaterialControls(gbSlabSecondary, ref yPos,
out cmbSlabSecMaterial, out cmbSlabSecSpec,
out cmbSlabSecDirection, out txtSlabSecSpacing, true);
// 板下主龙骨设置 (修改为顶托内方钢数量)
GroupBox gbSlabPrimary = new GroupBox
{
Text = "板下主龙骨设置",
Location = new Point(10, 130),
Size = new Size(700, 100)
};
tabSlab.Controls.Add(gbSlabPrimary);
yPos = 25;
// 材料选择
Label lblPriMaterial = new Label
{
Text = "材料:",
Location = new Point(20, yPos),
AutoSize = true
};
gbSlabPrimary.Controls.Add(lblPriMaterial);
cmbSlabPriMaterial = new ComboBox
{
Location = new Point(60, yPos),
Width = 80,
DropDownStyle = ComboBoxStyle.DropDownList
};
cmbSlabPriMaterial.Items.AddRange(new object[] { "木方", "钢管", "方钢", "工字钢" });
cmbSlabPriMaterial.SelectedIndex = 0;
cmbSlabPriMaterial.SelectedIndexChanged += Material_SelectedIndexChanged;
gbSlabPrimary.Controls.Add(cmbSlabPriMaterial);
// 规格选择
Label lblPriSpec = new Label
{
Text = "规格:",
Location = new Point(150, yPos),
AutoSize = true
};
gbSlabPrimary.Controls.Add(lblPriSpec);
cmbSlabPriSpec = new ComboBox
{
Location = new Point(190, yPos),
Width = 80
};
UpdateSpecOptions(cmbSlabPriMaterial, cmbSlabPriSpec);
gbSlabPrimary.Controls.Add(cmbSlabPriSpec);
// 布置方向
Label lblDirection = new Label
{
Text = "布置方向:",
Location = new Point(280, yPos),
AutoSize = true
};
gbSlabPrimary.Controls.Add(lblDirection);
cmbSlabPriDirection = new ComboBox
{
Location = new Point(350, yPos),
Width = 70
};
cmbSlabPriDirection.Items.AddRange(new object[] { "横向", "纵向", "垂直" });
cmbSlabPriDirection.SelectedIndex = 0;
gbSlabPrimary.Controls.Add(cmbSlabPriDirection);
// 顶托内方钢数量 (修改后的字段)
Label lblSteelCount = new Label
{
Text = "顶托方钢数量:",
Location = new Point(450, yPos),
AutoSize = true
};
gbSlabPrimary.Controls.Add(lblSteelCount);
txtSlabPriSteelCount = new TextBox
{
Location = new Point(540, yPos),
Width = 40,
Text = "1"
};
gbSlabPrimary.Controls.Add(txtSlabPriSteelCount);
// 根据方向更新控件状态 - 修改为纵向时启用
cmbSlabPriDirection.SelectedIndexChanged += (s, e) =>
{
string direction = cmbSlabPriDirection.SelectedItem?.ToString() ?? "";
bool isLongitudinal = direction == "纵向";
txtSlabPriSteelCount.Enabled = isLongitudinal;
txtSlabPriSteelCount.BackColor = isLongitudinal ? SystemColors.Window : SystemColors.Control;
};
// 初始状态
txtSlabPriSteelCount.Enabled = (cmbSlabPriDirection.SelectedItem?.ToString() == "纵向");
}
catch (SysException ex)
{
MessageBox.Show($"创建板下选项卡错误: {ex.Message}\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void AddMaterialControls(Control parent, ref int yPos, out ComboBox cmbMaterial,
out ComboBox cmbSpec, out ComboBox cmbDirection, out TextBox txtSpacing, bool includeSpacing)
{
cmbMaterial = null;
cmbSpec = null;
cmbDirection = null;
txtSpacing = null;
try
{
// 材料选择
Label lblMaterial = new Label
{
Text = "材料:",
Location = new Point(20, yPos),
AutoSize = true
};
parent.Controls.Add(lblMaterial);
cmbMaterial = new ComboBox
{
Location = new Point(60, yPos),
Width = 80,
DropDownStyle = ComboBoxStyle.DropDownList
};
cmbMaterial.Items.AddRange(new object[] { "木方", "钢管", "方钢", "工字钢" });
cmbMaterial.SelectedIndex = 0;
cmbMaterial.SelectedIndexChanged += Material_SelectedIndexChanged;
parent.Controls.Add(cmbMaterial);
// 规格选择
Label lblSpec = new Label
{
Text = "规格:",
Location = new Point(150, yPos),
AutoSize = true
};
parent.Controls.Add(lblSpec);
cmbSpec = new ComboBox
{
Location = new Point(190, yPos),
Width = 80
};
UpdateSpecOptions(cmbMaterial, cmbSpec);
parent.Controls.Add(cmbSpec);
// 布置方向
Label lblDirection = new Label
{
Text = "布置方向:",
Location = new Point(300, yPos),
AutoSize = true
};
parent.Controls.Add(lblDirection);
cmbDirection = new ComboBox
{
Location = new Point(370, yPos),
Width = 80
};
cmbDirection.Items.AddRange(new object[] { "横向", "纵向", "垂直" });
cmbDirection.SelectedIndex = 0;
parent.Controls.Add(cmbDirection);
// 间距设置
if (includeSpacing)
{
Label lblSpacing = new Label
{
Text = "间距:",
Location = new Point(460, yPos),
AutoSize = true
};
parent.Controls.Add(lblSpacing);
txtSpacing = new TextBox
{
Location = new Point(500, yPos),
Width = 70,
Tag = parent.Text
};
parent.Controls.Add(txtSpacing);
// 使用局部变量解决闭包问题
var localCmbDirection = cmbDirection;
var localTxtSpacing = txtSpacing;
var localLblSpacing = lblSpacing;
// 订阅方向改变事件 - 修改为纵向时启用
cmbDirection.SelectedIndexChanged += (s, e) =>
{
UpdateDirectionControls(localCmbDirection, localTxtSpacing, localLblSpacing, parent.Text);
};
// 初始化时更新控件状态
UpdateDirectionControls(cmbDirection, txtSpacing, lblSpacing, parent.Text);
}
yPos += 30;
}
catch (SysException ex)
{
MessageBox.Show($"添加材料控件错误: {ex.Message}\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 关键修改:纵向时启用间距输入
private void UpdateDirectionControls(ComboBox cmbDirection, TextBox txtSpacing, Label lblSpacing, string parentText)
{
if (cmbDirection == null || txtSpacing == null || lblSpacing == null)
return;
string direction = cmbDirection.SelectedItem?.ToString() ?? "";
bool isLongitudinal = direction == "纵向"; // 修改为纵向时启用
// 规则:只有纵向方向启用间距输入
txtSpacing.Enabled = isLongitudinal;
txtSpacing.BackColor = isLongitudinal ? SystemColors.Window : SystemColors.Control;
lblSpacing.Enabled = isLongitudinal;
}
private void AddBoltControl(Control parent, string label, ref int xPos, int yPos,
out TextBox textBox, string defaultValue)
{
textBox = new TextBox();
try
{
Label lbl = new Label
{
Text = label,
Location = new Point(xPos, yPos),
AutoSize = true
};
parent.Controls.Add(lbl);
textBox = new TextBox
{
Location = new Point(xPos + lbl.Width + 5, yPos),
Width = 80,
Text = defaultValue
};
parent.Controls.Add(textBox);
xPos += lbl.Width + 90;
}
catch (SysException ex)
{
MessageBox.Show($"添加螺栓控件错误: {ex.Message}\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void Material_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
ComboBox cmbMaterial = sender as ComboBox;
if (cmbMaterial == null) return;
foreach (Control ctrl in cmbMaterial.Parent.Controls)
{
if (ctrl is ComboBox cmbSpec && ctrl != cmbMaterial &&
ctrl.Location.Y == cmbMaterial.Location.Y)
{
UpdateSpecOptions(cmbMaterial, cmbSpec);
break;
}
}
}
catch (SysException ex)
{
MessageBox.Show($"材料选择变更错误: {ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpdateSpecOptions(ComboBox cmbMaterial, ComboBox cmbSpec)
{
try
{
if (cmbMaterial?.SelectedItem == null) return;
var material = cmbMaterial.SelectedItem.ToString();
if (cmbSpec == null) return;
cmbSpec.Items.Clear();
if (materialLib.ContainsKey(material))
{
cmbSpec.Items.AddRange(materialLib[material].ToArray());
if (cmbSpec.Items.Count > 0)
cmbSpec.SelectedIndex = 0;
}
}
catch (SysException ex)
{
MessageBox.Show($"更新规格选项错误: {ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ChkBeamSideEnabled_CheckedChanged(object sender, EventArgs e)
{
try
{
bool enabled = chkBeamSideEnabled.Checked;
// 启用/禁用所有梁侧控件
cmbBeamSideSecMaterial.Enabled = enabled;
cmbBeamSideSecSpec.Enabled = enabled;
cmbBeamSideSecDirection.Enabled = enabled;
txtBeamSideSecSpacing.Enabled = enabled;
cmbBeamSidePriMaterial.Enabled = enabled;
cmbBeamSidePriSpec.Enabled = enabled;
cmbBeamSidePriLayout.Enabled = enabled;
txtBoltDiameter.Enabled = enabled;
txtBoltStartHeight.Enabled = enabled;
txtBoltSlabHeight.Enabled = enabled;
txtBoltSpacing.Enabled = enabled;
}
catch (SysException ex)
{
MessageBox.Show($"梁侧启用状态变更错误: {ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void BtnDraw_Click(object sender, EventArgs e)
{
try
{
if (!ValidateInputs())
{
MessageBox.Show("请填写所有必填参数", "输入错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
this.DialogResult = WinFormsDialogResult.OK;
this.Close();
}
catch (SysException ex)
{
MessageBox.Show($"按钮点击错误: {ex.Message}\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private bool ValidateInputs()
{
try
{
// 验证模板厚度
if (string.IsNullOrEmpty(txtThickness.Text) ||
!int.TryParse(txtThickness.Text, out _))
return false;
// 验证梁下次龙骨 - 修改为纵向时验证
if (cmbBeamBottomSecDirection.SelectedItem?.ToString() == "纵向" &&
string.IsNullOrEmpty(txtBeamBottomSecSpacing.Text))
return false;
// 验证梁下主龙骨 - 修改为纵向时验证
string beamBottomPriDirection = cmbBeamBottomPriDirection?.SelectedItem?.ToString();
if (beamBottomPriDirection == "纵向" &&
(string.IsNullOrEmpty(txtBeamBottomPriSpacing.Text) ||
!double.TryParse(txtBeamBottomPriSpacing.Text, out _)))
return false;
// 验证梁侧设置
if (chkBeamSideEnabled.Checked)
{
// 梁侧次龙骨 - 修改为纵向时验证
if (cmbBeamSideSecDirection.SelectedItem?.ToString() == "纵向" &&
string.IsNullOrEmpty(txtBeamSideSecSpacing.Text))
return false;
if (!double.TryParse(txtBoltDiameter.Text, out _) ||
!double.TryParse(txtBoltStartHeight.Text, out _) ||
!double.TryParse(txtBoltSlabHeight.Text, out _) ||
!double.TryParse(txtBoltSpacing.Text, out _))
return false;
}
// 验证板下次龙骨 - 修改为纵向时验证
if (cmbSlabSecDirection.SelectedItem?.ToString() == "纵向" &&
!double.TryParse(txtSlabSecSpacing.Text, out _))
return false;
// 验证板下主龙骨
string slabPriDirection = cmbSlabPriDirection?.SelectedItem?.ToString();
if (slabPriDirection == "纵向" &&
(string.IsNullOrEmpty(txtSlabPriSteelCount.Text) ||
!int.TryParse(txtSlabPriSteelCount.Text, out _)))
return false;
return true;
}
catch (SysException ex)
{
MessageBox.Show($"输入验证错误: {ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public BeamParameters GetParameters()
{
try
{
return new BeamParameters
{
Thickness = int.TryParse(txtThickness.Text, out int thick) ? thick : 15,
BeamBottom = new BeamBottomSetting
{
SecondaryMaterial = cmbBeamBottomSecMaterial?.SelectedItem?.ToString() ?? "木方",
SecondarySpec = cmbBeamBottomSecSpec?.SelectedItem?.ToString() ?? "40x90",
SecondaryDirection = cmbBeamBottomSecDirection?.SelectedItem?.ToString() ?? "横向",
SecondarySpacing = txtBeamBottomSecSpacing?.Text ?? "@200",
PrimaryMaterial = cmbBeamBottomPriMaterial?.SelectedItem?.ToString() ?? "木方",
PrimarySpec = cmbBeamBottomPriSpec?.SelectedItem?.ToString() ?? "100x100",
PrimaryDirection = cmbBeamBottomPriDirection?.SelectedItem?.ToString() ?? "纵向",
PrimarySpacing = txtBeamBottomPriSpacing?.Text ?? ""
},
BeamSide = new BeamSideSetting
{
Enabled = chkBeamSideEnabled.Checked,
SecondaryMaterial = cmbBeamSideSecMaterial?.SelectedItem?.ToString() ?? "木方",
SecondarySpec = cmbBeamSideSecSpec?.SelectedItem?.ToString() ?? "40x90",
SecondaryDirection = cmbBeamSideSecDirection?.SelectedItem?.ToString() ?? "垂直",
SecondarySpacing = txtBeamSideSecSpacing?.Text ?? "@200",
PrimaryMaterial = cmbBeamSidePriMaterial?.SelectedItem?.ToString() ?? "木方",
PrimarySpec = cmbBeamSidePriSpec?.SelectedItem?.ToString() ?? "100x100",
PrimaryLayout = cmbBeamSidePriLayout?.SelectedItem?.ToString() ?? "双拼",
BoltDiameter = double.TryParse(txtBoltDiameter.Text, out double boltDia) ? boltDia : 12,
BoltStartHeight = double.TryParse(txtBoltStartHeight.Text, out double boltStart) ? boltStart : 50,
BoltSlabHeight = double.TryParse(txtBoltSlabHeight.Text, out double boltSlab) ? boltSlab : 250,
BoltSpacing = double.TryParse(txtBoltSpacing.Text, out double boltSpace) ? boltSpace : 500
},
Slab = new SlabSetting
{
SecondaryMaterial = cmbSlabSecMaterial?.SelectedItem?.ToString() ?? "木方",
SecondarySpec = cmbSlabSecSpec?.SelectedItem?.ToString() ?? "40x90",
SecondaryDirection = cmbSlabSecDirection?.SelectedItem?.ToString() ?? "横向",
SecondarySpacing = double.TryParse(txtSlabSecSpacing.Text, out double secSpacing) ? secSpacing : 200,
PrimaryMaterial = cmbSlabPriMaterial?.SelectedItem?.ToString() ?? "木方",
PrimarySpec = cmbSlabPriSpec?.SelectedItem?.ToString() ?? "100x100",
PrimaryDirection = cmbSlabPriDirection?.SelectedItem?.ToString() ?? "纵向",
SteelCount = int.TryParse(txtSlabPriSteelCount.Text, out int steelCount) ? steelCount : 1
}
};
}
catch (SysException ex)
{
MessageBox.Show($"获取参数错误: {ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return new BeamParameters();
}
}
}
#endregion
#region AutoCAD 命令
public class BeamSectionCommands
{
[CommandMethod("DB")]
public static void DrawBeamSection()
{
try
{
var doc = AcadApplication.DocumentManager.MdiActiveDocument;
if (doc == null)
{
AcadApplication.ShowAlertDialog("没有活动文档!");
return;
}
var db = doc.Database;
var ed = doc.Editor;
using (var form = new BeamSectionForm())
{
var res = AcadApplication.ShowModalDialog(form);
if (res != WinFormsDialogResult.OK)
{
ed.WriteMessage("\n用户取消操作。");
return;
}
// 获取参数
var parameters = form.GetParameters();
// 开始连续绘制
DrawContinuousBeamSections(ed, db, parameters);
}
}
catch (SysException ex)
{
var doc = AcadApplication.DocumentManager.MdiActiveDocument;
if (doc != null)
{
var ed = doc.Editor;
ed.WriteMessage($"\n严重错误: {ex.Message}\n{ex.StackTrace}");
}
else
{
MessageBox.Show($"严重错误: {ex.Message}",
"梁板剖面图错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private static void DrawContinuousBeamSections(Editor ed, Database db, BeamParameters parameters)
{
try
{
// 获取起始点
Point3d startPt = GetPoint(ed, "指定梁的起始点(按ESC退出):");
if (double.IsNaN(startPt.X)) return;
List<BeamSegment> segments = new List<BeamSegment>();
Point3d currentStart = startPt;
double lastSlabThickness = 250; // 默认板厚
double lastSlabOffset = 0; // 默认升降板高度
// 创建临时多段线用于实时显示
ObjectId tempPolylineId = ObjectId.Null;
try
{
// 创建临时多段线
using (var tempPolyline = new Polyline())
{
tempPolyline.AddVertexAt(0, new Point2d(currentStart.X, currentStart.Y), 0, 0, 0);
// 将临时多段线添加到图形
using (var trans = db.TransactionManager.StartTransaction())
{
var btr = (BlockTableRecord)trans.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
tempPolylineId = btr.AppendEntity(tempPolyline);
trans.AddNewlyCreatedDBObject(tempPolyline, true);
trans.Commit();
}
}
while (true)
{
// 获取下一个点(带橡皮筋效果)
Point3d endPt = GetPointWithRubberBand(ed, "指定下一个梁点(按ESC结束):", currentStart);
if (double.IsNaN(endPt.X)) break;
// 获取梁高
double beamHeight = GetHeight(ed);
if (double.IsNaN(beamHeight)) break;
// 获取板参数(使用上次值作为默认)
SlabParams slabParams = GetSlabParameters(ed, lastSlabThickness, lastSlabOffset);
if (slabParams == null) break;
// 保存当前设置供下次使用
lastSlabThickness = slabParams.Thickness;
lastSlabOffset = slabParams.Offset;
// 存储梁段信息
segments.Add(new BeamSegment
{
Start = currentStart,
End = endPt,
Height = beamHeight,
Slab = slabParams
});
// 更新临时多段线
using (var trans = db.TransactionManager.StartTransaction())
{
var tempPolyline = (Polyline)trans.GetObject(tempPolylineId, OpenMode.ForWrite);
int idx = tempPolyline.NumberOfVertices;
tempPolyline.AddVertexAt(idx, new Point2d(endPt.X, endPt.Y), 0, 0, 0);
trans.Commit();
}
// 当前终点作为下一段的起点
currentStart = endPt;
}
}
finally
{
// 删除临时多段线
if (tempPolylineId.IsValid && !tempPolylineId.IsErased)
{
using (var trans = db.TransactionManager.StartTransaction())
{
var tempPolyline = (Polyline)trans.GetObject(tempPolylineId, OpenMode.ForWrite);
tempPolyline.Erase();
trans.Commit();
}
}
}
// 绘制所有梁段
if (segments.Count > 0)
{
using (var tr = db.TransactionManager.StartTransaction())
{
try
{
// 创建连续梁板剖面
Polyline continuousPolyline = CreateContinuousBeamPolyline(segments);
var btr = (BlockTableRecord)tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
btr.AppendEntity(continuousPolyline);
tr.AddNewlyCreatedDBObject(continuousPolyline, true);
// 填充混凝土图案
var hatch = new Hatch();
btr.AppendEntity(hatch);
tr.AddNewlyCreatedDBObject(hatch, true);
hatch.SetHatchPattern(HatchPatternType.PreDefined, "AR-CONC");
hatch.Associative = true;
hatch.AppendLoop(HatchLoopTypes.Outermost, new ObjectIdCollection { continuousPolyline.ObjectId });
hatch.PatternScale = 50;
// 绘制标注和龙骨等...
DrawAllDimensionsAndMembers(ed, btr, tr, segments, parameters);
tr.Commit();
ed.WriteMessage($"\n成功绘制 {segments.Count} 个梁段组成的连续梁板剖面!");
}
catch (SysException ex)
{
tr.Abort();
ed.WriteMessage($"\n绘图错误: {ex.Message}");
}
}
}
}
catch (SysException ex)
{
ed.WriteMessage($"\n连续绘制错误: {ex.Message}");
}
}
private static Point3d GetPointWithRubberBand(Editor ed, string message, Point3d basePoint)
{
try
{
var opts = new PromptPointOptions(message)
{
UseBasePoint = true,
BasePoint = basePoint
};
var res = ed.GetPoint(opts);
return res.Status == PromptStatus.OK ? res.Value : new Point3d(double.NaN, double.NaN, double.NaN);
}
catch
{
return new Point3d(double.NaN, double.NaN, double.NaN);
}
}
private static Polyline CreateContinuousBeamPolyline(List<BeamSegment> segments)
{
if (segments == null || segments.Count == 0)
throw new ArgumentException("梁段数据为空");
var polyline = new Polyline();
int vertexIndex = 0;
// 添加第一个梁段的底部起点
polyline.AddVertexAt(vertexIndex++, new Point2d(segments[0].Start.X, segments[0].Start.Y), 0, 0, 0);
// 遍历所有梁段
foreach (var segment in segments)
{
Vector3d dir = (segment.End - segment.Start).GetNormal();
Vector3d perp = new Vector3d(-dir.Y, dir.X, 0) * segment.Height;
// 当前梁段终点
polyline.AddVertexAt(vertexIndex++, new Point2d(segment.End.X, segment.End.Y), 0, 0, 0);
// 当前梁段顶部终点
Point3d topEnd = segment.End + perp;
polyline.AddVertexAt(vertexIndex++, new Point2d(topEnd.X, topEnd.Y), 0, 0, 0);
// 当前梁段板位置(考虑升降板)
Point3d slabPoint = topEnd + dir * segment.Slab.Offset;
polyline.AddVertexAt(vertexIndex++, new Point2d(slabPoint.X, slabPoint.Y), 0, 0, 0);
// 板厚延伸点
Point3d slabThicknessPoint = slabPoint + dir * segment.Slab.Thickness;
polyline.AddVertexAt(vertexIndex++, new Point2d(slabThicknessPoint.X, slabThicknessPoint.Y), 0, 0, 0);
}
// 闭合多段线(从最后一个点回到起点)
Point3d firstPoint = segments[0].Start;
polyline.AddVertexAt(vertexIndex, new Point2d(firstPoint.X, firstPoint.Y), 0, 0, 0);
polyline.Closed = true;
return polyline;
}
private static SlabParams GetSlabParameters(Editor ed, double defaultThickness, double defaultOffset)
{
try
{
var pko = new PromptKeywordOptions("\n设置板参数[板厚(A)/升降板(S)/使用上次值(L)] <L>:");
pko.Keywords.Add("A");
pko.Keywords.Add("S");
pko.Keywords.Add("L");
pko.Keywords.Default = "L";
var pkr = ed.GetKeywords(pko);
if (pkr.Status != PromptStatus.OK) return null;
double thickness = defaultThickness;
double offset = defaultOffset;
if (pkr.StringResult == "A" || pkr.StringResult == "S")
{
var pdo = new PromptDoubleOptions("\n输入板厚(mm):");
pdo.DefaultValue = defaultThickness;
pdo.UseDefaultValue = true;
pdo.AllowNegative = false;
var pdr = ed.GetDouble(pdo);
if (pdr.Status != PromptStatus.OK) return null;
thickness = pdr.Value;
if (pkr.StringResult == "S")
{
pdo = new PromptDoubleOptions("\n输入升降高度(mm,正=升板,负=降板):");
pdo.DefaultValue = defaultOffset;
pdo.UseDefaultValue = true;
pdo.AllowNegative = true;
pdr = ed.GetDouble(pdo);
if (pdr.Status != PromptStatus.OK) return null;
offset = pdr.Value;
}
}
return new SlabParams { Thickness = thickness, Offset = offset };
}
catch
{
return null;
}
}
private static void DrawAllDimensionsAndMembers(Editor ed, BlockTableRecord btr, Transaction tr,
List<BeamSegment> segments, BeamParameters parameters)
{
try
{
// 绘制每个梁段的尺寸标注
foreach (var segment in segments)
{
// 梁宽标注
var dimWidth = new AlignedDimension();
dimWidth.SetDatabaseDefaults();
dimWidth.XLine1Point = segment.Start;
dimWidth.XLine2Point = segment.End;
dimWidth.DimLinePoint = new Point3d(
(segment.Start.X + segment.End.X) / 2,
segment.Start.Y - 50,
segment.Start.Z);
btr.AppendEntity(dimWidth);
tr.AddNewlyCreatedDBObject(dimWidth, true);
// 梁高标注
Vector3d perp = new Vector3d(-(segment.End.Y - segment.Start.Y),
segment.End.X - segment.Start.X, 0).GetNormal() * segment.Height;
var dimHeight = new AlignedDimension();
dimHeight.SetDatabaseDefaults();
dimHeight.XLine1Point = segment.Start;
dimHeight.XLine2Point = segment.Start + perp;
dimHeight.DimLinePoint = new Point3d(
segment.Start.X - 50,
segment.Start.Y + perp.Y / 2,
segment.Start.Z);
btr.AppendEntity(dimHeight);
tr.AddNewlyCreatedDBObject(dimHeight, true);
// 板厚标注
Vector3d dir = (segment.End - segment.Start).GetNormal();
Point3d slabStart = segment.End + perp + dir * segment.Slab.Offset;
Point3d slabEnd = slabStart + dir * segment.Slab.Thickness;
var dimSlab = new AlignedDimension();
dimSlab.SetDatabaseDefaults();
dimSlab.XLine1Point = slabStart;
dimSlab.XLine2Point = slabEnd;
dimSlab.DimLinePoint = new Point3d(
slabEnd.X + 50,
(slabStart.Y + slabEnd.Y) / 2,
slabStart.Z);
btr.AppendEntity(dimSlab);
tr.AddNewlyCreatedDBObject(dimSlab, true);
}
// 绘制主次龙骨(简化的实现)
// 实际应用中应根据参数设置详细绘制
}
catch (SysException ex)
{
ed.WriteMessage($"\n标注和龙骨绘制错误: {ex.Message}");
}
}
private static Point3d GetPoint(Editor ed, string message, Point3d? basePoint = null)
{
try
{
var opts = new PromptPointOptions(message);
if (basePoint.HasValue)
{
opts.UseBasePoint = true;
opts.BasePoint = basePoint.Value;
}
var res = ed.GetPoint(opts);
return res.Status == PromptStatus.OK ? res.Value : new Point3d(double.NaN, double.NaN, double.NaN);
}
catch
{
return new Point3d(double.NaN, double.NaN, double.NaN);
}
}
private static double GetHeight(Editor ed)
{
try
{
var opts = new PromptDoubleOptions("输入梁高(mm):");
opts.AllowNegative = false;
var res = ed.GetDouble(opts);
return res.Status == PromptStatus.OK ? res.Value : double.NaN;
}
catch
{
return double.NaN;
}
}
private static void DrawBeamBottomMembers(BlockTableRecord btr, Transaction tr, Polyline beamPoly,
BeamParameters parameters)
{
double beamLength = beamPoly.Length;
// 梁下次龙骨
if (parameters.BeamBottom.SecondaryDirection == "纵向")
{
double spacing = ParseSpacing(parameters.BeamBottom.SecondarySpacing, beamLength);
for (double pos = spacing; pos < beamLength; pos += spacing)
{
Point3d loc = beamPoly.GetPointAtDist(pos);
DrawMemberSection(btr, tr, loc, parameters.BeamBottom.SecondarySpec, 0);
}
}
// 梁下主龙骨
if (parameters.BeamBottom.PrimaryDirection == "纵向")
{
if (double.TryParse(parameters.BeamBottom.PrimarySpacing, out double spacing))
{
for (double pos = spacing; pos < beamLength; pos += spacing)
{
Point3d loc = beamPoly.GetPointAtDist(pos);
DrawMemberSection(btr, tr, loc, parameters.BeamBottom.PrimarySpec, 0);
}
}
}
else if (parameters.BeamBottom.PrimaryDirection == "纵向")
{
double spacing = 1000; // 默认纵向间距
for (double pos = spacing; pos < beamLength; pos += spacing)
{
Point3d loc = beamPoly.GetPointAtDist(pos);
DrawMemberSection(btr, tr, loc, parameters.BeamBottom.PrimarySpec, 0);
}
}
// 梁侧龙骨(如果启用)
if (parameters.BeamSide.Enabled)
{
// 实现梁侧龙骨绘制逻辑...
}
}
private static void DrawSlabMembers(BlockTableRecord btr, Transaction tr, Polyline beamPoly,
BeamParameters parameters)
{
// 板下次龙骨
if (parameters.Slab.SecondaryDirection == "纵向")
{
double spacing = parameters.Slab.SecondarySpacing;
for (double pos = spacing; pos < beamPoly.Length; pos += spacing)
{
Point3d loc = beamPoly.GetPointAtDist(pos);
DrawMemberSection(btr, tr, loc, parameters.Slab.SecondarySpec, 0);
}
}
// 板下主龙骨
if (parameters.Slab.PrimaryDirection == "纵向")
{
// 根据顶托内方钢数量绘制
for (int i = 0; i < parameters.Slab.SteelCount; i++)
{
// 绘制顶托内的方钢
// 这里需要根据实际位置计算
}
}
else if (parameters.Slab.PrimaryDirection == "纵向")
{
double spacing = 1000; // 默认纵向间距
for (double pos = spacing; pos < beamPoly.Length; pos += spacing)
{
Point3d loc = beamPoly.GetPointAtDist(pos);
DrawMemberSection(btr, tr, loc, parameters.Slab.PrimarySpec, 0);
}
}
}
private static void DrawMemberSection(BlockTableRecord btr, Transaction tr, Point3d loc,
string spec, double angle)
{
double width = 10, height = 10;
ParseMemberSpec(spec, ref width, ref height);
var rect = new Polyline();
rect.AddVertexAt(0, new Point2d(loc.X - width / 2, loc.Y - height / 2), 0, 0, 0);
rect.AddVertexAt(1, new Point2d(loc.X + width / 2, loc.Y - height / 2), 0, 0, 0);
rect.AddVertexAt(2, new Point2d(loc.X + width / 2, loc.Y + height / 2), 0, 0, 0);
rect.AddVertexAt(3, new Point2d(loc.X - width / 2, loc.Y + height / 2), 0, 0, 0);
rect.Closed = true;
if (angle != 0)
{
Matrix3d rotation = Matrix3d.Rotation(angle, Vector3d.ZAxis, loc);
rect.TransformBy(rotation);
}
btr.AppendEntity(rect);
tr.AddNewlyCreatedDBObject(rect, true);
}
private static void ParseMemberSpec(string spec, ref double width, ref double height)
{
if (spec.Contains("x") && !spec.Contains("Φ"))
{
string[] parts = spec.Split('x');
if (parts.Length >= 2)
{
string wStr = new string(parts[0].Where(c => char.IsDigit(c) || c == '.').ToArray());
string hStr = new string(parts[1].Where(c => char.IsDigit(c) || c == '.').ToArray());
double.TryParse(wStr, out width);
double.TryParse(hStr, out height);
}
}
else if (spec.Contains("Φ"))
{
string diamPart = spec.Split('x')[0].Replace("Φ", "");
string wStr = new string(diamPart.Where(c => char.IsDigit(c) || c == '.').ToArray());
double.TryParse(wStr, out width);
height = width;
}
else if (spec.StartsWith("I"))
{
string num = new string(spec.Where(char.IsDigit).ToArray());
if (int.TryParse(num, out int size))
{
width = size * 0.5;
height = size;
}
}
if (width <= 0) width = 10;
if (height <= 0) height = 10;
}
private static double ParseSpacing(string input, double totalLength)
{
if (input.Contains("@"))
{
string numPart = new string(input.Replace("@", "").Where(c => char.IsDigit(c) || c == '.').ToArray());
if (double.TryParse(numPart, out double spacing))
return spacing;
}
else if (input.Contains("根"))
{
string numPart = new string(input.Where(char.IsDigit).ToArray());
if (int.TryParse(numPart, out int count) && count > 1)
return totalLength / (count - 1);
}
return 200;
}
}
#endregion
}
绘制步骤错了,具体步骤如下:
第一步骤、指定梁的起始点,
第二步骤、指定下一个梁点,
第三步骤、输入梁高,
第四步骤、设置板参数,
重复第一步骤、指定梁的起始点,
重复第二步骤、指定下一个梁点,
重复第三步骤、输入梁高,
重复第四步骤、设置板参数,
一直重复操作,在绘制多段线时必须绘制一段显示一段线不然看不出梁或板绘制的轮廓线位置是否正确
最新发布