aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xjs/lib/geom/sub-path.js940
-rwxr-xr-xjs/tools/PenTool.js849
2 files changed, 542 insertions, 1247 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index 765316b1..761391b7 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -11,30 +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
15/*
16function SubpathOffsetPoint(pos, mapPos) {
17 this.Pos = [pos[0],pos[1],pos[2]];
18 this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]];
19}
20
21function SubpathOffsetTriangle(v0, v1, v2) {
22 this.v0 = v0;
23 this.v1 = v1;
24 this.v2 = v2;
25 this.n = [0,0,1]; //replace with the actual cross product later
26}
27
28function sortNumberAscending(a,b){
29 return a-b;
30}
31function sortNumberDescending(a,b){
32 return b-a;
33}
34function SegmentIntersections(){
35 this.paramArray = [];
36}
37*/
38/////////////////////////////////////////////////////////////////////// 14///////////////////////////////////////////////////////////////////////
39// Class GLSubpath 15// Class GLSubpath
40// representation a sequence of cubic bezier curves. 16// representation a sequence of cubic bezier curves.
@@ -45,60 +21,44 @@ var GLSubpath = function GLSubpath() {
45 /////////////////////////////////////////////////// 21 ///////////////////////////////////////////////////
46 // Instance variables 22 // Instance variables
47 /////////////////////////////////////////////////// 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
48 this._Anchors = []; 34 this._Anchors = [];
49 this._BBoxMin = [0, 0, 0]; 35 this._BBoxMin = [0, 0, 0];
50 this._BBoxMax = [0, 0, 0]; 36 this._BBoxMax = [0, 0, 0];
51 this._isClosed = false; 37 this._isClosed = false;
52 38
53 this._samples = []; //polyline representation of this curve in stage world space 39 this._Samples = []; //polyline representation of this curve in canvas space
54 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) 40 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)
55 this._anchorSampleIndex = []; //index within _samples corresponding to anchor points 41 this._anchorSampleIndex = []; //index within _Samples corresponding to anchor points
56 42
57 this._LocalPoints = []; //polyline representation of this curve in canvas space 43 //initially set the _dirty bit so we will re-construct _Anchors and _Samples
58 this._LocalBBoxMin = [0,0,0]; //bbox min point of _LocalPoints
59 this._LocalBBoxMax = [0,0,0]; //bbox max point of _LocalPoints
60 this._AnchorLocalCoords = []; //local coords for all the anchor points , stored as a triplet of 3D vectors (prev, curr, next, in order)
61 this._UnprojectedAnchors = [];
62
63 //initially set the _dirty bit so we will construct samples
64 this._dirty = true; 44 this._dirty = true;
65 45
66 //initially set the local dirty bit so we will construct local coordinates 46 //the top left location of this subpath's canvas in screen space (used to identify cases when location changes)
67 this._isLocalDirty = true;
68
69 //initially set the local dirty bit for the anchors so we will construct local coordinates
70 this._isAnchorLocalDirty = true;
71
72 //whether or not to use the canvas drawing to stroke/fill
73 this._useCanvasDrawing = true;
74
75 //the canvas that will draw this subpath
76 this._canvas = null;
77
78 //the top left location of this subpath's canvas in screen space
79 this._canvasLeft = 0; 47 this._canvasLeft = 0;
80 this._canvasTop = 0; 48 this._canvasTop = 0;
81 49
82 //stroke information 50 //stroke information
83 this._strokeWidth = 1.0; 51 this._strokeWidth = 1.0;
84 this._strokeColor = [0.4, 0.4, 0.4, 1.0]; 52 this._strokeColor = [0.4, 0.4, 0.4, 1.0];
85 this._strokeMaterial = null
86 this._strokeStyle = "Solid";
87 this._materialAmbient = [0.2, 0.2, 0.2, 1.0];
88 this._materialDiffuse = [0.4, 0.4, 0.4, 1.0];
89 this._materialSpecular = [0.4, 0.4, 0.4, 1.0];
90 this._fillColor = [1.0, 1.0, 1.0, 0.0]; 53 this._fillColor = [1.0, 1.0, 1.0, 0.0];
91 this._fillMaterial = null;
92 this._DISPLAY_ANCHOR_RADIUS = 5; 54 this._DISPLAY_ANCHOR_RADIUS = 5;
55
93 //drawing context 56 //drawing context
94 this._world = null; 57 this._world = null;
58 this._canvas = null; //todo this might be unnecessary (but faster) since we can get it from the world
95 59
96 //tool that owns this subpath 60 //tool that owns this subpath
97 this._drawingTool = null; 61 this._drawingTool = null;
98 this._planeMat = Matrix.I(4);
99 this._planeMatInv = Matrix.I(4);
100 this._planeCenter = null;
101 this._dragPlane = null;
102 62
103 //used to query what the user selected, OR-able for future extensions 63 //used to query what the user selected, OR-able for future extensions
104 this.SEL_NONE = 0; //nothing was selected 64 this.SEL_NONE = 0; //nothing was selected
@@ -110,8 +70,6 @@ var GLSubpath = function GLSubpath() {
110 this._selectedAnchorIndex = -1; 70 this._selectedAnchorIndex = -1;
111 71
112 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve 72 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve
113 this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified
114 this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path
115 73
116 // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) 74 // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype)
117 //buildBuffers 75 //buildBuffers
@@ -121,13 +79,6 @@ var GLSubpath = function GLSubpath() {
121 // return; //no need to do anything for now 79 // return; //no need to do anything for now
122 }; 80 };
123 81
124 this._offsetLocalCoord = function(deltaW, deltaH){
125 var numPoints = this._LocalPoints.length;
126 for (var i=0;i<numPoints;i++) {
127 this._LocalPoints[i][0]+= deltaW;
128 this._LocalPoints[i][1]+= deltaH;
129 }
130 };
131 //render 82 //render
132 // specify how to render the subpath in Canvas2D 83 // specify how to render the subpath in Canvas2D
133 this.render = function () { 84 this.render = function () {
@@ -146,24 +97,12 @@ var GLSubpath = function GLSubpath() {
146 if (numAnchors === 0) { 97 if (numAnchors === 0) {
147 return; //nothing to do for empty paths 98 return; //nothing to do for empty paths
148 } 99 }
149 var useLocalCoord = true;
150 this.createSamples(); //dirty bit checked in this function...will generate a polyline representation 100 this.createSamples(); //dirty bit checked in this function...will generate a polyline representation
151 101
152 //build the coordinates of the samples in 2D (canvas) space (localDirty bit checked in buildLocalCoord
153 this.buildLocalCoord();
154
155 //figure the size of the area we will draw into 102 //figure the size of the area we will draw into
156 var bboxWidth=0, bboxHeight=0; 103 var bboxWidth=0, bboxHeight=0;
157 if (useLocalCoord){ 104 bboxWidth = this._BBoxMax[0] - this._BBoxMin[0];
158 bboxWidth = this._LocalBBoxMax[0] - this._LocalBBoxMin[0]; 105 bboxHeight = this._BBoxMax[1] - this._BBoxMin[1];
159 bboxHeight = this._LocalBBoxMax[1] - this._LocalBBoxMin[1];
160 }
161 else {
162 var bboxMin = this.getBBoxMin();
163 var bboxMax = this.getBBoxMax();
164 bboxWidth = bboxMax[0] - bboxMin[0];
165 bboxHeight = bboxMax[1] - bboxMin[1];
166 }
167 106
168 ctx.save(); 107 ctx.save();
169 ctx.clearRect(0, 0, bboxWidth, bboxHeight); 108 ctx.clearRect(0, 0, bboxWidth, bboxHeight);
@@ -204,33 +143,17 @@ var GLSubpath = function GLSubpath() {
204 */ 143 */
205 144
206 145
207 var numPoints=0, i=0;
208 ctx.beginPath(); 146 ctx.beginPath();
209 if (!useLocalCoord){ 147 var numPoints = this._Samples.length;
210 numPoints = this._samples.length/3; 148 ctx.moveTo(this._Samples[0][0],this._Samples[0][1]);
211 ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); 149 for (var i=0;i<numPoints;i++){
212 for (i=0;i<numPoints;i++){ 150 ctx.lineTo(this._Samples[i][0],this._Samples[i][1]);
213 ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]);
214 }
215 if (this._isClosed === true) {
216 ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]);
217 }
218 ctx.fill();
219 ctx.stroke();
220 } 151 }
221 else { 152 if (this._isClosed === true) {
222 //render using the local coords 153 ctx.lineTo(this._Samples[0][0],this._Samples[0][1]);
223 numPoints = this._LocalPoints.length;
224 ctx.moveTo(this._LocalPoints[0][0],this._LocalPoints[0][1]);
225 for (i=0;i<numPoints;i++){
226 ctx.lineTo(this._LocalPoints[i][0],this._LocalPoints[i][1]);
227 }
228 if (this._isClosed === true) {
229 ctx.lineTo(this._LocalPoints[0][0],this._LocalPoints[0][1]);
230 }
231 ctx.fill();
232 ctx.stroke();
233 } 154 }
155 ctx.fill();
156 ctx.stroke();
234 ctx.restore(); 157 ctx.restore();
235 }; //render() 158 }; //render()
236 159
@@ -310,21 +233,21 @@ GLSubpath.prototype = new GeomObj();
310///////////////////////////////////////////////////////// 233/////////////////////////////////////////////////////////
311// Property Accessors/Setters 234// Property Accessors/Setters
312///////////////////////////////////////////////////////// 235/////////////////////////////////////////////////////////
313GLSubpath.prototype.setCanvas = function (c) {
314 this._canvas = c;
315};
316GLSubpath.prototype.getCanvas = function() {
317 return this._canvas;
318};
319
320GLSubpath.prototype.setWorld = function (world) { 236GLSubpath.prototype.setWorld = function (world) {
321 this._world = world; 237 this._world = world;
322}; 238};
323