板房系统开发详解
第七章:板房系统开发详解
7.1 板房系统概述
7.1.1 功能介绍
板房系统是FY_Layout中最复杂的功能模块,用于在施工场地布置临时板房建筑。主要功能包括:
- 板房楼栋的创建和布置
- 单间板房的配置
- 楼层管理
- 房间功能设置(宿舍、办公室、会议室等)
- 人员配置
- 三维模型生成
7.1.2 核心类结构
PlateHouse/
├── PlateBuilding.cs # 单间板房类
├── PlateBuildGroup.cs # 板房楼栋类
├── PlateBuildingFloor.cs # 楼层类
├── PlateRoom.cs # 房间类
├── PlateK.cs # 板房单元格
├── PlatePassageway.cs # 走廊类
├── StairsCell.cs # 楼梯单元
├── GridCell.cs # 网格单元
├── PlateBuildingAction.cs # 板房操作类
├── PlateBuildGroupAction.cs # 楼栋操作类
├── PlateBuild3dAction.cs # 三维渲染类
├── PlateSet.cs # 板房设置窗口
├── PlateGroupSet.cs # 楼栋设置窗口
├── PlateRoomConfigManager.cs # 房间配置管理器
└── RoomConfigControl.cs # 房间配置控件
7.2 板房数据模型
7.2.1 PlateBuilding - 单间板房
public class PlateBuilding : DirectComponent
{
/// <summary>
/// 板房位置
/// </summary>
public Vector2 Position { get; set; }
/// <summary>
/// 板房宽度
/// </summary>
public double Width
{
get => Properties.GetValue<double>("Width");
set => SetProps((GetPropId(nameof(Width)), value));
}
/// <summary>
/// 板房深度(长度)
/// </summary>
public double Depth
{
get => Properties.GetValue<double>("Depth");
set => SetProps((GetPropId(nameof(Depth)), value));
}
/// <summary>
/// 板房高度
/// </summary>
public double Height
{
get => Properties.GetValue<double>("Height");
set => SetProps((GetPropId(nameof(Height)), value));
}
/// <summary>
/// 旋转角度
/// </summary>
public double Rotation
{
get => Properties.GetValue<double>("Rotation");
set => SetProps((GetPropId(nameof(Rotation)), value));
}
/// <summary>
/// 所属楼栋
/// </summary>
public PlateBuildGroup ParentGroup { get; set; }
/// <summary>
/// 所在楼层
/// </summary>
public int FloorIndex { get; set; }
/// <summary>
/// 房间类型
/// </summary>
public RoomType RoomType { get; set; }
public PlateBuilding()
{
Type = LayoutElementType.PlateBuilding;
Width = 6000; // 默认6米
Depth = 3000; // 默认3米
Height = 2800; // 默认2.8米
}
/// <summary>
/// 获取板房轮廓
/// </summary>
public override Curve2dGroupCollection GetShapes()
{
var shapes = new Curve2dGroupCollection();
var group = new Curve2dGroup();
// 计算四个角点
var halfW = Width / 2;
var halfD = Depth / 2;
var p1 = new Vector2(-halfW, -halfD);
var p2 = new Vector2(halfW, -halfD);
var p3 = new Vector2(halfW, halfD);
var p4 = new Vector2(-halfW, halfD);
// 应用旋转
var rotMatrix = new Matrix3().MakeRotation(Rotation);
p1.ApplyMatrix3(rotMatrix);
p2.ApplyMatrix3(rotMatrix);
p3.ApplyMatrix3(rotMatrix);
p4.ApplyMatrix3(rotMatrix);
// 平移到位置
p1.Add(Position);
p2.Add(Position);
p3.Add(Position);
p4.Add(Position);
// 创建轮廓
group.Curve2ds.Add(new Line2d(p1, p2));
group.Curve2ds.Add(new Line2d(p2, p3));
group.Curve2ds.Add(new Line2d(p3, p4));
group.Curve2ds.Add(new Line2d(p4, p1));
shapes.Add(group);
return shapes;
}
}
public enum RoomType
{
Dormitory, // 宿舍
Office, // 办公室
MeetingRoom, // 会议室
Canteen, // 食堂
Bathroom, // 卫生间
Storage, // 仓库
Guard, // 门卫室
Other // 其他
}
7.2.2 PlateBuildGroup - 板房楼栋
public class PlateBuildGroup : DirectComponent
{
/// <summary>
/// 楼栋位置
/// </summary>
public Vector2 Position { get; set; }
/// <summary>
/// 旋转角度
/// </summary>
public double Rotation { get; set; }
/// <summary>
/// 楼层数
/// </summary>
public int FloorCount
{
get => Properties.GetValue<int>("FloorCount");
set => SetProps((GetPropId(nameof(FloorCount)), value));
}
/// <summary>
/// 每层房间数(X方向)
/// </summary>
public int RoomsPerFloorX
{
get => Properties.GetValue<int>("RoomsPerFloorX");
set => SetProps((GetPropId(nameof(RoomsPerFloorX)), value));
}
/// <summary>
/// 每层房间数(Y方向)
/// </summary>
public int RoomsPerFloorY
{
get => Properties.GetValue<int>("RoomsPerFloorY");
set => SetProps((GetPropId(nameof(RoomsPerFloorY)), value));
}
/// <summary>
/// 单间宽度
/// </summary>
public double RoomWidth
{
get => Properties.GetValue<double>("RoomWidth");
set => SetProps((GetPropId(nameof(RoomWidth)), value));
}
/// <summary>
/// 单间深度
/// </summary>
public double RoomDepth
{
get => Properties.GetValue<double>("RoomDepth");
set => SetProps((GetPropId(nameof(RoomDepth)), value));
}
/// <summary>
/// 层高
/// </summary>
public double FloorHeight
{
get => Properties.GetValue<double>("FloorHeight");
set => SetProps((GetPropId(nameof(FloorHeight)), value));
}
/// <summary>
/// 走廊宽度
/// </summary>
public double CorridorWidth
{
get => Properties.GetValue<double>("CorridorWidth");
set => SetProps((GetPropId(nameof(CorridorWidth)), value));
}
/// <summary>
/// 楼层列表
/// </summary>
public List<PlateBuildingFloor> Floors { get; set; } = new List<PlateBuildingFloor>();
/// <summary>
/// 楼栋名称
/// </summary>
public string BuildingName { get; set; }
public PlateBuildGroup()
{
Type = LayoutElementType.PlateBuildGroup;
FloorCount = 2;
RoomsPerFloorX = 5;
RoomsPerFloorY = 2;
RoomWidth = 6000;
RoomDepth = 3000;
FloorHeight = 2800;
CorridorWidth = 1500;
}
/// <summary>
/// 生成楼层和房间
/// </summary>
public void GenerateFloors()
{
Floors.Clear();
for (int f = 0; f < FloorCount; f++)
{
var floor = new PlateBuildingFloor
{
FloorIndex = f,
Elevation = f * FloorHeight,
Rooms = new List<PlateRoom>()
};
// 生成房间
for (int x = 0; x < RoomsPerFloorX; x++)
{
for (int y = 0; y < RoomsPerFloorY; y++)
{
var room = new PlateRoom
{
GridX = x,
GridY = y,
Width = RoomWidth,
Depth = RoomDepth,
RoomType = RoomType.Dormitory
};
floor.Rooms.Add(room);
}
}
Floors.Add(floor);
}
}
/// <summary>
/// 计算楼栋总尺寸
/// </summary>
public (double width, double depth, double height) GetTotalSize()
{
double width = RoomsPerFloorX * RoomWidth;
double depth = RoomsPerFloorY * RoomDepth + CorridorWidth;
double height = FloorCount * FloorHeight;
return (width, depth, height);
}
}
7.2.3 PlateBuildingFloor - 楼层
public class PlateBuildingFloor
{
/// <summary>
/// 楼层索引(从0开始)
/// </summary>
public int FloorIndex { get; set; }
/// <summary>
/// 楼层标高
/// </summary>
public double Elevation { get; set; }
/// <summary>
/// 房间列表
/// </summary>
public List<PlateRoom> Rooms { get; set; } = new List<PlateRoom>();
/// <summary>
/// 楼梯列表
/// </summary>
public List<StairsCell> Stairs { get; set; } = new List<StairsCell>();
/// <summary>
/// 走廊
/// </summary>
public PlatePassageway Corridor { get; set; }
/// <summary>
/// 获取楼层名称
/// </summary>
public string FloorName => FloorIndex == 0 ? "首层" : $"{FloorIndex + 1}层";
/// <summary>
/// 获取指定位置的房间
/// </summary>
public PlateRoom GetRoom(int gridX, int gridY)
{
return Rooms.FirstOrDefault(r => r.GridX == gridX && r.GridY == gridY);
}
}
7.2.4 PlateRoom - 房间
public class PlateRoom
{
/// <summary>
/// 网格X坐标
/// </summary>
public int GridX { get; set; }
/// <summary>
/// 网格Y坐标
/// </summary>
public int GridY { get; set; }
/// <summary>
/// 房间宽度
/// </summary>
public double Width { get; set; }
/// <summary>
/// 房间深度
/// </summary>
public double Depth { get; set; }
/// <summary>
/// 房间类型
/// </summary>
public RoomType RoomType { get; set; }
/// <summary>
/// 房间名称
/// </summary>
public string RoomName { get; set; }
/// <summary>
/// 容纳人数
/// </summary>
public int Capacity { get; set; }
/// <summary>
/// 已分配人数
/// </summary>
public int AssignedCount { get; set; }
/// <summary>
/// 门的位置
/// </summary>
public DoorPosition DoorPosition { get; set; }
/// <summary>
/// 窗的位置列表
/// </summary>
public List<WindowPosition> Windows { get; set; } = new List<WindowPosition>();
public PlateRoom()
{
Width = 6000;
Depth = 3000;
RoomType = RoomType.Dormitory;
Capacity = 4;
}
/// <summary>
/// 获取房间面积
/// </summary>
public double GetArea()
{
return Width * Depth / 1000000; // 转换为平方米
}
}
public class DoorPosition
{
public Side Side { get; set; } // 门所在的边
public double Offset { get; set; } // 沿边的偏移
public double Width { get; set; } // 门宽
public double Height { get; set; } // 门高
}
public class WindowPosition
{
public Side Side { get; set; }
public double Offset { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Sill { get; set; } // 窗台高度
}
public enum Side
{
Front, Back, Left, Right
}
7.3 板房操作类
7.3.1 PlateBuildingAction
public class PlateBuildingAction : DirectComponentAction
{
public PlateBuildingAction() { }
public PlateBuildingAction(IDocumentEditor docEditor) : base(docEditor)
{
commandCtrl.WriteInfo("命令:PlateBuilding");
}
/// <summary>
/// 执行创建
/// </summary>
public async void ExecCreate(string[] args = null)
{
var pointInputer = new PointInputer(docEditor);
// 获取放置位置
commandCtrl.WriteInfo("指定板房放置位置:");
var result = await pointInputer.Execute();
if (result.Status != InputStatus.OK)
{
commandCtrl.WriteInfo("操作已取消");
return;
}
// 显示设置对话框
var settingForm = new PlateSet();
if (settingForm.ShowDialog() == DialogResult.OK)
{
CreatePlateBuilding(result.Point, settingForm.Settings);
}
}
private void CreatePlateBuilding(Vector2 position, PlateBuildingSettings settings)
{
var doc = docRt.Document;
var plate = new PlateBuilding
{
Position = position,
Width = settings.Width,
Depth = settings.Depth,
Height = settings.Height,
RoomType = settings.RoomType
};
plate.Initilize(doc);
plate.ResetBoundingBox();
plate.Layer = GetLayer().Name;
vportRt.ActiveElementSet.InsertElement(plate);
docRt.Action.ClearSelects();
}
/// <summary>
/// 绘制板房
/// </summary>
public override void Draw(LcCanvas2d canvas, LcElement element, Matrix3 matrix)
{
var plate = element as PlateBuilding;
var pen = GetDrawPen(plate);
// 绘制轮廓
foreach (var curve in plate.GetShapes()[0].Curve2ds)
{
canvas.DrawCurve(pen, curve, matrix);
}
// 绘制房间类型标注
var textPaint = new LcTextPaint
{
Color = pen.Color,
FontName = "仿宋",
Size = 500,
Position = plate.Position
};
canvas.DrawText(textPaint, GetRoomTypeText(plate.RoomType), matrix, out _);
}
private string GetRoomTypeText(RoomType type)
{
return type switch
{
RoomType.Dormitory => "宿舍",
RoomType.Office => "办公室",
RoomType.MeetingRoom => "会议室",
RoomType.Canteen => "食堂",
RoomType.Bathroom => "卫生间",
RoomType.Storage => "仓库",
RoomType.Guard => "门卫",
_ => "其他"
};
}
}
7.3.2 PlateBuildGroupAction
public class PlateBuildGroupAction : DirectComponentAction
{
public PlateBuildGroupAction() { }
public PlateBuildGroupAction(IDocumentEditor docEditor) : base(docEditor)
{
commandCtrl.WriteInfo("命令:PlateBuildGroup");
}
/// <summary>
/// 创建板房楼栋
/// </summary>
public async void ExecCreate(string[] args = null)
{
var pointInputer = new PointInputer(docEditor);
// 获取放置位置
commandCtrl.WriteInfo("指定楼栋放置位置:");
var result = await pointInputer.Execute();
if (result.Status != InputStatus.OK)
{
Cancel();
return;
}
// 显示楼栋设置对话框
var settingForm = new PlateGroupSet();
if (settingForm.ShowDialog() == DialogResult.OK)
{
CreateBuildGroup(result.Point, settingForm.Settings);
}
}
private void CreateBuildGroup(Vector2 position, PlateBuildGroupSettings settings)
{
var doc = docRt.Document;
var group = new PlateBuildGroup
{
Position = position,
BuildingName = settings.BuildingName,
FloorCount = settings.FloorCount,
RoomsPerFloorX = settings.RoomsPerFloorX,
RoomsPerFloorY = settings.RoomsPerFloorY,
RoomWidth = settings.RoomWidth,
RoomDepth = settings.RoomDepth,
FloorHeight = settings.FloorHeight,
CorridorWidth = settings.CorridorWidth
};
group.GenerateFloors();
group.Initilize(doc);
group.ResetBoundingBox();
group.Layer = GetLayer().Name;
vportRt.ActiveElementSet.InsertElement(group);
docRt.Action.ClearSelects();
commandCtrl.WriteInfo($"已创建楼栋:{settings.BuildingName},共{settings.FloorCount}层,{settings.RoomsPerFloorX * settings.RoomsPerFloorY * settings.FloorCount}个房间");
}
/// <summary>
/// 设置楼栋属性
/// </summary>
public void SetGroup(string[] args = null)
{
var selectedElements = docRt.GetSelectedElements();
var groups = selectedElements.OfType<PlateBuildGroup>().ToList();
if (groups.Count == 0)
{
commandCtrl.WriteError("请先选择板房楼栋");
return;
}
var settingForm = new PlateGroupSet(groups[0]);
if (settingForm.ShowDialog() == DialogResult.OK)
{
foreach (var group in groups)
{
UpdateGroupSettings(group, settingForm.Settings);
}
}
}
private void UpdateGroupSettings(PlateBuildGroup group, PlateBuildGroupSettings settings)
{
group.BuildingName = settings.BuildingName;
group.FloorCount = settings.FloorCount;
group.RoomsPerFloorX = settings.RoomsPerFloorX;
group.RoomsPerFloorY = settings.RoomsPerFloorY;
group.RoomWidth = settings.RoomWidth;
group.RoomDepth = settings.RoomDepth;
group.FloorHeight = settings.FloorHeight;
group.CorridorWidth = settings.CorridorWidth;
group.GenerateFloors();
group.ResetCache();
}
/// <summary>
/// 绘制楼栋
/// </summary>
public override void Draw(LcCanvas2d canvas, LcElement element, Matrix3 matrix)
{
var group = element as PlateBuildGroup;
var pen = GetDrawPen(group);
// 计算楼栋边界
var (width, depth, _) = group.GetTotalSize();
var halfW = width / 2;
var halfD = depth / 2;
// 绘制外边框
var p1 = group.Position + new Vector2(-halfW, -halfD);
var p2 = group.Position + new Vector2(halfW, -halfD);
var p3 = group.Position + new Vector2(halfW, halfD);
var p4 = group.Position + new Vector2(-halfW, halfD);
canvas.DrawLine(pen, p1.ApplyMatrix3(matrix), p2.ApplyMatrix3(matrix));
canvas.DrawLine(pen, p2.ApplyMatrix3(matrix), p3.ApplyMatrix3(matrix));
canvas.DrawLine(pen, p3.ApplyMatrix3(matrix), p4.ApplyMatrix3(matrix));
canvas.DrawLine(pen, p4.ApplyMatrix3(matrix), p1.ApplyMatrix3(matrix));
// 绘制内部网格(房间分隔)
DrawRoomGrid(canvas, group, matrix, pen);
// 绘制楼栋名称
var textPaint = new LcTextPaint
{
Color = pen.Color,
FontName = "仿宋",
Size = 1000,
Position = group.Position
};
canvas.DrawText(textPaint, group.BuildingName ?? "板房楼栋", matrix, out _);
}
private void DrawRoomGrid(LcCanvas2d canvas, PlateBuildGroup group, Matrix3 matrix, LcPaint pen)
{
var (width, depth, _) = group.GetTotalSize();
var startX = group.Position.X - width / 2;
var startY = group.Position.Y - depth / 2;
// 绘制垂直线(X方向分隔)
for (int x = 1; x < group.RoomsPerFloorX; x++)
{
var lineX = startX + x * group.RoomWidth;
var p1 = new Vector2(lineX, startY);
var p2 = new Vector2(lineX, startY + depth);
canvas.DrawLine(pen, p1.ApplyMatrix3(matrix), p2.ApplyMatrix3(matrix));
}
// 绘制水平线(Y方向分隔)
for (int y = 1; y <= group.RoomsPerFloorY; y++)
{
var lineY = startY + y * group.RoomDepth;
if (y == group.RoomsPerFloorY)
{
// 走廊分隔线
lineY = startY + group.RoomsPerFloorY * group.RoomDepth;
}
var p1 = new Vector2(startX, lineY);
var p2 = new Vector2(startX + width, lineY);
canvas.DrawLine(pen, p1.ApplyMatrix3(matrix), p2.ApplyMatrix3(matrix));
}
}
}
7.4 房间配置管理
7.4.1 PlateRoomConfigManager
public static class PlateRoomConfigManager
{
private static Dictionary<RoomType, RoomConfig> Configs = new Dictionary<RoomType, RoomConfig>();
public static void Init()
{
// 初始化默认配置
Configs[RoomType.Dormitory] = new RoomConfig
{
Type = RoomType.Dormitory,
Name = "宿舍",
DefaultCapacity = 4,
MinArea = 12,
RequiredFurniture = new[] { "床", "衣柜", "桌子" }
};
Configs[RoomType.Office] = new RoomConfig
{
Type = RoomType.Office,
Name = "办公室",
DefaultCapacity = 2,
MinArea = 15,
RequiredFurniture = new[] { "办公桌", "椅子", "文件柜" }
};
Configs[RoomType.MeetingRoom] = new RoomConfig
{
Type = RoomType.MeetingRoom,
Name = "会议室",
DefaultCapacity = 10,
MinArea = 30,
RequiredFurniture = new[] { "会议桌", "椅子", "投影仪" }
};
Configs[RoomType.Canteen] = new RoomConfig
{
Type = RoomType.Canteen,
Name = "食堂",
DefaultCapacity = 50,
MinArea = 100,
RequiredFurniture = new[] { "餐桌", "椅子", "厨具" }
};
Configs[RoomType.Bathroom] = new RoomConfig
{
Type = RoomType.Bathroom,
Name = "卫生间",
DefaultCapacity = 5,
MinArea = 10,
RequiredFurniture = new[] { "便器", "洗手台", "镜子" }
};
// 加载自定义配置
LoadCustomConfigs();
}
public static RoomConfig GetConfig(RoomType type)
{
return Configs.TryGetValue(type, out var config) ? config : null;
}
public static void SetConfig(RoomType type, RoomConfig config)
{
Configs[type] = config;
SaveCustomConfigs();
}
private static void LoadCustomConfigs()
{
var path = GetConfigFilePath();
if (File.Exists(path))
{
var json = File.ReadAllText(path);
var customConfigs = JsonConvert.DeserializeObject<Dictionary<RoomType, RoomConfig>>(json);
foreach (var kvp in customConfigs)
{
Configs[kvp.Key] = kvp.Value;
}
}
}
private static void SaveCustomConfigs()
{
var path = GetConfigFilePath();
var json = JsonConvert.SerializeObject(Configs, Formatting.Indented);
File.WriteAllText(path, json);
}
private static string GetConfigFilePath()
{
return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"LightCAD", "QdLayout", "room_configs.json"
);
}
}
public class RoomConfig
{
public RoomType Type { get; set; }
public string Name { get; set; }
public int DefaultCapacity { get; set; }
public double MinArea { get; set; }
public string[] RequiredFurniture { get; set; }
}
7.5 三维模型生成
7.5.1 PlateBuild3dAction
public class PlateBuild3dAction : IElement3dAction
{
/// <summary>
/// 生成板房楼栋的三维模型
/// </summary>
public Object3D Get3dObject(LcElement element, DocumentRuntime docRt)
{
var group = element as PlateBuildGroup;
var root = new Object3D();
// 获取楼栋尺寸
var (width, depth, height) = group.GetTotalSize();
// 生成每层
for (int f = 0; f < group.FloorCount; f++)
{
var floorObj = CreateFloor3D(group, f);
floorObj.Position.Y = f * group.FloorHeight;
root.Add(floorObj);
}
// 生成屋顶
var roofObj = CreateRoof3D(group);
roofObj.Position.Y = height;
root.Add(roofObj);
// 生成楼梯
if (group.FloorCount > 1)
{
var stairsObj = CreateStairs3D(group);
root.Add(stairsObj);
}
// 设置位置和旋转
root.Position.X = group.Position.X;
root.Position.Z = group.Position.Y;
root.Rotation.Y = group.Rotation;
return root;
}
private Object3D CreateFloor3D(PlateBuildGroup group, int floorIndex)
{
var floor = new Object3D();
var (width, depth, _) = group.GetTotalSize();
// 创建楼板
var slabGeometry = new BoxGeometry(width, 100, depth);
var slabMaterial = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0xCCCCCC)
};
var slab = new Mesh(slabGeometry, slabMaterial);
floor.Add(slab);
// 创建房间
var startX = -width / 2 + group.RoomWidth / 2;
var startZ = -depth / 2 + group.RoomDepth / 2;
for (int x = 0; x < group.RoomsPerFloorX; x++)
{
for (int y = 0; y < group.RoomsPerFloorY; y++)
{
var room = CreateRoom3D(group, floorIndex, x, y);
room.Position.X = startX + x * group.RoomWidth;
room.Position.Z = startZ + y * group.RoomDepth;
floor.Add(room);
}
}
// 创建走廊
var corridorObj = CreateCorridor3D(group);
corridorObj.Position.Z = -depth / 2 + group.RoomsPerFloorY * group.RoomDepth + group.CorridorWidth / 2;
floor.Add(corridorObj);
return floor;
}
private Object3D CreateRoom3D(PlateBuildGroup group, int floorIndex, int gridX, int gridY)
{
var room = new Object3D();
var floor = group.Floors[floorIndex];
var roomData = floor.GetRoom(gridX, gridY);
// 墙体高度
var wallHeight = group.FloorHeight - 100; // 减去楼板厚度
var wallThickness = 100;
// 创建四面墙
// 前墙
var frontWall = CreateWall(group.RoomWidth, wallHeight, wallThickness);
frontWall.Position.Z = group.RoomDepth / 2;
room.Add(frontWall);
// 后墙
var backWall = CreateWall(group.RoomWidth, wallHeight, wallThickness);
backWall.Position.Z = -group.RoomDepth / 2;
room.Add(backWall);
// 左墙
var leftWall = CreateWall(wallThickness, wallHeight, group.RoomDepth);
leftWall.Position.X = -group.RoomWidth / 2;
room.Add(leftWall);
// 右墙
var rightWall = CreateWall(wallThickness, wallHeight, group.RoomDepth);
rightWall.Position.X = group.RoomWidth / 2;
room.Add(rightWall);
// 添加门洞
if (roomData?.DoorPosition != null)
{
// 在相应的墙上创建门洞
// 简化实现:使用布尔运算或多个几何体组合
}
return room;
}
private Mesh CreateWall(double width, double height, double depth)
{
var geometry = new BoxGeometry(width, height, depth);
var material = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0xFFFFFF)
};
var mesh = new Mesh(geometry, material);
mesh.Position.Y = height / 2;
return mesh;
}
private Object3D CreateCorridor3D(PlateBuildGroup group)
{
var corridor = new Object3D();
var (width, _, _) = group.GetTotalSize();
// 走廊地面
var floorGeometry = new BoxGeometry(width, 50, group.CorridorWidth);
var floorMaterial = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0x808080)
};
var floorMesh = new Mesh(floorGeometry, floorMaterial);
corridor.Add(floorMesh);
// 走廊护栏
var railHeight = 1000;
var railGeometry = new BoxGeometry(width, railHeight, 50);
var railMaterial = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0x404040)
};
var railMesh = new Mesh(railGeometry, railMaterial);
railMesh.Position.Y = railHeight / 2;
railMesh.Position.Z = group.CorridorWidth / 2;
corridor.Add(railMesh);
return corridor;
}
private Object3D CreateRoof3D(PlateBuildGroup group)
{
var roof = new Object3D();
var (width, depth, _) = group.GetTotalSize();
var roofGeometry = new BoxGeometry(width + 200, 100, depth + 200);
var roofMaterial = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0x404040)
};
var roofMesh = new Mesh(roofGeometry, roofMaterial);
roof.Add(roofMesh);
return roof;
}
private Object3D CreateStairs3D(PlateBuildGroup group)
{
var stairs = new Object3D();
// 简化的楼梯实现
var stairWidth = 1200;
var stairDepth = 2400;
for (int f = 0; f < group.FloorCount - 1; f++)
{
var stairRun = CreateStairRun(stairWidth, group.FloorHeight, stairDepth);
stairRun.Position.Y = f * group.FloorHeight;
stairs.Add(stairRun);
}
return stairs;
}
private Object3D CreateStairRun(double width, double height, double depth)
{
var stairRun = new Object3D();
int stepCount = 16;
var stepHeight = height / stepCount;
var stepDepth = depth / stepCount;
for (int i = 0; i < stepCount; i++)
{
var stepGeometry = new BoxGeometry(width, stepHeight, stepDepth);
var stepMaterial = new MeshLambertMaterial
{
Color = new ThreeJs4Net.Color(0x808080)
};
var stepMesh = new Mesh(stepGeometry, stepMaterial);
stepMesh.Position.Y = i * stepHeight + stepHeight / 2;
stepMesh.Position.Z = i * stepDepth + stepDepth / 2;
stairRun.Add(stepMesh);
}
return stairRun;
}
}
7.6 设置界面
7.6.1 PlateGroupSet窗口
设置楼栋参数的WinForms对话框:
public partial class PlateGroupSet : Form
{
public PlateBuildGroupSettings Settings { get; private set; }
public PlateGroupSet()
{
InitializeComponent();
Settings = new PlateBuildGroupSettings();
LoadDefaults();
}
public PlateGroupSet(PlateBuildGroup existingGroup) : this()
{
// 从现有楼栋加载设置
txtBuildingName.Text = existingGroup.BuildingName;
numFloorCount.Value = existingGroup.FloorCount;
numRoomsX.Value = existingGroup.RoomsPerFloorX;
numRoomsY.Value = existingGroup.RoomsPerFloorY;
numRoomWidth.Value = (decimal)(existingGroup.RoomWidth / 1000);
numRoomDepth.Value = (decimal)(existingGroup.RoomDepth / 1000);
numFloorHeight.Value = (decimal)(existingGroup.FloorHeight / 1000);
numCorridorWidth.Value = (decimal)(existingGroup.CorridorWidth / 1000);
}
private void LoadDefaults()
{
txtBuildingName.Text = "板房楼栋";
numFloorCount.Value = 2;
numRoomsX.Value = 5;
numRoomsY.Value = 2;
numRoomWidth.Value = 6;
numRoomDepth.Value = 3;
numFloorHeight.Value = 2.8m;
numCorridorWidth.Value = 1.5m;
}
private void btnOK_Click(object sender, EventArgs e)
{
Settings = new PlateBuildGroupSettings
{
BuildingName = txtBuildingName.Text,
FloorCount = (int)numFloorCount.Value,
RoomsPerFloorX = (int)numRoomsX.Value,
RoomsPerFloorY = (int)numRoomsY.Value,
RoomWidth = (double)numRoomWidth.Value * 1000,
RoomDepth = (double)numRoomDepth.Value * 1000,
FloorHeight = (double)numFloorHeight.Value * 1000,
CorridorWidth = (double)numCorridorWidth.Value * 1000
};
DialogResult = DialogResult.OK;
Close();
}
}
public class PlateBuildGroupSettings
{
public string BuildingName { get; set; }
public int FloorCount { get; set; }
public int RoomsPerFloorX { get; set; }
public int RoomsPerFloorY { get; set; }
public double RoomWidth { get; set; }
public double RoomDepth { get; set; }
public double FloorHeight { get; set; }
public double CorridorWidth { get; set; }
}
7.7 本章小结
本章详细介绍了FY_Layout中板房系统的开发:
- 数据模型:PlateBuilding、PlateBuildGroup、PlateBuildingFloor、PlateRoom的设计
- 操作类:PlateBuildingAction和PlateBuildGroupAction的实现
- 房间配置:PlateRoomConfigManager的配置管理
- 三维模型:PlateBuild3dAction的三维生成逻辑
- 设置界面:PlateGroupSet对话框的实现
板房系统是FY_Layout中最复杂的模块,涉及多层数据结构、参数化设计和三维模型生成。掌握这个模块的开发方法,对于开发其他复杂的BIM组件有很大帮助。
下一章我们将学习二维绘图与交互操作的详细内容。

浙公网安备 33010602011771号