Skip to content
43 changes: 43 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/BrailleCell.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Represents a single Braille cell using Unicode Braille Patterns (U+2800 to U+28FF).
/// </summary>
public class BrailleCell
{
/// <summary>
/// The Unicode character representing this Braille cell.
/// </summary>
public char Character { get; set; }

/// <summary>
/// Creates a Braille cell from a Unicode Braille character.
/// </summary>
public BrailleCell(char character)
{
Character = character;
}

/// <summary>
/// Gets the value (0-255) representing the dot pattern.
/// </summary>
public int GetValue()
{
return Character - 0x2800;
}

/// <summary>
/// Checks if a specific dot is raised in this cell.
/// </summary>
public bool HasDot(BrailleDotPosition position)
{
int value = GetValue();
return (value & (1 << (int)position)) != 0;
}

public override string ToString()
{
return Character.ToString();
}
}
}
19 changes: 19 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/BrailleDot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Represents the position of a dot in a Braille cell (0-7 for 8-dot Braille).
/// Standard 6-dot positions: 0-5
/// Extended 8-dot positions: 0-7
/// </summary>
public enum BrailleDotPosition
{
Dot1 = 0, // Top-left
Dot2 = 1, // Middle-left
Dot3 = 2, // Bottom-left
Dot4 = 3, // Top-right
Dot5 = 4, // Middle-right
Dot6 = 5, // Bottom-right
Dot7 = 6, // Extended bottom-left
Dot8 = 7 // Extended bottom-right
}
}
29 changes: 29 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/BraillePageLayout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Represents a paginated layout of Braille text.
/// </summary>
public class BraillePageLayout
{
/// <summary>
/// Pages of Braille lines.
/// Each page contains multiple lines, each line is a string of Braille characters.
/// </summary>
public List<List<string>> Pages { get; set; } = new();

/// <summary>
/// Gets the total number of pages.
/// </summary>
public int PageCount => Pages.Count;

/// <summary>
/// Gets a specific page by index.
/// </summary>
public List<string> GetPage(int pageIndex)
{
if (pageIndex < 0 || pageIndex >= Pages.Count)
return new List<string>();
return Pages[pageIndex];
}
}
}
7 changes: 7 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/GeomPoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Represents a geometric point in 2D space for BrailleRAP positioning.
/// </summary>
public record GeomPoint(double X, double Y);
}
48 changes: 48 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/MachineConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Configuration for BrailleRAP machine parameters.
/// </summary>
public class MachineConfig
{
/// <summary>
/// Horizontal spacing between dots in a cell (mm).
/// </summary>
public double DotPaddingX { get; set; } = 2.2;

/// <summary>
/// Vertical spacing between dots in a cell (mm).
/// </summary>
public double DotPaddingY { get; set; } = 2.2;

/// <summary>
/// Horizontal spacing between cells (mm).
/// </summary>
public double CellPaddingX { get; set; } = 6.0;

/// <summary>
/// Vertical spacing between lines (mm).
/// </summary>
public double CellPaddingY { get; set; } = 12.0;

/// <summary>
/// Feed rate for movement (mm/min).
/// </summary>
public int FeedRate { get; set; } = 6000;

/// <summary>
/// X-axis offset from origin (mm).
/// </summary>
public double OffsetX { get; set; } = 0.0;

/// <summary>
/// Y-axis offset from origin (mm).
/// </summary>
public double OffsetY { get; set; } = 0.0;

/// <summary>
/// Y-coordinate for return position after printing (mm).
/// </summary>
public double ReturnPositionY { get; set; } = 300.0;
}
}
31 changes: 31 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Models/PageConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace MakerPrompt.Shared.BrailleRAP.Models
{
/// <summary>
/// Configuration for Braille page layout.
/// </summary>
public class PageConfig
{
/// <summary>
/// Number of Braille cells per line.
/// </summary>
public int Columns { get; set; } = 28;

/// <summary>
/// Maximum number of lines per page.
/// </summary>
public int Rows { get; set; } = 21;

/// <summary>
/// Line spacing multiplier (0 = normal, 1 = double space, etc.).
/// </summary>
public int LineSpacing { get; set; } = 0;

/// <summary>
/// Gets the computed number of rows based on spacing.
/// </summary>
public int GetComputedRows()
{
return (int)Math.Floor(Rows / ((LineSpacing * 0.5) + 1));
}
}
}
114 changes: 114 additions & 0 deletions MakerPrompt.Shared/BrailleRAP/Services/BrailleGCodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using MakerPrompt.Shared.BrailleRAP.Models;
using System.Text;

namespace MakerPrompt.Shared.BrailleRAP.Services
{
/// <summary>
/// Generates G-code for BrailleRAP embossing from geometric points.
/// Ported from AccessBrailleRAP's GeomToGCode.js
/// </summary>
public class BrailleGCodeGenerator
{
private readonly MachineConfig _config;

public BrailleGCodeGenerator(MachineConfig config)
{
_config = config;
}

/// <summary>
/// Generates complete G-code from geometric points.
/// </summary>
public string GenerateGCode(List<GeomPoint> points)
{
var gcode = new StringBuilder();

// Initialize
gcode.Append(Home());
gcode.Append(SetSpeed(_config.FeedRate));
gcode.Append(MoveTo(0, 0));

// Process each point
foreach (var point in points)
{
gcode.Append(MoveTo(point.X, point.Y));
gcode.Append(PrintDot());
}

// Return to home position
gcode.Append(MoveTo(0, _config.ReturnPositionY));
gcode.Append(MotorOff());

return gcode.ToString();
}

/// <summary>
/// Generates G-code from a Braille page layout.
/// </summary>
public string GenerateGCodeFromLayout(BraillePageLayout layout, int pageIndex = 0)
{
var page = layout.GetPage(pageIndex);
if (page.Count == 0)
return string.Empty;

var geometry = new BrailleToGeometry(_config);
var points = geometry.BraillePageToGeom(page, _config.OffsetX, _config.OffsetY);

return GenerateGCode(points);
}

private string MotorOff()
{
return "M84;\r\n";
}

private string Home()
{
var sb = new StringBuilder();
sb.Append("G28 X;\r\n");
sb.Append("G28 Y;\r\n");
return sb.ToString();
}

private string GCodePosition(double? x, double? y)
{
if (x == null && y == null)
{
throw new ArgumentException("At least one coordinate must be specified");
}

var code = new StringBuilder();

if (x.HasValue)
{
code.Append($" X{x.Value:F2}");
}

if (y.HasValue)
{
code.Append($" Y{y.Value:F2}");
}

code.Append(";\r\n");
return code.ToString();
}

private string SetSpeed(int speed)
{
return $"G1 F{speed};\r\n";
}

private string MoveTo(double x, double y)
{
return "G1" + GCodePosition(x, y);
}

private string PrintDot()
{
var sb = new StringBuilder();
sb.Append("M3 S1;\r\n");
sb.Append("M3 S0;\r\n");
return sb.ToString();
}
}
}
Loading
Loading