Parsing thermals works.
Parsing thermals works.

--- a/src/data/pcb/ThermalTest.pcb
+++ b/src/data/pcb/ThermalTest.pcb
@@ -6,7 +6,7 @@
 PCB["" 50000 50000]
 
 Grid[1000.0 0 0 0]
-Cursor[0 0 0.000000]
+Cursor[4000 43000 0.000000]
 PolyArea[3100.006200]
 Thermal[0.500000]
 DRC[1000 1000 1000 1000 1500 1000]
@@ -792,7 +792,7 @@
 Via[25000 14000 3600 2000 0 2000 "" "thermal(0S)"]
 Via[32000 14000 3600 2000 0 2000 "" "thermal(0X)"]
 Via[39000 14000 3600 2000 0 2000 "" "thermal(0t)"]
-Via[11000 36000 3600 2000 0 2000 "" "thermal(0+,5)"]
+Via[11000 36000 3600 2000 0 2000 "" "thermal(0-2,5)"]
 Via[18000 36000 3600 2000 0 2000 "" "thermal(0X,5+)"]
 Via[25000 36000 3600 2000 0 2000 "" "thermal(5S)"]
 Via[32000 36000 3600 2000 0 2000 "" "thermal(0+,5X)"]
@@ -811,9 +811,17 @@
 )
 Layer(2 "ground")
 (
+	Polygon("clearpoly")
+	(
+		[3000 44000] [15000 44000] [15000 29000] [3000 29000] 
+	)
 )
 Layer(3 "signal2")
 (
+	Polygon("clearpoly")
+	(
+		[7000 40000] [15000 40000] [15000 29000] [7000 29000] 
+	)
 )
 Layer(4 "signal3")
 (

--- a/src/js/circuit/PCB/Layer.js
+++ b/src/js/circuit/PCB/Layer.js
@@ -48,7 +48,7 @@
 						elements.parts[i].clear(ctx);
 				if(pins)
 					for(i = 0; i < pins.parts.length; i++)
-						pins.parts[i].clear(ctx);
+						pins.parts[i].clear(ctx, this.number);
 				ctx.globalCompositeOperation = "source-over";
 			}
 

