diff options
Diffstat (limited to 'js/lib/geom/sub-path.js')
-rwxr-xr-x | js/lib/geom/sub-path.js | 853 |
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; | |||
11 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; | 11 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; |
12 | var MaterialsModel = require("js/models/materials-model").MaterialsModel; | 12 | var MaterialsModel = require("js/models/materials-model").MaterialsModel; |
13 | 13 | ||
14 | // TODO Those function do not seems to be used. We should remove them | ||
15 | function SubpathOffsetPoint(pos, mapPos) { | ||
16 | this.Pos = [pos[0],pos[1],pos[2]]; | ||
17 | this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]]; | ||
18 | } | ||
19 | |||
20 | function 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 | |||
27 | function sortNumberAscending(a,b){ | ||
28 | return a-b; | ||
29 | } | ||
30 | function sortNumberDescending(a,b){ | ||
31 | return b-a; | ||
32 | } | ||
33 | function 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 |