Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9636514dfc |
16 changed files with 75 additions and 512 deletions
|
@ -1,3 +1,3 @@
|
||||||
# lauchpioos
|
# lauchpioos
|
||||||
|
|
||||||
Under construction
|
A JavaScript geometry sketching library.
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
point(200, 300) -> A
|
point(3 | 4)
|
||||||
point(400, 300) -> B
|
|
||||||
[point(300, 128) -> C]
|
|
||||||
|
|
||||||
line(A, B) -> AB
|
point(6 | 7)
|
||||||
line(B, C)
|
|
||||||
line(C, A)
|
|
||||||
|
|
||||||
circle(A, len(AB))
|
|
||||||
circle(B, len(AB))
|
|
|
@ -1,9 +0,0 @@
|
||||||
point(-1, 0) -> A
|
|
||||||
point(1, 0) -> B
|
|
||||||
line(A, B) -> AB
|
|
||||||
len(AB) -> length
|
|
||||||
circle(A, len(AB)) -> circleA
|
|
||||||
circle(B, len(AB)) -> circleB
|
|
||||||
intersection(circleA, circleB, 0) -> C
|
|
||||||
line(A, C)
|
|
||||||
line(B, C)
|
|
|
@ -1,31 +1,16 @@
|
||||||
# Syntax
|
# Syntax
|
||||||
|
|
||||||
```
|
```
|
||||||
[point(3, 4) -> A]
|
point(3 | 4) -> A
|
||||||
point(6, 7) -> B
|
point(6 | 7) -> B
|
||||||
|
|
||||||
line[color=red, weight=4](A, B) -> AB
|
line(A, B) -> AB
|
||||||
line(point(0, 0), point(100, 100))
|
line(0 | 0, 100 | 100)
|
||||||
|
|
||||||
circle(A, len(AB))
|
circle(A, len(AB))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Behaviour
|
## Primitives
|
||||||
Every line is one instruction. It is possible to assign instructions names to re-use them later.
|
* `Point point(x, y)` is a 2D point. It returns an element of type `Point`
|
||||||
These variables are immutable. Objects do not exist in this script, in fact, variables are more similar to C-style macros than actual variables.
|
* `Line line(Point from, Point to)` is a straight line. It returns an element of type `Line`.
|
||||||
|
* `Circle circle(Point center, radius)` draws a circle at `center` and `radius`
|
||||||
Lines in brackets `[]` are "hidden". They are parsed, but will not be rendered.
|
|
||||||
|
|
||||||
It is possible to add an optional set of parameters in front of each parameter list, in order to specify the appearance of the element.
|
|
||||||
|
|
||||||
## Primitives vs Functions
|
|
||||||
Primitives (e.g. `point`, `line`) and Functions (e.g. `len`, `intersection`) are syntactically indistinguishable.
|
|
||||||
Both can be used as parameters or instructions and can be assigned to variables. The only difference is that Primitives generate a visual output (unless they are surrounded by square brackets)
|
|
||||||
|
|
||||||
## Grammar
|
|
||||||
```
|
|
||||||
instruction ::= identifier({parameter, }) [-> identifer]
|
|
||||||
parameter ::= instruction | identifier | number
|
|
||||||
identifier ::= (A-Za-z)
|
|
||||||
number ::= (0-9)[.(0-9)]
|
|
||||||
```
|
|
|
@ -1,9 +0,0 @@
|
||||||
# TODO (Parser)
|
|
||||||
* Type checking
|
|
||||||
* Ignore case in instruction names
|
|
||||||
* Implement remaining functions
|
|
||||||
* Abort parsing on error
|
|
||||||
|
|
||||||
# TODO (Renderer)
|
|
||||||
* Implement shape classes
|
|
||||||
* Render shape classes
|
|
|
@ -1,11 +1,10 @@
|
||||||
/// <reference path="vector.ts" />
|
import { Vector2D } from "./vector.js"
|
||||||
/// <reference path="gfx/polygon.ts" />
|
import * as shape from "./shapes.js"
|
||||||
/// <reference path="parser/parser.ts" />
|
|
||||||
|
|
||||||
function loadScript(filepath: string): string
|
function loadScript(filepath: string): string
|
||||||
{
|
{
|
||||||
let result = null;
|
var result = null;
|
||||||
let xmlhttp = new XMLHttpRequest();
|
var xmlhttp = new XMLHttpRequest();
|
||||||
xmlhttp.open("GET", filepath, false);
|
xmlhttp.open("GET", filepath, false);
|
||||||
xmlhttp.send();
|
xmlhttp.send();
|
||||||
if (xmlhttp.status==200) {
|
if (xmlhttp.status==200) {
|
||||||
|
@ -17,7 +16,6 @@ function loadScript(filepath: string): string
|
||||||
|
|
||||||
class Geometry extends HTMLElement
|
class Geometry extends HTMLElement
|
||||||
{
|
{
|
||||||
private shapes: Shape[];
|
|
||||||
private canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
private context: CanvasRenderingContext2D;
|
private context: CanvasRenderingContext2D;
|
||||||
private sourceFile: string;
|
private sourceFile: string;
|
||||||
|
@ -25,7 +23,7 @@ class Geometry extends HTMLElement
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
console.log("constructor")
|
|
||||||
if(!this.hasAttribute("src"))
|
if(!this.hasAttribute("src"))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -34,16 +32,37 @@ class Geometry extends HTMLElement
|
||||||
let sourceFile = this.getAttribute("src");
|
let sourceFile = this.getAttribute("src");
|
||||||
let content = loadScript(sourceFile);
|
let content = loadScript(sourceFile);
|
||||||
|
|
||||||
let parser = new Parser(content);
|
let lines = content.split("\n");
|
||||||
if(!parser.good())
|
for(let line of lines)
|
||||||
{
|
{
|
||||||
console.error("Failed to create parser for script " + sourceFile);
|
if(line === "\r")
|
||||||
return;
|
{
|
||||||
|
console.log("empty");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let instruction = line.split("(")[0];
|
||||||
|
|
||||||
|
switch(instruction)
|
||||||
|
{
|
||||||
|
case instruction:
|
||||||
|
{
|
||||||
|
let coords = line.split("(")[1].split("|");
|
||||||
|
console.log(coords);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
console.log("something else");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.attachShadow({mode: "open"});
|
this.attachShadow({mode: "open"});
|
||||||
let canvas = document.createElement("canvas");
|
let canvas = document.createElement("canvas");
|
||||||
canvas.width = 700;
|
canvas.width = 500;
|
||||||
canvas.height = 500;
|
canvas.height = 500;
|
||||||
let context = canvas.getContext("2d");
|
let context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
@ -52,38 +71,13 @@ class Geometry extends HTMLElement
|
||||||
|
|
||||||
this.shadowRoot.append(this.canvas);
|
this.shadowRoot.append(this.canvas);
|
||||||
|
|
||||||
|
|
||||||
this.shapes = []
|
|
||||||
for(let instruction of parser.instructions)
|
|
||||||
{
|
|
||||||
let value = instruction.eval();
|
|
||||||
switch(instruction.getType())
|
|
||||||
{
|
|
||||||
case InstructionType.Line:
|
|
||||||
{
|
|
||||||
console.log("New line " + value)
|
|
||||||
this.shapes.push(new Line(this.context, new Vector2D(value[0].x, value[0].y), new Vector2D(value[1].x, value[1].y)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case InstructionType.Circle:
|
|
||||||
{
|
|
||||||
console.log("New circle " + value)
|
|
||||||
this.shapes.push(new Circle(this.context, new Vector2D(value[0].x, value[0].y), value[1]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.redraw();
|
this.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
private redraw()
|
private redraw()
|
||||||
{
|
{
|
||||||
for (let shape of this.shapes)
|
shape.line(this.context, new Vector2D(), new Vector2D(300, 300));
|
||||||
{
|
shape.circle(this.context, new Vector2D(150, 150), 100);
|
||||||
shape.draw()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/// <reference path="./shapes.ts" />
|
|
||||||
|
|
||||||
class Polygon extends Shape
|
|
||||||
{
|
|
||||||
private points: Vector2D[]
|
|
||||||
|
|
||||||
|
|
||||||
constructor(ctx, points) {
|
|
||||||
super(ctx);
|
|
||||||
if (points.length <3)
|
|
||||||
{
|
|
||||||
console.error("cant draw polygon, need min 3 points")
|
|
||||||
}
|
|
||||||
this.points = points
|
|
||||||
}
|
|
||||||
|
|
||||||
public draw()
|
|
||||||
{
|
|
||||||
let last_element = this.points[this.points.length-1]
|
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.moveTo(last_element.x, last_element.y);
|
|
||||||
for (let point of this.points)
|
|
||||||
{
|
|
||||||
this.ctx.lineTo(point.x, point.y);
|
|
||||||
}
|
|
||||||
this.ctx.lineWidth = this.style.strokeWidth;
|
|
||||||
this.ctx.strokeStyle = this.style.strokeColor;
|
|
||||||
this.ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/// <reference path="../vector.ts" />
|
|
||||||
/// <reference path="../shapeStyle.ts" />
|
|
||||||
|
|
||||||
abstract class Shape
|
|
||||||
{
|
|
||||||
protected ctx: CanvasRenderingContext2D
|
|
||||||
protected style: ShapeStyle
|
|
||||||
|
|
||||||
constructor(ctx) {
|
|
||||||
this.ctx = ctx
|
|
||||||
this.style = new ShapeStyle()
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract draw()
|
|
||||||
}
|
|
||||||
|
|
||||||
class Line extends Shape
|
|
||||||
{
|
|
||||||
private from: Vector2D
|
|
||||||
private to: Vector2D
|
|
||||||
|
|
||||||
constructor(ctx,from, to) {
|
|
||||||
super(ctx)
|
|
||||||
this.from = from
|
|
||||||
this.to = to
|
|
||||||
}
|
|
||||||
|
|
||||||
public draw()
|
|
||||||
{
|
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.moveTo(this.from.x, this.from.y);
|
|
||||||
this.ctx.lineTo(this.to.x, this.to.y);
|
|
||||||
|
|
||||||
this.ctx.lineWidth = this.style.strokeWidth;
|
|
||||||
this.ctx.strokeStyle = this.style.strokeColor;
|
|
||||||
this.ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Circle extends Shape
|
|
||||||
{
|
|
||||||
|
|
||||||
private center: Vector2D
|
|
||||||
private radius: number
|
|
||||||
|
|
||||||
constructor(ctx,center, radius) {
|
|
||||||
super(ctx)
|
|
||||||
this.center = center
|
|
||||||
this.radius = radius
|
|
||||||
}
|
|
||||||
|
|
||||||
public draw()
|
|
||||||
{
|
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.arc(this.center.x, this.center.y, this.radius, 0, 2 * Math.PI, false);
|
|
||||||
|
|
||||||
this.ctx.fillStyle = this.style.fillColor;
|
|
||||||
this.ctx.fill();
|
|
||||||
|
|
||||||
this.ctx.lineWidth = this.style.strokeWidth;
|
|
||||||
this.ctx.strokeStyle = this.style.strokeColor;
|
|
||||||
this.ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
/// <reference path="../vector.ts" />
|
|
||||||
|
|
||||||
enum InstructionType
|
|
||||||
{
|
|
||||||
Point,
|
|
||||||
Line,
|
|
||||||
Circle,
|
|
||||||
Length
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Instruction
|
|
||||||
{
|
|
||||||
private type: InstructionType;
|
|
||||||
public params :Parameter[];
|
|
||||||
private argc: number;
|
|
||||||
|
|
||||||
constructor(type: InstructionType, argc: number)
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
this.argc = argc;
|
|
||||||
this.params = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract eval();
|
|
||||||
public getParameterCount(): number { return this.argc; }
|
|
||||||
public getType(): InstructionType { return this.type; }
|
|
||||||
}
|
|
||||||
|
|
||||||
class PointInstruction extends Instruction
|
|
||||||
{
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super(InstructionType.Point, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
return new Vector2D(this.params[0].eval(), this.params[1].eval());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LineInstruction extends Instruction
|
|
||||||
{
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super(InstructionType.Line, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
this.params[0].eval(),
|
|
||||||
this.params[1].eval()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CircleInstruction extends Instruction
|
|
||||||
{
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super(InstructionType.Circle, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
this.params[0].eval(),
|
|
||||||
this.params[1].eval()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LengthInstruction extends Instruction
|
|
||||||
{
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super(InstructionType.Line, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
let line = this.params[0].eval();
|
|
||||||
let dx = line[1].x - line[0].x;
|
|
||||||
let dy = line[1].y - line[0].y;
|
|
||||||
return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
/// <reference path="instruction.ts" />
|
|
||||||
|
|
||||||
abstract class InstructionFactory
|
|
||||||
{
|
|
||||||
private static symbolDict: { [name: string] : Function } = {
|
|
||||||
"point": (): PointInstruction => { return new PointInstruction(); },
|
|
||||||
"line": (): LineInstruction => { return new LineInstruction(); },
|
|
||||||
"circle": (): CircleInstruction => { return new CircleInstruction(); },
|
|
||||||
"len": (): LengthInstruction => { return new LengthInstruction(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static createInstruction(name: string): Instruction
|
|
||||||
{
|
|
||||||
if(!(name in InstructionFactory.symbolDict))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return InstructionFactory.symbolDict[name]();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
enum ParameterType
|
|
||||||
{
|
|
||||||
Instruction,
|
|
||||||
Identifier,
|
|
||||||
Number
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Parameter
|
|
||||||
{
|
|
||||||
public type: ParameterType;
|
|
||||||
|
|
||||||
constructor(type: ParameterType)
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract eval();
|
|
||||||
}
|
|
||||||
|
|
||||||
class NumberParameter extends Parameter
|
|
||||||
{
|
|
||||||
public val: number;
|
|
||||||
|
|
||||||
constructor(val: number)
|
|
||||||
{
|
|
||||||
super(ParameterType.Number);
|
|
||||||
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
return this.val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InstructionParameter extends Parameter
|
|
||||||
{
|
|
||||||
public instr: Instruction;
|
|
||||||
|
|
||||||
constructor(instr: Instruction)
|
|
||||||
{
|
|
||||||
super(ParameterType.Identifier);
|
|
||||||
|
|
||||||
this.instr = instr;
|
|
||||||
}
|
|
||||||
|
|
||||||
eval()
|
|
||||||
{
|
|
||||||
return this.instr.eval();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,166 +0,0 @@
|
||||||
/// <reference path="parameter.ts" />
|
|
||||||
/// <reference path="instructionFactory.ts" />
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Turns a .gs script into a list of instructions to be passed to the renderer
|
|
||||||
*/
|
|
||||||
class Parser
|
|
||||||
{
|
|
||||||
public instructions: Instruction[];
|
|
||||||
private macros: { [id: string] : InstructionParameter};
|
|
||||||
private success: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses each line of the script and turns them into instructions or adds them to the macro list
|
|
||||||
*
|
|
||||||
* @param source The source code of the script
|
|
||||||
*/
|
|
||||||
constructor(source: string)
|
|
||||||
{
|
|
||||||
this.instructions = [];
|
|
||||||
this.macros = {};
|
|
||||||
this.success = false;
|
|
||||||
|
|
||||||
let lines = source.split(/\r?\n/);
|
|
||||||
let currentLine = 1;
|
|
||||||
for(let line of lines)
|
|
||||||
{
|
|
||||||
let instr;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
instr = this.parseInstruction(line);
|
|
||||||
}
|
|
||||||
catch(e)
|
|
||||||
{
|
|
||||||
console.error("Error in line " + currentLine);
|
|
||||||
console.error(e);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the instruction is null it means that the instruction was a function and not a primitive
|
|
||||||
if(instr !== null)
|
|
||||||
if(!instr[0])
|
|
||||||
this.instructions.push(instr[1]);
|
|
||||||
|
|
||||||
currentLine++;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public good() { return this.success; }
|
|
||||||
|
|
||||||
private parseInstruction(instruction: string): [boolean, Instruction]
|
|
||||||
{
|
|
||||||
// If the instruction is an empty line, do nothing for now
|
|
||||||
if(instruction === "")
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Handle [] syntax. Lines in [] will be processed but not rendered
|
|
||||||
let hidden = false;
|
|
||||||
if(instruction[0] === "[" && instruction[instruction.length - 1] === "]")
|
|
||||||
{
|
|
||||||
hidden = true;
|
|
||||||
instruction = instruction.substring(1, instruction.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
instruction = instruction.split(" ").join(""); // Remove spaces
|
|
||||||
|
|
||||||
// match the pattern "text(text)"
|
|
||||||
let matches = instruction.match(/[A-Za-z]*\(.*\)/);
|
|
||||||
if(matches === null) // no match found
|
|
||||||
throw new Error("Line does not contain a valid instruction.");
|
|
||||||
|
|
||||||
if(matches.length > 1) // more than one match
|
|
||||||
throw new Error("Line may only contain one instruction");
|
|
||||||
|
|
||||||
let instr = matches[0]; // get the instruction
|
|
||||||
let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
|
|
||||||
|
|
||||||
|
|
||||||
let symbol = instr.substr(0, paranthesisPos); // get function name
|
|
||||||
let paramlist = instr.substring(paranthesisPos + 1, instr.length - 1); // get parameter list
|
|
||||||
|
|
||||||
// Construct the parameter list
|
|
||||||
let match;
|
|
||||||
let params = [];
|
|
||||||
while((match = paramlist.search(/,(?![^\(]*\))/)) !== -1)
|
|
||||||
{
|
|
||||||
params.push(paramlist.substring(0, match));
|
|
||||||
paramlist = paramlist.substring(match + 1, paramlist.length);
|
|
||||||
}
|
|
||||||
params.push(paramlist);
|
|
||||||
|
|
||||||
// Create appropriate instruction
|
|
||||||
let newInstruction = InstructionFactory.createInstruction(symbol);
|
|
||||||
if(newInstruction === null)
|
|
||||||
throw new Error("Unknown instruction: \"" + symbol + "\"");
|
|
||||||
|
|
||||||
// Check that the number of arguments passed to the function is correct
|
|
||||||
let expectedArgs = newInstruction.getParameterCount();
|
|
||||||
if(expectedArgs !== params.length)
|
|
||||||
throw new Error("Wrong number of arguments for instruction \"" + symbol + "\". Expected " + expectedArgs + " arguments but received " + params.length + " instead.");
|
|
||||||
|
|
||||||
// Parse the individual parameters
|
|
||||||
for(let param of params)
|
|
||||||
{
|
|
||||||
if(!this.parseParameter(newInstruction, param))
|
|
||||||
throw new Error("Error during parameter parsing: \"" + param + "\" failed to be parsed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case there is an assignment, add the instruction to the macro list
|
|
||||||
let assignment = instruction.search(/->/);
|
|
||||||
if(assignment !== -1)
|
|
||||||
{
|
|
||||||
let variableName = instruction.substring(assignment + 2, instruction.length);
|
|
||||||
if(variableName in this.macros)
|
|
||||||
throw new Error("Redefinition of variable \"" + variableName + "\" is not allowed.");
|
|
||||||
|
|
||||||
this.macros[variableName] = new InstructionParameter(newInstruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hidden, newInstruction];
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseParameter(instr: Instruction, parameter: string): boolean
|
|
||||||
{
|
|
||||||
// Parameter is a number
|
|
||||||
let match = parameter.match(/-?\d*\.?\d*$/);
|
|
||||||
if(match !== null && match[0] === parameter && match.index === 0)
|
|
||||||
{
|
|
||||||
let val = parseFloat(parameter);
|
|
||||||
let paramObj = new NumberParameter(val);
|
|
||||||
|
|
||||||
instr.params.push(paramObj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parameter is an identifier (macro)
|
|
||||||
match = parameter.match(/[A-Za-z]*/)
|
|
||||||
if(match !== null && match[0] === parameter && match.index === 0)
|
|
||||||
{
|
|
||||||
let paramObj = this.macros[parameter];
|
|
||||||
if(paramObj === undefined)
|
|
||||||
{
|
|
||||||
console.error("Variable \"" + parameter + "\" is not defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
instr.params.push(paramObj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parameter is another instruction
|
|
||||||
match = parameter.match(/[A-Za-z]*\(.*\)/)
|
|
||||||
if(match !== null && match[0] === parameter && match.index === 0)
|
|
||||||
{
|
|
||||||
let paramObj = new InstructionParameter(this.parseInstruction(parameter)[1]);
|
|
||||||
|
|
||||||
instr.params.push(paramObj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
class ShapeStyle
|
|
||||||
|
export class ShapeStyle
|
||||||
{
|
{
|
||||||
public strokeWidth: number;
|
public strokeWidth: number;
|
||||||
public strokeColor: string;
|
public strokeColor: string;
|
||||||
|
|
26
src/shapes.ts
Normal file
26
src/shapes.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Vector2D } from "./vector.js"
|
||||||
|
import { ShapeStyle } from "./shapeStyle.js";
|
||||||
|
|
||||||
|
export function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2D, style: ShapeStyle = new ShapeStyle())
|
||||||
|
{
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(from.x, from.y);
|
||||||
|
ctx.lineTo(to.x, to.y);
|
||||||
|
|
||||||
|
ctx.lineWidth = style.strokeWidth;
|
||||||
|
ctx.strokeStyle = style.strokeColor;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function circle(ctx: CanvasRenderingContext2D, center: Vector2D, radius: number, style: ShapeStyle = new ShapeStyle())
|
||||||
|
{
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI, false);
|
||||||
|
|
||||||
|
ctx.fillStyle = style.fillColor;
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
ctx.lineWidth = style.strokeWidth;
|
||||||
|
ctx.strokeStyle = style.strokeColor;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
class Vector2D
|
export class Vector2D
|
||||||
{
|
{
|
||||||
public x: number;
|
public x: number;
|
||||||
public y: number;
|
public y: number;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outFile": "./out/geometry.js",
|
// "outFile": "./out/lauchpioos.js",
|
||||||
|
"outDir": "./out",
|
||||||
"sourceRoot": "./src",
|
"sourceRoot": "./src",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"sourceMap": true
|
"sourceMap": true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue