-
Notifications
You must be signed in to change notification settings - Fork 1
/
MikesFlotExample_v2.html
263 lines (218 loc) · 8.99 KB
/
MikesFlotExample_v2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Flot Examples</title>
<link href="flot/layout.css" rel="stylesheet" type="text/css">
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]-->
<!--script language="javascript" type="text/javascript" src="http://people.iola.dk/olau/flot/jquery.js"></script-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script language="javascript" type="text/javascript" src="flot/jquery.flot.js"></script>
<!-- include PCHIP-JS library from dropbox public folder-->
<script language="javascript" type="text/javascript" src="pchip.js"></script>
<!-- include PCHIP-JS library from google code (mime type may not match) -->
<!--script language="javascript" type="text/javascript" src="http://pchip-js.googlecode.com/svn/trunk/pchip.js"></script-->
<!-- plese dont copy this next script, it is for my google analytics account-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-33680265-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<h1>Flot Examples: Drag and Push With PCHIP Shape Preserving Fit and Inverse Cumulative Histogram constraint</h1>
<p>Click to grab a point, move it to desired location, then click again to release it. You can also click on the fit line to add a control point.</p>
<p>This demo was built from an official <a href="http://code.google.com/p/flot/">Flot</a> example found <a href="http://people.iola.dk/olau/flot/examples/">here</a>, using my <a href="http://code.google.com/p/pchip-js/">pchip-js</a> fit library.</p>
<div id="placeholder" style="width:600px;height:300px"></div>
<p>One of the goals of Flot is to support user interactions. Try
pointing and clicking on the points.</p>
<p id="hoverdata">Mouse hovers at
(<span id="x">0</span>, <span id="y">0</span>). <span id="clickdata"></span></p>
<p>A tooltip is easy to build with a bit of jQuery code and the
data returned from the plot.</p>
<p><input id="enableTooltip" type="checkbox">Enable tooltip</p>
<script type="text/javascript">
$(function () { //removed namespace wrapper
var dragItem = null;
var fit = [], pts = [];
var m1 = -1.0, b1 = 100;
var m2 = -0.5, b2 = 50;
for (var i = 0; i < 110; i += 10) {
pts.push([i, m1*i+b1]);
}
for (i = 0; i < 110; i += 10) {
fit.push([i, m1*i+b1]);
}
var plot = $.plot($("#placeholder"),
[ { data: fit, label: "Fit", lines: {show:true }, points:{show:false}, grid:{clickable:false} },
{ data: pts, label: "Points", lines: {show:false}, points:{show:true}, grid:{clickable:true} }], {
// series: { lines: { show: true }, points: { show: true }
// },
grid: { hoverable: true, clickable: true, autoHighlight: false},
yaxis: { min: 0.0, max: 100.0 }
});
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': '#fee',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
//relocate current point:
if(dragItem){// add check for mousedown if for drag only
var buffer = 2.0;
//copy old data:
var newData = plot.getData();
//get new point location:
var X = pos.x;//.toFixed(2);
var Y = pos.y;//.toFixed(2);
//item info:
var idx = dragItem.dataIndex;
var series = dragItem.seriesIndex;
newData[series].data[idx][0] = X;
newData[series].data[idx][1] = Y;
/*apply constraints here*/
//look right for overlapping points and PUSH them:
for(var i = idx+1; i < newData[series].data.length; i++){
//if x value of elements after the current value are less
if( newData[series].data[i][0] < X ){
newData[series].data[i][0] = X;//+(i-idx)*buffer;
}
if( newData[series].data[i][1] > Y ){
newData[series].data[i][1] = Y;//-(i-idx)*buffer;
}
}
//now look left and PUSH
for(i = idx-1; i >= 0; i--){
//if x value of elements after the current value are less
if( newData[series].data[i][0] > X ){
newData[series].data[i][0] = X;//-(idx-i)*buffer;
}
if( newData[series].data[i][1] < Y ){
newData[series].data[i][1] = Y;//+(idx-i)*buffer;
}
}
//redraw plot
cleanData(plot,series);
fitData(plot,1,0);
plot.draw();
}
if ($("#enableTooltip:checked").length > 0) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
showTooltip(item.pageX, item.pageY,
item.series.label + " of " + x + " = " + y);
}
}
else {
$("#tooltip").remove();
previousPoint = null;
s$("#placeholder").onmousemove = null;
}
}
});//end bind
$("#placeholder").bind("plotclick", function (event, pos, item) {
if (item) {
$("#clickdata").text("You clicked point " + item.dataIndex + " in " + item.series.label + ".");
if(dragItem === null){
//only drag for upper layer series:
if(item.seriesIndex == 1){
dragItem = item;//set drag item
}else{//add the point to the first series and make it dragable
var newData = plot.getData();
for(var i=0; i<newData[1].data.length; i++){
if( item.datapoint[0] <= newData[1].data[i][0]){
newData[1].data.splice(i,0,item.datapoint);
item.seriesIndex = 1;
item.dataIndex = i;
dragItem=item;
break; //out of loop
}
}
plot.setData(newData);
plot.draw();
}
}
else{//unselect item
//plot.unhighlight(dragItem.series, dragItem.datapoint);
//--clean up data--//
//cleanData(plot,1);
//fitData(plot,1,0);
dragItem = null;
}
}
});//end bind
function cleanData(plot,series){
/** applies constraints to series within plot and re-plots data **/
var clean_data = plot.getData();
for( var i = 0; i<clean_data[series].data.length-1; i++ ){
//caution one-pass clean may be buggy
iX = clean_data[series].data[i][0];
iY = clean_data[series].data[i][1];
//find duplicate points and delete them
if( Math.abs(iX - clean_data[series].data[i+1][0]) < 2.0 &&
Math.abs(iY - clean_data[series].data[i+1][1]) < 2.0 ){
if(dragItem == null){
clean_data[series].data.splice(i,1);//remove 1 element at index 'i'
}
//we are dragging be careful...
else{
//only delete points outside of range of dragIndex
//if( dragItem.dataIndex != i+1 & dragItem.dataIndex != i ){
if(dragItem.dataIndex > i){
dragItem.dataIndex--; //decriment index since we are loosing data below
}
clean_data[series].data.splice(i,1);//remove 1 element at index 'i'
//}
}
}
//make sure data points are greater than zero or less than 100
if( iY > 100.0 ){
clean_data[series].data[i][1] = 100.0;
}
else if( iY < 0.0 ){
clean_data[series].data[i][1] = 0.0;
}
//no neg. x values either
if( iX < 0.0 ){
clean_data[series].data[i][0] = 0.0;
}
}
//clamp first and last value to 0
var len = clean_data[series].data.length;
clean_data[series].data[len-1][1] = 0; //last point has 0 y value
clean_data[series].data[0][0] = 0; //first point has 0 x value
//if(len-2 >=0 )
// clean_data[series].data[len-1][0] = clean_data[series].data[len-2][0] + 2.0;
//and last x value must be larger than previous value (due to sampling freq.)
plot.setData(clean_data);
}
function fitData(plot,inputIdx,fitIdx){
var clean_data = plot.getData();
sample_frequency = 3.0; //samples per unit x along x axis
/** USING PCHIP JS LIBRARY **/
clean_data[fitIdx].data = PCHIP.fit(clean_data[inputIdx].data,sample_frequency,"shape_preserving"); //array and frequency of new sample, specify shape_preserving algorithm
plot.setData(clean_data);
}
});
</script>
</body>
</html>