Editor/Output/ArchReport.WallDebug.cs

Editor-side report generator for wall geometry. It formats debug text describing each wall in a plan including start/end, length, direction, thickness, join info, grid snapping and baseboard/head measurements.

File Access
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;

namespace Sunless.Architecture;

public static partial class ArchReport
{
	// The same numbers the generator reads, so what is printed is what is built.
	public static string WallDebug( ArchPlan plan, ArchKit kit )
	{
		var grid = new ArchGridService();
		// The generator resolves across the whole storey, so a wall landing on the building next door
		// joins. Reading a building at a time made the report disagree with what was built at exactly
		// the joins that are hardest to settle by eye.
		var connections = new ArchConnectionService( plan, kit );
		var lines = new List<string>
		{
			"# Architecture wall debug",
			$"kit {kit.Name}  grid {grid.BaseSize:0.##}  wall thickness {kit.WallThickness:0.##}",
			""
		};

		foreach ( var building in plan.Buildings )
		{
			foreach ( var room in building.Rooms )
			{
				foreach ( var wall in room.Walls )
				{
					lines.AddRange( WallDebug( connections, building, room, wall, grid, kit ) );
				}
			}
		}

		return string.Join( "\n", lines );
	}

	static IEnumerable<string> WallDebug( ArchConnectionService connections, ArchBuilding building, ArchRoom room, ArchWall wall, ArchGridService grid, ArchKit kit )
	{
		var thickness = ArchWallSection.Thickness( wall, kit );
		var height = ArchWallSection.Height( wall, room, kit );
		var join = connections.JoinWall( wall, room, thickness );
		var foot = join.Foot( kit.BaseboardDepth );
		var head = join.Head( kit.BaseboardDepth );
		var from = join.From;
		var to = join.To;
		var side = wall.Normal * (thickness * 0.5f);
		var bandStart = wall.Start + wall.Direction * join.StartExtend - side;
		var bandEnd = wall.Start + wall.Direction * join.EndExtend - side;
		var bandTopEnd = wall.Start + wall.Direction * join.EndMitre + side;
		var bandTopStart = wall.Start + wall.Direction * join.StartMitre + side;

		return new[]
		{
			$"{building.Name}/{room.Name}/{ArchNames.Wall( wall )}  (id {wall.Id})",
			$"  start ({wall.Start.x:0.##},{wall.Start.y:0.##})  end ({wall.End.x:0.##},{wall.End.y:0.##})"
				+ $"  len {wall.Length:0.##}  dir ({wall.Direction.x:0.##},{wall.Direction.y:0.##})"
				+ $"  thickness {thickness:0.##}  height {height:0.##}"
				+ $"  exterior {wall.Exterior}  baseboard {wall.Baseboard}  cap {wall.Cap}",
			$"  grid  start {Grid( grid, wall.Start.x )},{Grid( grid, wall.Start.y )}  end {Grid( grid, wall.End.x )},{Grid( grid, wall.End.y )}",
			$"  join  start extend {join.StartExtend:0.##} joined {join.StartJoined} capped {join.StartCapped} mitre {join.StartMitre:0.##}"
				+ $"  |  end extend {join.EndExtend:0.##} joined {join.EndJoined} capped {join.EndCapped} mitre {join.EndMitre:0.##}"
				+ $"  landings [{string.Join( ", ", join.Landings.Select( value => value.ToString( "0.##" ) ) )}]",
			$"  board  foot {foot.Inner:0.##}/{foot.Outer:0.##} {foot.Stop}  |  head {head.Inner:0.##}/{head.Outer:0.##} {head.Stop}",
			$"  band  along {from:0.##}..{to:0.##}  corners ({bandStart.x:0.##},{bandStart.y:0.##}) ({bandEnd.x:0.##},{bandEnd.y:0.##})"
				+ $" ({bandTopEnd.x:0.##},{bandTopEnd.y:0.##}) ({bandTopStart.x:0.##},{bandTopStart.y:0.##})",
			""
		};
	}

	static string Grid( ArchGridService grid, float value ) => OnGrid( value, grid.BaseSize ) ? "on" : "off";

	static bool OnGrid( float value, float size ) => MathF.Abs( value - ArchGridService.Snap( value, size ) ) < 0.01f;

	static string Say( Vector3 point ) => $"{point.x:0.#},{point.y:0.#},{point.z:0.#}";
}