aboutsummaryrefslogtreecommitdiff
path: root/js/lib/geom/sub-path.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib/geom/sub-path.js')
-rwxr-xr-xjs/lib/geom/sub-path.js853
1 files changed, 308 insertions, 545 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index 7046673e..56c94df3 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -11,29 +11,6 @@ var GeomObj = require("js/lib/geom/geom-obj").GeomObj;
11var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; 11var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint;
12var MaterialsModel = require("js/models/materials-model").MaterialsModel; 12var MaterialsModel = require("js/models/materials-model").MaterialsModel;
13 13
14// TODO Those function do not seems to be used. We should remove them
15function SubpathOffsetPoint(pos, mapPos) {
16 this.Pos = [pos[0],pos[1],pos[2]];
17 this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]];
18}
19
20function SubpathOffsetTriangle(v0, v1, v2) {
21 this.v0 = v0;
22 this.v1 = v1;
23 this.v2 = v2;
24 this.n = [0,0,1]; //replace with the actual cross product later
25}
26
27function sortNumberAscending(a,b){
28 return a-b;
29}
30function sortNumberDescending(a,b){
31 return b-a;
32}
33function SegmentIntersections(){
34 this.paramArray = [];
35}
36
37/////////////////////////////////////////////////////////////////////// 14///////////////////////////////////////////////////////////////////////
38// Class GLSubpath 15// Class GLSubpath
39// representation a sequence of cubic bezier curves. 16// representation a sequence of cubic bezier curves.
@@ -44,49 +21,42 @@ var GLSubpath = function GLSubpath() {
44 /////////////////////////////////////////////////// 21 ///////////////////////////////////////////////////
45 // Instance variables 22 // Instance variables
46 /////////////////////////////////////////////////// 23 ///////////////////////////////////////////////////
24
25 // NOTE:
26 // This class contains functionality to store piecewise cubic bezier paths.
27 // The coordinates of the paths are always in local, canvas space.
28 // That is, the Z coordinate can be ignored (for now), and the paths are essentially in 2D.
29 // All coordinates of the '_Samples' should lie within [0,0] and [width, height],
30 // where width and height refer to the dimensions of the canvas for this path.
31 // Whenever the the canvas dimensions change, the coordinates of the anchor points
32 // and _Samples must be re-computed.
33
47 this._Anchors = []; 34 this._Anchors = [];
48 this._BBoxMin = [0, 0, 0]; 35 this._BBoxMin = [0, 0, 0];
49 this._BBoxMax = [0, 0, 0]; 36 this._BBoxMax = [0, 0, 0];
37 this._canvasCenterLocalCoord = [0,0,0];
38
50 this._isClosed = false; 39 this._isClosed = false;
51 40
52 this._samples = []; //polyline representation of this curve 41 this._Samples = []; //polyline representation of this curve in canvas space
53 this._sampleParam = []; //parametric distance of samples, within [0, N], where N is # of Bezier curves (=# of anchor points if closed, =#anchor pts -1 if open) 42 this._sampleParam = []; //parametric distance of samples, within [0, N], where N is # of Bezier curves (=# of anchor points if closed, =#anchor pts -1 if open)
54 this._anchorSampleIndex = []; //index within _samples corresponding to anchor points 43 this._anchorSampleIndex = []; //index within _Samples corresponding to anchor points
55
56 this._UnprojectedAnchors = [];
57 44
58 //initially set the _dirty bit so we will construct samples 45 //initially set the _dirty bit so we will re-construct _Anchors and _Samples
59 this._dirty = true; 46 this._dirty = true;
60 47
61 //whether or not to use the canvas drawing to stroke/fill
62 this._useCanvasDrawing = true;
63
64 //the canvas that will draw this subpath
65 this._canvas = null;
66
67 //the X and Y location of this subpath's canvas in stage world space of Ninja
68 this._canvasX = 0;
69 this._canvasY = 0;
70
71 //stroke information 48 //stroke information
72 this._strokeWidth = 0.0; 49 this._strokeWidth = 1.0;
73 this._strokeColor = [0.4, 0.4, 0.4, 1.0]; 50 this._strokeColor = [0.4, 0.4, 0.4, 1.0];
74 this._strokeMaterial = null
75 this._strokeStyle = "Solid";
76 this._materialAmbient = [0.2, 0.2, 0.2, 1.0];
77 this._materialDiffuse = [0.4, 0.4, 0.4, 1.0];
78 this._materialSpecular = [0.4, 0.4, 0.4, 1.0];
79 this._fillColor = [1.0, 1.0, 1.0, 0.0]; 51 this._fillColor = [1.0, 1.0, 1.0, 0.0];
80 this._fillMaterial = null;
81 this._DISPLAY_ANCHOR_RADIUS = 5; 52 this._DISPLAY_ANCHOR_RADIUS = 5;
53
82 //drawing context 54 //drawing context
83 this._world = null; 55 this._world = null;
56 this._canvas = null; //todo this might be unnecessary (but faster) since we can get it from the world
84 57
85 //tool that owns this subpath 58 //tool that owns this subpath
86 this._drawingTool = null; 59 this._drawingTool = null;
87 this._planeMat = null;
88 this._planeMatInv = null;
89 this._planeCenter = null;
90 60
91 //used to query what the user selected, OR-able for future extensions 61 //used to query what the user selected, OR-able for future extensions
92 this.SEL_NONE = 0; //nothing was selected 62 this.SEL_NONE = 0; //nothing was selected
@@ -98,8 +68,6 @@ var GLSubpath = function GLSubpath() {
98 this._selectedAnchorIndex = -1; 68 this._selectedAnchorIndex = -1;
99 69
100 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve 70 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve
101 this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified
102 this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path
103 71
104 // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) 72 // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype)
105 //buildBuffers 73 //buildBuffers
@@ -115,36 +83,39 @@ var GLSubpath = function GLSubpath() {
115 // get the world 83 // get the world
116 var world = this.getWorld(); 84 var world = this.getWorld();
117 if (!world) throw( "null world in subpath render" ); 85 if (!world) throw( "null world in subpath render" );
118 86 if (!this._canvas){
119 // get the context 87 //set the canvas by querying the world
88 this._canvas = this.getWorld().getCanvas();
89 }
90 // get the context
120 var ctx = world.get2DContext(); 91 var ctx = world.get2DContext();
121 if (!ctx) throw ("null context in subpath render") 92 if (!ctx) throw ("null context in subpath render");
122 93
123 var numAnchors = this.getNumAnchors(); 94 var numAnchors = this.getNumAnchors();
124 if (numAnchors === 0) { 95 if (numAnchors === 0) {
125 return; //nothing to do for empty paths 96 return; //nothing to do for empty paths
126 } 97 }
98 this.createSamples(false); //dirty bit checked in this function...will generate a polyline representation
127 99
128 ctx.save(); 100 var numPoints = this._Samples.length;
129 101 if (numPoints === 0){
130 this.createSamples(); //dirty bit checked in this function...will generate a polyline representation 102 return; //nothing to do for empty paths
131 var bboxMin = this.getBBoxMin();
132 var bboxMax = this.getBBoxMax();
133 var bboxWidth = bboxMax[0] - bboxMin[0];
134 var bboxHeight = bboxMax[1] - bboxMin[1];
135 var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])];
136
137 if (this._canvas) {
138 CanvasController.setProperty(this._canvas, "width", bboxWidth+"px");
139 CanvasController.setProperty(this._canvas, "height", bboxHeight+"px");
140 this._canvas.elementModel.shapeModel.GLWorld.setViewportFromCanvas(this._canvas);
141 } 103 }
104
105 //figure the size of the area we will draw into
106 var bboxWidth=0, bboxHeight=0;
107 bboxWidth = this._BBoxMax[0] - this._BBoxMin[0];
108 bboxHeight = this._BBoxMax[1] - this._BBoxMin[1];
109
110 ctx.save();
142 ctx.clearRect(0, 0, bboxWidth, bboxHeight); 111 ctx.clearRect(0, 0, bboxWidth, bboxHeight);
143 112
144 ctx.lineWidth = this._strokeWidth; 113 ctx.lineWidth = this._strokeWidth;
145 ctx.strokeStyle = "black"; 114 ctx.strokeStyle = "black";
146 if (this._strokeColor) { 115 if (this._strokeColor) {
147 ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); 116 //ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor );
117 var strokeColorStr = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+this._strokeColor[3]+")";
118 ctx.strokeStyle = strokeColorStr;
148 } 119 }
149 120
150 ctx.fillStyle = "white"; 121 ctx.fillStyle = "white";
@@ -152,14 +123,15 @@ var GLSubpath = function GLSubpath() {
152 //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); 123 //ctx.fillStyle = MathUtils.colorToHex( this._fillColor );
153 var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; 124 var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")";
154 ctx.fillStyle = fillColorStr; 125 ctx.fillStyle = fillColorStr;
155 console.log("Fill color:" + fillColorStr);
156 } 126 }
157 var lineCap = ['butt','round','square']; 127 var lineCap = ['butt','round','square'];
158 ctx.lineCap = lineCap[1]; 128 ctx.lineCap = lineCap[1];
159 ctx.beginPath(); 129 var lineJoin = ['round','bevel','miter'];
130 ctx.lineJoin = lineJoin[0];
160 131
161 /* 132 /*
162 commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered 133 commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered
134 ctx.beginPath();
163 var prevAnchor = this.getAnchor(0); 135 var prevAnchor = this.getAnchor(0);
164 ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]); 136 ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]);
165 for (var i = 1; i < numAnchors; i++) { 137 for (var i = 1; i < numAnchors; i++) {
@@ -176,13 +148,13 @@ var GLSubpath = function GLSubpath() {
176 */ 148 */
177 149
178 150
179 var numPoints = this._samples.length/3; 151 ctx.beginPath();
180 ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); 152 ctx.moveTo(this._Samples[0][0],this._Samples[0][1]);
181 for (var i=0;i<numPoints;i++){ 153 for (var i=0;i<numPoints;i++){
182 ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]); 154 ctx.lineTo(this._Samples[i][0],this._Samples[i][1]);
183 } 155 }
184 if (this._isClosed === true) { 156 if (this._isClosed === true) {
185 ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); 157 ctx.lineTo(this._Samples[0][0],this._Samples[0][1]);
186 } 158 }
187 ctx.fill(); 159 ctx.fill();
188 ctx.stroke(); 160 ctx.stroke();
@@ -265,18 +237,21 @@ GLSubpath.prototype = new GeomObj();
265///////////////////////////////////////////////////////// 237/////////////////////////////////////////////////////////
266// Property Accessors/Setters 238// Property Accessors/Setters
267///////////////////////////////////////////////////////// 239/////////////////////////////////////////////////////////
268GLSubpath.prototype.setCanvas = function (c) {
269 this._canvas = c;