--- a/src/js/circuit/PCB/Pin.js
+++ b/src/js/circuit/PCB/Pin.js
@@ -1,137 +1,142 @@
-define(function() {
-
-	// Pin [x y thickness clearance mask drillholedia name number flags]
-	var Pin = function(x, y, thick, clearance, mask, drill, name, num, flags) {
-
-		this.x = x;
-		this.y = y;
-		this.thick = thick;
-		this.clearance = clearance;
-		this.mask = mask;
-		this.drill = drill;
-		this.name = name;
-		this.num = num;
-		this.flags = {
+define(
+	[
+	 	"./parseFlags"
+	],
+	function(
+		parseFlags
+	){
+	
+		// Pin [x y thickness clearance mask drillholedia name number flags]
+		var Pin = function(x, y, thick, clearance, mask, drill, name, num, flags) {
+	
+			this.x = x;
+			this.y = y;
+			this.thick = thick;
+			this.clearance = clearance;
+			this.mask = mask;
+			this.drill = drill;
+			this.name = name;
+			this.num = num;
+			this.flags = parseFlags(Pin._defaultFlags, flags);
+	
+		};
+	
+		Pin._defaultFlags = {
 			square: false
 		};
-
-		var i, split = flags.split(',');
-		for(i = 0; i < split.length; i++)
-			this.flags[split[i]] = true;
-
-	};
-
-	Pin.prototype._createCache = function(){
-
-		this._cache = {};
-
-		this._cache.x = this.x;
-		this._cache.y = this.y;
-		if(this.parent){
-			this._cache.x += this.parent.mx;
-			this._cache.y += this.parent.my;
+	
+		Pin.prototype._createCache = function(){
+	
+			this._cache = {};
+	
+			this._cache.x = this.x;
+			this._cache.y = this.y;
+			if(this.parent){
+				this._cache.x += this.parent.mx;
+				this._cache.y += this.parent.my;
+			}
+			this._cache.rx = this._cache.x - (this.thick / 2);
+			this._cache.ry = this._cache.y - (this.thick / 2);
+	
 		}
-		this._cache.rx = this._cache.x - (this.thick / 2);
-		this._cache.ry = this._cache.y - (this.thick / 2);
+	
+		Pin.prototype.render = function(ctx, color) {
+	
+			if(!this._cache) this._createCache();
+	
+			if(color == '#FFFFFF')
+				return;
+	
+			ctx.beginPath();
+			if(this.flags.square)
+				ctx.rect(this._cache.rx, this._cache.ry, this.thick, this.thick);
+			else
+				ctx.arc(this._cache.x, this._cache.y, this.thick / 2, 0, Math.PI * 2, true);
+	
+			ctx.closePath();
+			ctx.fillStyle = '#4D4D4D'; // TODO: global color
+			ctx.fill();
+	
+			ctx.beginPath();
+			ctx.arc(this._cache.x, this._cache.y, this.drill / 2, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
+			ctx.fill();
+	
+		};
+	
+		Pin.prototype.clear = function(ctx){
+	
+			if(!this._cache) this._createCache();
+	
+			ctx.beginPath();
+			ctx.arc(this._cache.x, this._cache.y, (this.clearance + this.thick) / 2.0, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fill();
+	
+		};
+	
+		Pin.prototype.renderGL = function(gl, shaderProgram){
+			
+			gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.35, 0.35, 0.35, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.thick * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+			gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.drill * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		}
+	
+		Pin.prototype.clearGL = function(gl, shaderProgram){
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, (this.thick + this.clearance) * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		};
+	
+		Pin.prototype.cleanupGL = function(gl){
+	
+			if(this.pointBuffer){
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+				gl.deleteBuffer(this.pointBuffer);
+				this.pointBuffer = null;
+			}
+	
+		}
+	
+		Pin.prototype.setup3DArrayBuffer = function(gl, x, y){
+	
+			var vBuffer;
+			vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x + this.parent.mx,this.y + this.parent.my,0.0]), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = 1;
+			this.pointBuffer = vBuffer;
+	
+		}
+	
+		return Pin;
 
 	}
-
-	Pin.prototype.render = function(ctx, color) {
-
-		if(!this._cache) this._createCache();
-
-		if(color == '#FFFFFF')
-			return;
-
-		ctx.beginPath();
-		if(this.flags.square)
-			ctx.rect(this._cache.rx, this._cache.ry, this.thick, this.thick);
-		else
-			ctx.arc(this._cache.x, this._cache.y, this.thick / 2, 0, Math.PI * 2, true);
-
-		ctx.closePath();
-		ctx.fillStyle = '#4D4D4D'; // TODO: global color
-		ctx.fill();
-
-		ctx.beginPath();
-		ctx.arc(this._cache.x, this._cache.y, this.drill / 2, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
-		ctx.fill();
-
-	};
-
-	Pin.prototype.clear = function(ctx){
-
-		if(!this._cache) this._createCache();
-
-		ctx.beginPath();
-		ctx.arc(this._cache.x, this._cache.y, (this.clearance + this.thick) / 2.0, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fill();
-
-	};
-
-	Pin.prototype.renderGL = function(gl, shaderProgram){
-		
-		gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
-
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-
-		gl.uniform4f(shaderProgram.vColorUniform, 0.35, 0.35, 0.35, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.thick * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, true);
-		gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.drill * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
-
-	}
-
-	Pin.prototype.clearGL = function(gl, shaderProgram){
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
-
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, (this.thick + this.clearance) * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
-
-	};
-
-	Pin.prototype.cleanupGL = function(gl){
-
-		if(this.pointBuffer){
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-			gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
-			gl.deleteBuffer(this.pointBuffer);
-			this.pointBuffer = null;
-		}
-
-	}
-
-	Pin.prototype.setup3DArrayBuffer = function(gl, x, y){
-
-		var vBuffer;
-		vBuffer = gl.createBuffer();
-		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
-		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x + this.parent.mx,this.y + this.parent.my,0.0]), gl.STATIC_DRAW);
-		vBuffer.itemSize = 3;
-		vBuffer.numItems = 1;
-		this.pointBuffer = vBuffer;
-
-	}
-
-	return Pin;
-
-});
+);

--- a/src/js/circuit/PCB/Via.js
+++ b/src/js/circuit/PCB/Via.js
@@ -1,100 +1,123 @@
-define(function() {
-	var Via = function(x, y, od, clearance, u2, id, u3, u4) {
+define(
+	[
+	 	"./parseFlags"
+	],
+	function(
+		parseFlags
+	){
 
-		this.x = x;
-		this.y = y;
-		this.od = od;
-		this.id = id;
-		this.clearance = clearance;
+		var Via = function(x, y, od, clearance, u2, id, u3, flags) {
 
-	};
+			this.x = x;
+			this.y = y;
+			this.od = od;
+			this.id = id;
+			this.clearance = clearance;
+			this.flags = parseFlags(Via._defaultFlags, flags);
 
-	Via.prototype.render = function(ctx) {
+		};
 
-		ctx.beginPath();
-		ctx.arc(this.x, this.y, this.od / 2, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fillStyle = '#7F7F7F'; // TODO: set colors to global option
-		ctx.fill();
+		Via._defaultFlags = {
+		};
 
-		ctx.beginPath();
-		ctx.arc(this.x, this.y, this.id / 2, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
-		ctx.fill();
+		Via.prototype.render = function(ctx) {
+	
+			ctx.beginPath();
+			ctx.arc(this.x, this.y, this.od / 2, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fillStyle = '#7F7F7F'; // TODO: set colors to global option
+			ctx.fill();
+	
+			ctx.beginPath();
+			ctx.arc(this.x, this.y, this.id / 2, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
+			ctx.fill();
+	
+		};
+	
+		Via.prototype.clear = function(ctx, layerNumber){
 
-	};
+			var thrm, i;
 
-	Via.prototype.clear = function(ctx){
+			thrm = this.flags.thermal;
 
-		ctx.beginPath();
-		ctx.arc(this.x, this.y, (this.clearance + this.od) / 2.0, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fill();
+			if(thrm){
+				for(i = 0; i < thrm.length; i++){
+					if(layerNumber - 1 == thrm[i].number)
+						console.log("thrm");
+				}
+			}
 
-	};
-
-	Via.prototype.renderGL = function(gl, shaderProgram){
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, true);
-
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-
-		gl.uniform4f(shaderProgram.vColorUniform, 0.59, 0.59, 0.59, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.od*gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.id*gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
+			ctx.beginPath();
+			ctx.arc(this.x, this.y, (this.clearance + this.od) / 2.0, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fill();
+	
+		};
+	
+		Via.prototype.renderGL = function(gl, shaderProgram){
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.59, 0.59, 0.59, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.od*gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.id*gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		}
+	
+		Via.prototype.clearGL = function(gl, shaderProgram){
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+			gl.uniform1f(shaderProgram.pointsizeUniform, (this.od + this.clearance) * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		};
+	
+		Via.prototype.cleanupGL = function(gl){
+	
+			if(this.pointBuffer){
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+				gl.deleteBuffer(this.pointBuffer);
+				this.pointBuffer = null;
+			}
+	
+		}
+	
+		Via.prototype.setup3DArrayBuffer = function(gl){
+	
+			var vBuffer;
+			vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x,this.y,0.0]), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = 1;
+			this.pointBuffer = vBuffer;
+	
+		}
+	
+		return Via;
 
 	}
-
-	Via.prototype.clearGL = function(gl, shaderProgram){
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, true);
-
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-
-		gl.uniform1f(shaderProgram.pointsizeUniform, (this.od + this.clearance) * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
-
-	};
-
-	Via.prototype.cleanupGL = function(gl){
-
-		if(this.pointBuffer){
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-			gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
-			gl.deleteBuffer(this.pointBuffer);
-			this.pointBuffer = null;
-		}
-
-	}
-
-	Via.prototype.setup3DArrayBuffer = function(gl){
-
-		var vBuffer;
-		vBuffer = gl.createBuffer();
-		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
-		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x,this.y,0.0]), gl.STATIC_DRAW);
-		vBuffer.itemSize = 3;
-		vBuffer.numItems = 1;
-		this.pointBuffer = vBuffer;
-
-	}
-
-	return Via;
-
-});
+);

--- /dev/null
+++ b/src/js/circuit/PCB/parseFlags.js
@@ -1,1 +1,65 @@
+define(function(){
 
+	var parseFlags = function(defaultFlags, flags){
+
+		if(!flags) return {};
+
+		var parsedFlags, split, parts, flag, attr, thrm, i, j, k;
+
+		split = flags.split("\(.*?\)|(,)");
+
+		parsedFlags = {};
+
+		for(attr in defaultFlags)
+            if(obj.hasOwnProperty(attr))
+            	parsedFlags[attr] = obj[attr];
+
+		for(i = 0; i < split.length; i++){
+
+			flag = split[i];
+
+			if(flag.indexOf("thermal") == 0){
+
+				thrm = [];
+
+				flag = flag.split('(')[1].split(')')[0].split(',');
+				for(j = 0; j < flag.length; j++){
+					// check for #-#
+					// for each add layer
+					//else layer #
+					parts = flag[j].split('-');
+					if(parts.length == 2){
+						parts = flag[j][flag[j].length-1];
+						if(isNaN(parseInt(parts))){
+							parts = flag[j].substring(0, flag[j].length - 1).split('-');
+							attr = parts;
+						} else {
+							parts = flag[j].split('-');
+							attr = 'O';
+						}
+						
+						for(k = parseInt(parts[0]); k <= parseInt(parts[1]); k++){
+							thrm.push({number: k, type: attr});
+						}
+					} else {
+						parts = flag[j][flag[j].length-1];
+						if(isNaN(parseInt(parts)))
+							thrm.push({number: parseInt(flag[j].substring(0, flag[j].length - 1)), type: parts});
+						else
+							thrm.push({number: parseInt(flag[j].substring(0, flag[j].length)), type: 'O'});
+					}
+				}
+				parsedFlags.thermal = thrm;
+			}
+			else
+				parsedFlags[flag] = true;
+
+		}
+
+		return parsedFlags;
+
+	};
+
+	return parseFlags;
+
+});