Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
clinicaltrials
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
david Chavalarias
clinicaltrials
Commits
7af0b354
Commit
7af0b354
authored
Apr 04, 2017
by
Romain Loth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: area select
parent
9e6a6545
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
224 additions
and
159 deletions
+224
-159
extras_explorerjs.js
extras_explorerjs.js
+127
-49
grid.css
libs/css2/grid.css
+2
-6
Tinaweb.js
tinawebJS/Tinaweb.js
+86
-98
enviroment.js
tinawebJS/enviroment.js
+2
-2
main.js
tinawebJS/main.js
+4
-1
methods.js
tinawebJS/methods.js
+3
-3
No files found.
extras_explorerjs.js
View file @
7af0b354
...
...
@@ -414,7 +414,7 @@ function draw1Circle(ctx , x , y , color) {
// --------------------
// new sigma.js: could be replaced by default _moveHandler with bindings ?
// => atm rewrote entire function with new values
function
t
rackMouse
(
e
)
{
function
circleT
rackMouse
(
e
)
{
if
(
!
shift_key
)
{
// $.doTimeout(300,function (){
// new sigma.js 2D mouse context
...
...
@@ -426,17 +426,9 @@ function trackMouse(e) {
TW
.
partialGraph
.
renderers
[
0
].
container
.
offsetWidth
,
TW
.
partialGraph
.
renderers
[
0
].
container
.
offsetHeight
);
// testing with overNodes event
// cf. https://github.com/jacomyal/sigma.js/wiki/Events-API
if
(
e
.
type
==
"overNodes"
)
{
x
=
e
.
data
.
captor
.
clientX
y
=
e
.
data
.
captor
.
clientY
}
// classic mousemove event or other similar events
else
{
x
=
sigma
.
utils
.
getX
(
e
);
y
=
sigma
.
utils
.
getY
(
e
);
}
// classic mousemove event or other similar non-sigma events
x
=
sigma
.
utils
.
getX
(
e
);
y
=
sigma
.
utils
.
getY
(
e
);
// console.log("trackMouse mod: x", x, "y", y)
...
...
@@ -446,46 +438,33 @@ function trackMouse(e) {
ctx
.
globalAlpha
=
0.5
;
ctx
.
beginPath
();
//
labels appear
// var nds = TW.partialGraph.graph.nodes(
)
//
convert (TODO CHECK IN THIS CONTEXT)
var
camCoords
=
TW
.
cam
.
cameraPosition
(
x
,
y
)
// TODO replace by a hover binding (and POSS use quadtree zone)
var
exactNodeset
=
circleGetAreaNodes
(
camCoords
.
x
,
camCoords
.
y
)
// TODO REFA UNCOMMENT pseudo hover
// labels appear
//
// if(TW.partialGraph.camera.ratio>showLabelsIfZoom){
// for(var i in nds){
// n=nds[i];
// if(n.hidden==false){
// distance = Math.sqrt(
// Math.pow((x-parseInt(n.displayX)),2) +
// Math.pow((y-parseInt(n.displayY)),2)
// );
// if(parseInt(distance)<=cursor_size) {
// n.forceLabel=true;
// } else {
// if(typeof(n.neighbour)!=="undefined") {
// if(!n.neighbour) n.forceLabel=false;
// } else n.forceLabel=false;
// }
// }
// }
// if(TW.partialGraph.forceatlas2 && TW.partialGraph.forceatlas2.count<=1) {
// TW.partialGraph.refresh({skipIndexation:true})
// }
// } else {
// for(var i in nds){
// n=nds[i];
// if(!n.hidden){
// n.forceLabel=false;
// if(typeof(n.neighbour)!=="undefined") {
// if(!n.neighbour) n.forceLabel=false;
// else n.forceLabel=true;
// } else n.forceLabel=false;
// }
// }
// if(TW.partialGraph.forceatlas2 && TW.partialGraph.forceatlas2.count<=1) {
// TW.partialGraph.refresh({skipIndexation:true})
// }
// if(TW.partialGraph.camera.ratio > showLabelsIfZoom){
// for n of exactNodeset
// n.forceLabel=true;
// }
// else {
// for(var i in exactNodeset){
// n.forceLabel=false;
// if(typeof(n.neighbour)!=="undefined") {
// if(!n.neighbour) n.forceLabel=false;
// else n.forceLabel=true;
// } else n.forceLabel=false;
// }
// if(TW.partialGraph.forceatlas2 && TW.partialGraph.forceatlas2.count<=1) {
// TW.partialGraph.refresh({skipIndexation:true})
// }
// }
ctx
.
arc
(
x
,
y
,
cursor_size
,
0
,
Math
.
PI
*
2
,
true
);
//ctx.arc(TW.partialGraph._core.width/2, TW.partialGraph._core.height/2, 4, 0, 2 * Math.PI, true);/*todel*/
ctx
.
closePath
();
...
...
@@ -495,6 +474,105 @@ function trackMouse(e) {
}
}
// exact subset of nodes under circle
function
circleGetAreaNodes
(
camX0
,
camY0
)
{
// leverage quadtree to get a neighborhood
var
slightlyLargerNodeset
=
circleLocalSubset
(
camX0
,
camY0
,
cursor_size
*
TW
.
cam
.
ratio
// cursor_size to cam units
)
var
exactNodeset
=
[]
for
(
var
i
in
slightlyLargerNodeset
){
n
=
slightlyLargerNodeset
[
i
];
if
(
n
.
hidden
==
false
){
distance
=
Math
.
sqrt
(
Math
.
pow
((
x
-
parseInt
(
n
.
displayX
)),
2
)
+
Math
.
pow
((
y
-
parseInt
(
n
.
displayY
)),
2
)
);
if
(
parseInt
(
distance
)
<=
cursor_size
)
{
exactNodeset
.
push
.
}
else
{
if
(
typeof
(
n
.
neighbour
)
!==
"undefined"
)
{
if
(
!
n
.
neighbour
)
n
.
forceLabel
=
false
;
}
else
n
.
forceLabel
=
false
;
}
}
}
if
(
TW
.
partialGraph
.
forceatlas2
&&
TW
.
partialGraph
.
forceatlas2
.
count
<=
1
)
{
TW
.
partialGraph
.
refresh
({
skipIndexation
:
true
})
}
return
exactNodeset
}
// returns set of nodes in the quad subzones around a square
// that is containing the circle centered on x0, y0
// (use case: reduce number of nodes before exact check)
function
circleLocalSubset
(
camX0
,
camY0
,
camRay
)
{
y
var
P0
=
{
x
:
camX0
,
y
:
camY0
}
// to use quadtree.area, we consider the square
// in which our circle is inscribed
// y-
//
// P1 x----------x P2
// | |
// <= x- | P0 | 2r x+ =>
// | |
// x----------x
//
// y+
var
P1
=
{
x
:
P0
.
x
-
camRay
,
y
:
P0
.
y
-
camRay
}
// top left
var
P2
=
{
x
:
P0
.
x
+
camRay
,
y
:
P0
.
y
-
camRay
}
// top right
var
areaNodes
=
TW
.
cam
.
quadtree
.
area
({
height
:
2
*
camRay
,
x1
:
P1
.
x
,
y1
:
P1
.
y
,
x2
:
P2
.
x
,
y2
:
P2
.
y
})
// neighborhood guaranteed a bit larger than the square
// console.log('got ',areaNodes.length, 'nodes:', areaNodes)
return
areaNodes
}
// not used but useful to quickly make visible any nodes[]
function
flashNodesArray
(
nodesArray
)
{
// for diagnostic
var
minX
=
1000000
var
minY
=
1000000
var
maxX
=
0
var
maxY
=
0
for
(
var
j
in
nodesArray
)
{
var
n
=
nodesArray
[
j
]
if
(
minX
>
n
.
x
)
minX
=
n
.
x
if
(
minY
>
n
.
y
)
minY
=
n
.
y
if
(
maxX
<
n
.
x
)
maxX
=
n
.
x
if
(
maxY
<
n
.
y
)
maxY
=
n
.
y
n
.
size
=
300
n
.
label
=
"> "
+
n
.
label
+
"< "
n
.
color
=
"yellow"
}
console
.
log
(
"nodesArray encompassed by:"
,
minX
,
minY
,
';'
,
maxX
,
maxY
)
TW
.
partialGraph
.
refresh
()
}
// BASIC MODULARITY
// =================
// ProcessDivsFlags is for adding/removing features from TinawebJS
...
...
libs/css2/grid.css
View file @
7af0b354
...
...
@@ -14,15 +14,11 @@
display
:
none
;
}
#graph-div
{
background-color
:
#22e
;
}
#graph-zone
{
#sigma-contnr
{
background-color
:
#44b
;
}
#
right-
sidebar
{
#sidebar
{
background-color
:
#2e2
;
}
...
...
tinawebJS/Tinaweb.js
View file @
7af0b354
...
...
@@ -682,110 +682,85 @@ TinaWebJS = function ( sigmacanvas ) {
});
// new sigma.js: attempt to use sigma events bindings
// cf. https://github.com/jacomyal/sigma.js/wiki/Events-API
// cases:
// [DONE] - simple click, one node
// [TODO] - simple click, area
// 'click' - simple click, early event
// used for area (with global: cursor_size)
// 'clickNode'- simple click, second event if one node
// one node:
// POSS easy in new sigma.js:
// add doubleClick to select node + neighboors
// when circle area select
// ========================
// 1st event, even before we know if there are nodes
TW
.
partialGraph
.
bind
(
'click'
,
function
(
e
)
{
// console.log("sigma click event e", e)
// case with a selector circle cursor handled here
if
(
cursor_size
>
0
)
{
// actual click position, but in graph coords
var
x
=
e
.
data
.
x
var
y
=
e
.
data
.
y
// convert
var
camCoords
=
TW
.
cam
.
cameraPosition
(
x
,
y
)
// retrieve area nodes, using indexed quadtree and global cursor_size
var
circleNodes
=
circleGetAreaNodes
(
camCoords
.
x
,
camCoords
.
y
)
// TODO 1) use SelectorEngine prevsels iff 'Add'
// circleNodes += prevsels
// 2) show selection + do all related effects
SelInst
.
MultipleSelection2
({
nodes
:
circleNodes
})
}
})
// when one node and normal click
// ===============================
TW
.
partialGraph
.
bind
(
'clickNode'
,
function
(
e
)
{
console
.
log
(
"clickNode event node"
,
e
.
data
.
node
)
// console.log("clickNode event e", e.data.node)
// new sigma.js gives easy access to clicked node!
theNodeId
=
e
.
data
.
node
.
id
cancelSelection
(
false
);
if
(
cursor_size
==
0
)
{
// sigma already provided us the target
SelInst
.
MultipleSelection2
({
nodes
:[
theNodeId
]})
}
// case with a selector circle cursor
else
{
// cf TODO mousedown
}
// case with a selector circle cursor handled
// just before, at click event
})
// TODO re-connect area click
// TW.partialGraph.bind('click', function(e) {
// console.log("===click===");
// console.log("e", e);
// })
// TW.partialGraph.bind('downgraph upgraph', function(e) {
// console.log("===downgraph upgraph===");
// console.log("e", e);
// })
// --------------------------------------------fragment from v1.customized
// TW.partialGraph.bind('mousedown mouseup', function(e) {
//
// console.log("---------- event", e)
// var targeted = self.graph.nodes.filter(function(n) {
// return !!n['hover'];
// }).map(function(n) {
// return n.id;
// });
// console.log("---------- targeted by hover check loop", targeted)
// })
//
// self.dispatch(
// e['type'] == 'mousedown' ?
// 'downgraph' :
// 'upgraph'
// );
//
// if (targeted.length) {
// self.dispatch(
// e['type'] == 'mousedown' ?
// 'downnodes' :
// 'upnodes',
// targeted
// );
// }
// }
//
// FOLLOW UP in v1 customized:
// ===========================
// .mousedown(function(e) { // using SelectionEngine
// //left click!<- normal click
// if(e.which==1){
// console.warn('new sigma.js FIX event bindings for downgraph, upgraph')
// partialGraph.dispatchEvent(
// e['type'] == 'mousedown' ?
// 'downgraph' :
// 'upgraph'
// );
// var area = {}
//
//
// // new sigma.js: (x,y) from event -- TODO check if convert coords
// area.x1 = sigma.utils.getX(e);
// area.y1 = sigma.utils.getY(e);
//
// // old version
// // area.x1 = partialGraph._core.mousecaptor.mouseX;
// // area.y1 = partialGraph._core.mousecaptor.mouseY;
//
// var targeted = SelInst.SelectorEngine( {
// cursorsize:cursor_size,
// area:area,
// addvalue:checkBox,
// clicktype:"simple",
// prevsels:selections
// } )
// if(targeted.length>0) {
// cancelSelection(false);
// SelInst.MultipleSelection2( {nodes:targeted} )
// }
// partialGraph.refresh({skipIndexation:true});
// trackMouse(e);
// }
// });
// -------------------------------------------/fragment from v1.customized
// goTo (move/zoom) events
// -------------------------------------------fragment from v1.customized
// FOLLOW UP in v1 customized
// =========
// (last non-reimplemented bit that was using SelectorEngine)
//
// var targeted = SelInst.SelectorEngine( {
// cursorsize:cursor_size,
// area:area,
// addvalue:checkBox,
// clicktype:"simple",
// prevsels:selections
// } )
// if(targeted.length>0) {
// cancelSelection(false);
// SelInst.MultipleSelection2( {nodes:targeted} )
// }
// partialGraph.refresh({skipIndexation:true});
// trackMouse(e);
// -------------------------------------------/fragment from v1.customized
// for all goTo (move/zoom) events
var
zoomTimeoutId
=
null
TW
.
cam
.
bind
(
'coordinatesUpdated'
,
function
(
e
)
{
// debounce
...
...
@@ -796,12 +771,12 @@ TinaWebJS = function ( sigmacanvas ) {
}
// schedule next
zoomTimeoutId
=
window
.
setTimeout
(
// make zoom slider cursor follow scroll
function
(){
// make zoom slider cursor follow scroll
$
(
"#zoomSlider"
).
slider
(
"value"
,
1
/
TW
.
cam
.
ratio
)
// console.log('auto cursor on val', 1/TW.cam.ratio , "( ratio:", TW.cam.ratio,")" )
},
25
0
50
0
)
})
...
...
@@ -810,14 +785,13 @@ TinaWebJS = function ( sigmacanvas ) {
// ==========
$
(
"#sigma-contnr"
)
.
mousemove
(
function
(
e
vent
){
.
mousemove
(
function
(
e
){
if
(
!
isUndef
(
partialGraph
))
{
//
when
selector circle cursor
if
(
cursor_size
>
0
)
trackMouse
(
event
);
//
show/move
selector circle cursor
if
(
cursor_size
>
0
)
circleTrackMouse
(
e
);
}
})
// POSSible for the future: add tools to contextmenu
// .contextmenu(function(){
// return false;
...
...
@@ -941,6 +915,8 @@ TinaWebJS = function ( sigmacanvas ) {
});
//Cursor Size slider
// + reindexation when size is settled (=> updates the quadtree)
var
reindexTimeout
=
null
$
(
"#unranged-value"
).
freshslider
({
step
:
1
,
min
:
cursor_size_min
,
...
...
@@ -950,9 +926,21 @@ TinaWebJS = function ( sigmacanvas ) {
// console.log("en cursorsize: "+value);
cursor_size
=
value
;
if
(
cursor_size
==
0
)
partialGraph
.
refresh
({
skipIndexation
:
true
});
// have reindex ready to go for when user stops moving slider
if
(
reindexTimeout
)
{
// (debounced)
clearTimeout
(
reindexTimeout
)
reindexTimeout
=
null
}
reindexTimeout
=
setTimeout
(
function
()
{
TW
.
partialGraph
.
refresh
({
skipIndexation
:
false
})
// =====
console
.
log
(
"graph quadtree reindexed for cursor"
)
},
500
)
}
});
}
}
// finish initListeners
};
tinawebJS/enviroment.js
View file @
7af0b354
...
...
@@ -66,7 +66,7 @@ function changeType() {
}
}
TW
.
partialGraph
.
emptyGraph
();
TW
.
partialGraph
.
graph
.
clear
();
var
nodes_2_colour
=
{}
var
edges_2_colour
=
{}
...
...
@@ -296,7 +296,7 @@ function changeLevel() {
}
var
str_nextState
=
nextState
.
map
(
Number
).
join
(
"|"
)
TW
.
partialGraph
.
emptyGraph
();
TW
.
partialGraph
.
graph
.
clear
();
var
voisinage
=
{}
// Dictionaries of: selection+neighbors
...
...
tinawebJS/main.js
View file @
7af0b354
...
...
@@ -258,8 +258,11 @@ if(RES["OK"]) {
});
// shortcuts to the renderer and camera
TW
.
rend
=
TW
.
partialGraph
.
renderers
[
0
]
TW
.
cam
=
TW
.
partialGraph
.
camera
TW
.
rend
=
TW
.
partialGraph
.
renderers
[
0
]
// NB : camera positions are fix if the node is fixed => they only depend on layout
// renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div)
// useful
TW
.
partialGraph
.
nNodes
=
TW
.
partialGraph
.
graph
.
nodes
().
length
...
...
tinawebJS/methods.js
View file @
7af0b354
...
...
@@ -399,7 +399,7 @@ function LevelButtonDisable( TF ){
function
graphTagCloudElem
(
nodes
)
{
console
.
log
(
"in graphTagCloudElem, nodae_id: "
+
nodes
);
cancelSelection
();
TW
.
partialGraph
.
emptyGraph
();
TW
.
partialGraph
.
graph
.
clear
();
var
ndsids
=
[]
...
...
@@ -603,7 +603,7 @@ function add1Elem(id) {
updateSearchLabels
(
id
,
TW
.
Nodes
[
id
].
label
,
TW
.
Nodes
[
id
].
type
);
nodeslength
++
;
}
TW
.
partialGraph
.
addNode
(
id
,
anode
);
TW
.
partialGraph
.
graph
.
addNode
(
anode
);
return
;
}
}
else
{
// It's an edge!
...
...
@@ -621,7 +621,7 @@ function add1Elem(id) {
weight
:
TW
.
Edges
[
id
].
weight
};
TW
.
partialGraph
.
addEdge
(
id
,
anedge
.
sourceID
,
anedge
.
targetID
,
anedge
);
TW
.
partialGraph
.
graph
.
addEdge
(
anedge
);
return
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment