概述
在一些设计场景中,用户需要用到相互靠近但又不重叠的面域。但用户画图过程中,因为画图习惯或者精度问题,一些肉眼无法识别的重叠在所难免,因此需要些工具来辅助重叠判别和重叠区域识别。
原理
用面域间的布尔运算可以判定两个面域是否重叠。为了让用户知道重叠区域在哪,需要把重叠的区域生成重来,并设置特定的图层和颜色;当面域数量比较多时,耗时比较多,还需要设置进度条;判别完后,用户想知道有没有面域重叠,有多少个面域重叠,因此还需要输出结论;用户有时只想对某个或者某些图层进行面域识别,因此还需要提供一个选择的界面。整个原理比较简单,就不提供流程图了。
代码实现
完整业务代码(界面和ViewModel未包含)如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using CadToolset.Common;
using TimesBIM.CadToolset.App.Commands.Landscape;
using TimesBIM.CadToolset.App.Utils;
using TimesBIM.CadToolset.App.View.Landscape;
using TimesBIM.CadToolset.App.ViewModel.Landscape;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: CommandClass(typeof(CmdCheckRegion))]
namespace TimesBIM.CadToolset.App.Commands.Landscape
{
public class CmdCheckRegion
{
private const string _regionLayerName = "00-重叠面域";
[CommandMethod("MYJC")]
public void CheckRegion()
{
var db = Application.DocumentManager.MdiActiveDocument.Database;
using (var transaction = db.TransactionManager.StartTransaction())
{
var mDocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
var regions = GetRegions(transaction);//获取面域
var layerTable = transaction.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;//层表
var layerTableRecords = GetLayerTableRecords(layerTable);//获取层表记录
SetLayerByName(layerTable);//设置目标图层
var regionTuples = layerTableRecords.Select(x => new Tuple<string, List<Region>>(x.Name, regions //面域按图层分组
.Where(y => y.LayerId.ToString() == x.Id.ToString()).ToList())).ToList();
regionTuples = regionTuples.Where(x => x.Item2.Count > 0).ToList();
var checkRegionVM = new CheckRegionVM(regionTuples
.Select(x => new CheckRegionVM.LayerForCheck { ToCheck = x.Item1.Contains("(预)"), LayerName = x.Item1 }).ToList());
var checkRegionView = new CheckRegionView { DataContext = checkRegionVM };
checkRegionView.ShowDialog();
if ( !checkRegionView.ToConfirm) { transaction.Commit(); return; };//选择检查图层
CheckRegions(transaction, layerTable[_regionLayerName], checkRegionVM, regionTuples, regions);//检查
mDocumentLock.Dispose();
transaction.Commit();
}
}
private List<Region> GetRegions(Transaction transaction)
{
var regions = new List<Region>();
var doc = Application.DocumentManager.MdiActiveDocument;
var curBlockTb = transaction.GetObject(doc.Database.BlockTableId, OpenMode.ForWrite) as BlockTable; //当前文档块表
if (curBlockTb == null) { transaction.Commit(); return regions; }
var modelSpaceBlockTableRecord = (BlockTableRecord)transaction.GetObject(curBlockTb[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId id in modelSpaceBlockTableRecord)
{
var region = transaction.GetObject(id, OpenMode.ForRead);
if (region != null && region is Region) regions.Add(region as Region);
}
return regions;
}
private List<LayerTableRecord> GetLayerTableRecords(LayerTable layerTable)
{
var layerTableRecords = new List<LayerTableRecord>();
foreach (ObjectId id in layerTable)
{
layerTableRecords.Add((LayerTableRecord)id.GetObject(OpenMode.ForRead));
}
return layerTableRecords;
}
private void SetLayerByName(LayerTable layerTable)
{
using (var record = new LayerTableRecord())
{
record.Name = _regionLayerName;
record.Color = Color.FromRgb(255, 0, 0);
layerTable.UpgradeOpen();//修改图层打开方式为写
if (!layerTable.Has(record.Name)) layerTable.Add(record);//将新图层追加到图层表
layerTable.DowngradeOpen();
}
}
private void CheckRegions(Transaction transaction,ObjectId layerId, CheckRegionVM checkRegionVM, List<Tuple<string, List<Region>>> regionTuples, List<Region> regions)
{
var layers = checkRegionVM.LayerForChecks.Where(x => x.ToCheck).Select(x => x.LayerName).ToList();
regionTuples = regionTuples.Where(x => layers.Contains(x.Item1)).ToList();
regions = regions.Where(x => regionTuples.Any(y => y.Item2.Contains(x))).ToList();
var overlapedRegionCount = 0;
var count = regions.Count;
if (count < 2) { MessageBox.Show("面域数<2,不需要检查重叠");return; }
var progressMeter = new ProgressMeter();
progressMeter.Start("面域重叠检查进行中...");
progressMeter.SetLimit(count*(count-1)/2);
foreach (var region in regions)
{
int index = regions.IndexOf(region);
for (int i = index + 1; i < regions.Count; i++)
{
var overlapResult = RegionOverlap(region, regions[i], out var OverlapedRegion);
progressMeter.MeterProgress();
if (overlapResult)
{
OverlapedRegion.SetLayerId(layerId, true);
transaction.AddEntity(OverlapedRegion);//添加实体
overlapedRegionCount++;
}
}
}
progressMeter.Stop();
var message = overlapedRegionCount > 0 ? "重叠面域数为:" + overlapedRegionCount+ ",请检查图面。" : "未有发现面域重叠!";
if (overlapedRegionCount > 0) MessageBox.Show(message);
}
private static bool RegionOverlap(Region bigRegion, Region regionSecond,out Region region)
{
var newRegion1 = (Region)bigRegion.Clone();
region = (Region)regionSecond.Clone();
try
{
region.BooleanOperation(BooleanOperationType.BoolIntersect, newRegion1);
}
catch
{
return false;
}
return region.Area > 0;
}
}
}