using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using FengJing.Services.PlantLibModule;
using FengJing.Views.OtherView;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using Exception = Autodesk.AutoCAD.Runtime.Exception;
[assembly: CommandClass(typeof(FengJing.CADModule.PlantManager))]
namespace FengJing.CADModule
{
public class PlantManager
{
private static string _selectedPlantName = null;
private const string RegAppName = "MyPlantApp";
// 属性定义与标签的映射
private static readonly Dictionary<string, string> AttributeTags = new Dictionary<string, string>
{
{"名称", "PLANT_NAME"},
{"类型", "PLANT_TYPE"},
{"高度(m)", "PLANT_HEIGHT"},
{"冠幅(cm)", "PLANT_CROWN"},
{"胸径(cm)", "PLANT_DIAMETER"},
{"单位", "PLANT_UNIT"},
{"观赏价值", "PLANT_ORNAMENTAL"},
{"色叶期", "PLANT_COLOR_PERIOD"},
{"颜色", "PLANT_COLOR"},
{"耐湿耐旱性", "PLANT_TOLERANCE"},
{"海绵类", "PLANT_SPONGE"},
{"生长习性", "PLANT_HABIT"},
{"种植密度(株/㎡)", "PLANT_DENSITY"},
{"信息价(元)", "PLANT_PRICE"}
};
[CommandMethod("INSERT_PLANT", CommandFlags.Modal)]
public void InsertPlantBlock()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
RegisterRegAppName(db);
try
{
plantService plantService = new plantService();
List<Plant> allPlants = plantService.GetAllPlants();
if (allPlants == null || allPlants.Count == 0)
{
ed.WriteMessage("\n数据库中没有苗木数据!");
return;
}
_selectedPlantName = null;
Application.ShowModelessWindow(new PlantList(allPlants, this));
while (_selectedPlantName == null)
{
System.Windows.Forms.Application.DoEvents();
System.Threading.Thread.Sleep(100);
if (!Application.MainWindow.Visible) return;
}
string plantName = _selectedPlantName;
PromptPointResult ppr = ed.GetPoint("\n指定苗木插入点: ");
if (ppr.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable blockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
string blockName = GenerateBlockName(plantName);
if (!blockTable.Has(blockName))
{
ed.WriteMessage($"\n错误:未找到名为 {blockName} 的块定义,请在CAD中预先创建!");
return;
}
BlockReference blockRef = InsertPlantReference(tr, db, blockName, ppr.Value);
Plant plantForBinding = plantService.GetPlantByName(plantName);
if (plantForBinding != null)
{
BlockReference blockRefForWrite = (BlockReference)tr.GetObject(blockRef.ObjectId, OpenMode.ForWrite);
BindPlantAttributes(tr, blockRefForWrite, plantForBinding);
ed.WriteMessage($"\n苗木 '{plantName}' 属性已绑定到块!");
}
tr.Commit();
ed.WriteMessage($"\n苗木 '{plantName}' 插入成功!");
}
}
catch (Exception ex)
{
ed.WriteMessage($"\n错误: {ex.Message}");
}
}
[CommandMethod("BIND_PLANT", CommandFlags.Modal)]
public void BindPlantToBlock()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
RegisterRegAppName(db);
try
{
PromptEntityOptions opts = new PromptEntityOptions("\n选择要绑定苗木属性的块: ");
opts.SetRejectMessage("\n请选择一个块参照.");
opts.AddAllowedClass(typeof(BlockReference), false);
PromptEntityResult per = ed.GetEntity(opts);
if (per.Status != PromptStatus.OK) return;
plantService plantService = new plantService();
List<Plant> allPlants = plantService.GetAllPlants();
if (allPlants == null || allPlants.Count == 0)
{
ed.WriteMessage("\n数据库中没有苗木数据!");
return;
}
_selectedPlantName = null;
Application.ShowModelessWindow(new PlantList(allPlants, this));
while (_selectedPlantName == null)
{
System.Windows.Forms.Application.DoEvents();
System.Threading.Thread.Sleep(100);
if (!Application.MainWindow.Visible) return;
}
string plantName = _selectedPlantName;
Plant selectedPlant = plantService.GetPlantByName(plantName);
if (selectedPlant == null)
{
ed.WriteMessage($"\n未找到苗木: {plantName}");
return;
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference blockRef = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;
BindPlantAttributes(tr, blockRef, selectedPlant);
tr.Commit();
ed.WriteMessage($"\n成功绑定苗木属性到块: {plantName}");
}
}
catch (Exception ex)
{
ed.WriteMessage($"\n错误: {ex.Message}");
}
}
// 绑定属性到块属性
private void BindPlantAttributes(Transaction tr, BlockReference blockRef, Plant plant)
{
// 1. 绑定到块属性
if (blockRef.AttributeCollection.Count > 0)
{
foreach (ObjectId attId in blockRef.AttributeCollection)
{
AttributeReference attRef = tr.GetObject(attId, OpenMode.ForWrite) as AttributeReference;
if (attRef != null && AttributeTags.ContainsValue(attRef.Tag))
{
var mapping = AttributeTags.FirstOrDefault(x => x.Value == attRef.Tag);
if (!string.IsNullOrEmpty(mapping.Key))
{
attRef.TextString = GetPlantPropertyValue(plant, mapping.Key);
}
}
}
}
// 2. 同时保留XData以备其他用途
ResultBuffer rb = new ResultBuffer();
rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, RegAppName));
foreach (var prop in AttributeTags)
{
rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, prop.Key));
rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString,
GetPlantPropertyValue(plant, prop.Key)));
}
blockRef.XData = rb;
}
// 获取苗木属性值
private string GetPlantPropertyValue(Plant plant, string propertyName)
{
switch (propertyName)
{
case "名称": return plant.Name;
case "类型": return plant.Type?.Name ?? "未知";
case "高度(m)": return plant.Height.ToString("0.0");
case "冠幅(cm)": return plant.CrownWidth.ToString();
case "胸径(cm)": return plant.Diameter.ToString();
case "单位": return plant.Unit?.UnitName ?? "";
case "观赏价值": return plant.OrnamentalValue?.OrnamentalValueName ?? "";
case "色叶期": return plant.ColorPeriod?.ColorPeriodName ?? "";
case "颜色": return plant.Color?.ColorName ?? "";
case "耐湿耐旱性": return plant.WetDroughtTolerance;
case "海绵类": return plant.IsSpongePlant.ToString();
case "生长习性": return plant.Habit;
case "种植密度(株/㎡)": return plant.PlantingDensity.ToString();
case "信息价(元)": return plant.Price.ToString();
default: return string.Empty;
}
}
public void SetSelectedPlant(string plantName)
{
_selectedPlantName = plantName;
}
private string GenerateBlockName(string plantName)
{
return plantName
.Replace(" ", "_")
.Replace("/", "_")
.Replace("\\", "_")
.Replace("*", "")
.ToUpper();
}
private BlockReference InsertPlantReference(
Transaction tr, Database db, string blockName, Point3d insertionPoint)
{
BlockTable blockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
ObjectId blockId = blockTable[blockName];
BlockTableRecord modelSpace = tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db),
OpenMode.ForWrite) as BlockTableRecord;
BlockReference plantRef = new BlockReference(insertionPoint, blockId);
modelSpace.AppendEntity(plantRef);
tr.AddNewlyCreatedDBObject(plantRef, true);
// 创建属性引用
CreateAttributeReferences(tr, plantRef);
return plantRef;
}
// 创建属性引用
private void CreateAttributeReferences(Transaction tr, BlockReference blockRef)
{
BlockTableRecord btr = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
if (id.ObjectClass == RXClass.GetClass(typeof(AttributeDefinition)))
{
AttributeDefinition ad = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
if (ad != null && !ad.Constant)
{
AttributeReference ar = new AttributeReference();
ar.SetAttributeFromBlock(ad, blockRef.BlockTransform);
ar.Position = ad.Position.TransformBy(blockRef.BlockTransform);
ar.TextString = ad.TextString;
ar.Layer = blockRef.Layer;
ar.ColorIndex = blockRef.ColorIndex;
blockRef.AttributeCollection.AppendAttribute(ar);
tr.AddNewlyCreatedDBObject(ar, true);
}
}
}
}
private void RegisterRegAppName(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
RegAppTable regAppTable = tr.GetObject(db.RegAppTableId, OpenMode.ForWrite) as RegAppTable;
if (!regAppTable.Has(RegAppName))
{
RegAppTableRecord record = new RegAppTableRecord();
record.Name = RegAppName;
regAppTable.Add(record);
tr.AddNewlyCreatedDBObject(record, true);
}
tr.Commit();
}
}
}
}
整体代码实现还是有问题,我的需求如下:
1、在CAD界面先创建图形,然后把这些图形添加到块里
2、块添加完成之后,我需要输入命令选择苗木把苗木属性绑定到块的属性
3、绑定完成之后不需要输入其他命令,点击块,查看块的特性然后显示添加的苗木信息
最新发布