Skip to content

Commit dd6a17e

Browse files
authored
Merge pull request #12 from akinbender/copilot/add-braillerap-page-backend
Add BrailleRAP text-to-Braille translation and G-code generation with multi-language support
2 parents 07067d3 + 5e93f68 commit dd6a17e

21 files changed

Lines changed: 10121 additions & 2905 deletions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Represents a single Braille cell using Unicode Braille Patterns (U+2800 to U+28FF).
5+
/// </summary>
6+
public class BrailleCell
7+
{
8+
/// <summary>
9+
/// The Unicode character representing this Braille cell.
10+
/// </summary>
11+
public char Character { get; set; }
12+
13+
/// <summary>
14+
/// Creates a Braille cell from a Unicode Braille character.
15+
/// </summary>
16+
public BrailleCell(char character)
17+
{
18+
Character = character;
19+
}
20+
21+
/// <summary>
22+
/// Gets the value (0-255) representing the dot pattern.
23+
/// </summary>
24+
public int GetValue()
25+
{
26+
return Character - 0x2800;
27+
}
28+
29+
/// <summary>
30+
/// Checks if a specific dot is raised in this cell.
31+
/// </summary>
32+
public bool HasDot(BrailleDotPosition position)
33+
{
34+
int value = GetValue();
35+
return (value & (1 << (int)position)) != 0;
36+
}
37+
38+
public override string ToString()
39+
{
40+
return Character.ToString();
41+
}
42+
}
43+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Represents the position of a dot in a Braille cell (0-7 for 8-dot Braille).
5+
/// Standard 6-dot positions: 0-5
6+
/// Extended 8-dot positions: 0-7
7+
/// </summary>
8+
public enum BrailleDotPosition
9+
{
10+
Dot1 = 0, // Top-left
11+
Dot2 = 1, // Middle-left
12+
Dot3 = 2, // Bottom-left
13+
Dot4 = 3, // Top-right
14+
Dot5 = 4, // Middle-right
15+
Dot6 = 5, // Bottom-right
16+
Dot7 = 6, // Extended bottom-left
17+
Dot8 = 7 // Extended bottom-right
18+
}
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Represents a paginated layout of Braille text.
5+
/// </summary>
6+
public class BraillePageLayout
7+
{
8+
/// <summary>
9+
/// Pages of Braille lines.
10+
/// Each page contains multiple lines, each line is a string of Braille characters.
11+
/// </summary>
12+
public List<List<string>> Pages { get; set; } = new();
13+
14+
/// <summary>
15+
/// Gets the total number of pages.
16+
/// </summary>
17+
public int PageCount => Pages.Count;
18+
19+
/// <summary>
20+
/// Gets a specific page by index.
21+
/// </summary>
22+
public List<string> GetPage(int pageIndex)
23+
{
24+
if (pageIndex < 0 || pageIndex >= Pages.Count)
25+
return new List<string>();
26+
return Pages[pageIndex];
27+
}
28+
}
29+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Represents a geometric point in 2D space for BrailleRAP positioning.
5+
/// </summary>
6+
public record GeomPoint(double X, double Y);
7+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Configuration for BrailleRAP machine parameters.
5+
/// </summary>
6+
public class MachineConfig
7+
{
8+
/// <summary>
9+
/// Horizontal spacing between dots in a cell (mm).
10+
/// </summary>
11+
public double DotPaddingX { get; set; } = 2.2;
12+
13+
/// <summary>
14+
/// Vertical spacing between dots in a cell (mm).
15+
/// </summary>
16+
public double DotPaddingY { get; set; } = 2.2;
17+
18+
/// <summary>
19+
/// Horizontal spacing between cells (mm).
20+
/// </summary>
21+
public double CellPaddingX { get; set; } = 6.0;
22+
23+
/// <summary>
24+
/// Vertical spacing between lines (mm).
25+
/// </summary>
26+
public double CellPaddingY { get; set; } = 12.0;
27+
28+
/// <summary>
29+
/// Feed rate for movement (mm/min).
30+
/// </summary>
31+
public int FeedRate { get; set; } = 6000;
32+
33+
/// <summary>
34+
/// X-axis offset from origin (mm).
35+
/// </summary>
36+
public double OffsetX { get; set; } = 0.0;
37+
38+
/// <summary>
39+
/// Y-axis offset from origin (mm).
40+
/// </summary>
41+
public double OffsetY { get; set; } = 0.0;
42+
43+
/// <summary>
44+
/// Y-coordinate for return position after printing (mm).
45+
/// </summary>
46+
public double ReturnPositionY { get; set; } = 300.0;
47+
}
48+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace MakerPrompt.Shared.BrailleRAP.Models
2+
{
3+
/// <summary>
4+
/// Configuration for Braille page layout.
5+
/// </summary>
6+
public class PageConfig
7+
{
8+
/// <summary>
9+
/// Number of Braille cells per line.
10+
/// </summary>
11+
public int Columns { get; set; } = 28;
12+
13+
/// <summary>
14+
/// Maximum number of lines per page.
15+
/// </summary>
16+
public int Rows { get; set; } = 21;
17+
18+
/// <summary>
19+
/// Line spacing multiplier (0 = normal, 1 = double space, etc.).
20+
/// </summary>
21+
public int LineSpacing { get; set; } = 0;
22+
23+
/// <summary>
24+
/// Gets the computed number of rows based on spacing.
25+
/// </summary>
26+
public int GetComputedRows()
27+
{
28+
return (int)Math.Floor(Rows / ((LineSpacing * 0.5) + 1));
29+
}
30+
}
31+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using MakerPrompt.Shared.BrailleRAP.Models;
2+
using System.Text;
3+
4+
namespace MakerPrompt.Shared.BrailleRAP.Services
5+
{
6+
/// <summary>
7+
/// Generates G-code for BrailleRAP embossing from geometric points.
8+
/// Ported from AccessBrailleRAP's GeomToGCode.js
9+
/// </summary>
10+
public class BrailleGCodeGenerator
11+
{
12+
private readonly MachineConfig _config;
13+
14+
public BrailleGCodeGenerator(MachineConfig config)
15+
{
16+
_config = config;
17+
}
18+
19+
/// <summary>
20+
/// Generates complete G-code from geometric points.
21+
/// </summary>
22+
public string GenerateGCode(List<GeomPoint> points)
23+
{
24+
var gcode = new StringBuilder();
25+
26+
// Initialize
27+
gcode.Append(Home());
28+
gcode.Append(SetSpeed(_config.FeedRate));
29+
gcode.Append(MoveTo(0, 0));
30+
31+
// Process each point
32+
foreach (var point in points)
33+
{
34+
gcode.Append(MoveTo(point.X, point.Y));
35+
gcode.Append(PrintDot());
36+
}
37+
38+
// Return to home position
39+
gcode.Append(MoveTo(0, _config.ReturnPositionY));
40+
gcode.Append(MotorOff());
41+
42+
return gcode.ToString();
43+
}
44+
45+
/// <summary>
46+
/// Generates G-code from a Braille page layout.
47+
/// </summary>
48+
public string GenerateGCodeFromLayout(BraillePageLayout layout, int pageIndex = 0)
49+
{
50+
var page = layout.GetPage(pageIndex);
51+
if (page.Count == 0)
52+
return string.Empty;
53+
54+
var geometry = new BrailleToGeometry(_config);
55+
var points = geometry.BraillePageToGeom(page, _config.OffsetX, _config.OffsetY);
56+
57+
return GenerateGCode(points);
58+
}
59+
60+
private string MotorOff()
61+
{
62+
return "M84;\r\n";
63+
}
64+
65+
private string Home()
66+
{
67+
var sb = new StringBuilder();
68+
sb.Append("G28 X;\r\n");
69+
sb.Append("G28 Y;\r\n");
70+
return sb.ToString();
71+
}
72+
73+
private string GCodePosition(double? x, double? y)
74+
{
75+
if (x == null && y == null)
76+
{
77+
throw new ArgumentException("At least one coordinate must be specified");
78+
}
79+
80+
var code = new StringBuilder();
81+
82+
if (x.HasValue)
83+
{
84+
code.Append($" X{x.Value:F2}");
85+
}
86+
87+
if (y.HasValue)
88+
{
89+
code.Append($" Y{y.Value:F2}");
90+
}
91+
92+
code.Append(";\r\n");
93+
return code.ToString();
94+
}
95+
96+
private string SetSpeed(int speed)
97+
{
98+
return $"G1 F{speed};\r\n";
99+
}
100+
101+
private string MoveTo(double x, double y)
102+
{
103+
return "G1" + GCodePosition(x, y);
104+
}
105+
106+
private string PrintDot()
107+
{
108+
var sb = new StringBuilder();
109+
sb.Append("M3 S1;\r\n");
110+
sb.Append("M3 S0;\r\n");
111+
return sb.ToString();
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)