D3.js: Getting my own data for the layout - javascript

I have experimenting around with the D3 cluster force layout.
However I am not sure as to how to bind the data and hence, I am not able to have my own data within.
This is what I have tried, without any binding, it's bound not to work.
d3.tsv("data.tsv", function(data){
nodes = d3.range(n).map(function(data) {
var i = Math.floor(Math.random() * m),
r = Math.sqrt((i + 1) / m * -Math.log(data.diskSpace)) * maxRadius,
d = {
cluster: i,
radius: data.radius,
x: Math.cos(i / m * 2 * Math.PI) * 200 + width / 2 + Math.random(),
y: Math.sin(i / m * 2 * Math.PI) * 200 + height / 2 + Math.random()
};
if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d;
return d;
});
This does not seem to work as expected.
What exactly is happening and how do I fix it?
EDIT:
The TSV file
model diskSpace radius
DE431 8 8
DD342 16 18
...

First, make sure the file is actually separated with tabs and not spaces. Loading a tsv in d3 looks like this:
d3.tsv('data.tsv', function (rows) {
console.log(rows);
});
an array of rows will be logged to the console. Note that this call is made asynchronously, the d3.tsv()-function does not return the rows but instead calls a function with the rows as first argument.
Now we need to transform this data into something the d3 force layout understands:
d3.tsv('data.tsv', function (rows) {
var nodes = rows.map(function (item) {
var i = item['diskSpace'],
r = +item['radius'], // note the + to convert to number here.
d = {
cluster: i,
radius: r,
x: Math.cos(i / m * 2 * Math.PI) * 200 + width / 2 + Math.random(),
y: Math.sin(i / m * 2 * Math.PI) * 200 + height / 2 + Math.random()
};
if (!clusters[i] || (r > clusters[i].radius)) {
clusters[i] = d;
}
return d;
});
// insert code generating the force layout here (including the cluster and collide functions)
});
This will cluster the rows by diskSpace. Please note the comments I added.
Working Demo here

Related

Why does my css-animation extend beyond the window?

I have made a CSS-animation with Velocity.js:
https://codepen.io/blaustern_fotografie/pen/GvxWoW
The code is designed such that the circles are not allowed to go beyond the window on the left and right side. The function "my_animate" is responsible for this:
function my_animate(circle) {
var new_y = Math.floor(
Math.random() * ((height -50)-50)+50
);
var new_x = Math.floor(
Math.random() * ((width-50)-50)+50
);
var r = Math.random();
//var nd = Math.floor(r * 500 - 250);
$(circle).velocity(
{
translateX: new_x-$(circle).position().left,
translateY: new_y-$(circle).position().top,
//translateZ: nd,
opacity: r,
blur: Math.round((1 - r) * 5)
},
{
duration: Math.round(Math.random() * 10000 + 10000),
complete: function() {
my_animate(circle);
}
}
);
}
Does anyone know why the circles are passing the edges?
Problem seems here in calculating the new position.
The use of Math.random() is leading to random values being generated for new_x.
var new_x = Math.floor(
Math.random() * ((width -50)-50)+50
);
Then new_x-$(circle).position().left is leading to values being generated which are out of window range.
You should normalise your randomiser to generate new position such that the values generated are always between the min and max points on the viewport.
You need to make the Math.random in range of your window.width, otherwise the randomizer will just calculate values out of your window.width.

Need explanation of basic JavaScript code

I am completely new to JavaScript and I try to understand some basic code.
I need explanation of what's going on in this code:
circles = d3.range(numDisks).map(function(i) {
return {
index: i,
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
};
});
I don't need explanation of math round/random etc.
I need to understand what data structure is built and how to delete elements from this data structure? Not null-them out but complete remove with a shift or whatever.
Thanks you
the data structure created is just an array of objects. Starting with the d3.range function which returns an array of objects which you then map into a new array of objects with the array map operator
you can't remove items in an array map operator as map transforms all objects in the original array, you need to add a filter operator before or after the map with the removal logic.
circles = d3.range(numDisks).map(function(i) {
return {
index: i,
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
};
}).filter(i => i.x !== 0); // this filter removes items where their x value = 0

Instancing PointCloud(ParticleCloud) in THREE.js

i am just a beginner in Threejs so please excuse if its a noobie question. but i haven't worked with particles.
How do i put points(particles) inside a custom geometry of a text geometry?
What i want to achieve is instance points inside a geometry or text then explode it to the world position. if someone direct me to the path, would be much helpful.
i know there's an example https://threejs.org/examples/#webgl_points_dynamic
but i cant understand whats happening in the render loop.
This is not the ultimate solution, but just a starting point.
You can set points from any type of geometry (usual geometry or buffer geometry).
Let's imagine that you have a THREE.TextGeometry(), then you can set points from it as:
textGeo = new THREE.TextGeometry("ABC", {
font: font,
size: 2,
height: 0.25,
curveSegments: 1,
bevelEnabled: false
});
textGeo.computeBoundingBox();
textGeo.computeVertexNormals();
textGeo.center();
fillWithPoints(textGeo, 1000); // fill our text geometry with 1000 random points
textGeo.vertices.forEach(function(vertex){
vertex.startPoint = vertex.clone(); // remember the starting position of a vertex
vertex.direction = vertex.clone().normalize(); // set direction
})
textPoints = new THREE.Points(textGeo, new THREE.PointsMaterial({color: 0x00ff00, size: 0.1})); // all you need is to have a geometry and THREE.PointsMaterial()
scene.add(textPoints);
To determine if a random point is inside our geometry, we can do the trick with projection of all the faces of our text geometry into 2D (x,y) and check if the point (with its x,y coordinates) is inside of one of projected triangles (faces):
function isPointInside(point, geometry) {
var retVal = false;
for (var i = 0; i < geometry.faces.length; i++) { //loop through faces
face = geometry.faces[i];
a = geometry.vertices[face.a];
b = geometry.vertices[face.b];
c = geometry.vertices[face.c];
if (ptInTriangle(point, a, b, c)) {
var retVal = true;
break; // exit the loop if the point is in a projected triangle
}
}
return retVal;
}
where
function ptInTriangle(p, p0, p1, p2) {
// credits: http://jsfiddle.net/PerroAZUL/zdaY8/1/
var A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
var sign = A < 0 ? -1 : 1;
var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
return s > 0 && t > 0 && (s + t) < 2 * A * sign;
}
and then in the animation loop we'll use the stuff of a vertex (startPoint and direction):
textGeo.vertices.forEach(function(vertex){
vertex.copy(vertex.startPoint).addScaledVector(vertex.direction, 5 + Math.sin(Date.now() * 0.001) * 5);
});
textGeo.verticesNeedUpdate = true; // this is the most important thing, you have to set it to true after each rendering
jsfiddle example

JavaScript: Can't get value of variable from another function

I'm facing issues getting value of a variable from another function. I'm trying to get the distance of the place from current position in google maps, but using Haversine Formula of calculating distance.
My HTML:
<p>
<script>
lat = "<?php echo $atm_row_data->latitude;?>";
lng = "<?php echo $atm_row_data->longitude;?>";
dist = getDistance(lat, lng);
document.write(dist);
</script>
</p>
My JavaScript:
var curPosition;
var lat, lng;
/**** get current position ****/
function getPosition() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showCurrentPosition);
} else {
alert('Geolocation is not supported by this browser.');
}
}
function showCurrentPosition(position) {
lat = position.coords.latitude;
lng = position.coords.longitude;
curPosition = new google.maps.LatLng(lat, lng);
console.log('curPosition: '+curPosition); <--- this works
}
/******** Haversine Formula of Getting Distance ********/
var rad = function(x) {
return x * Math.PI / 180;
};
function getDistance(lt, lg) {
console.log(curPosition); <--- this shows undefined
var p1 = curPosition;
var R = 6378137; // Earth’s mean radius in meter
var dLat = rad(lt - p1.lat());
var dLong = rad(lg - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(lt)) *
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
if (d >= 1000)
return Math.round( (d / 1000) * 100) / 100 + "Km";
else
return Math.round( (d * 100) / 100) + "m";
};
/******** END Haversine Formula of Getting Distance ********/
Where am I going wrong?
Any help is appreciated...
Knowing the google api, , navigator.geolocation has a callback, so showcurrentPostion is the callback function, but the thing is u never call
getPosition() <--
function getDistance(lt, lg) {
console.log(curPosition); <--- this shows undefined <---- so this will always be undefined
var p1 = curPosition;
var R = 6378137; // Earth’s mean radius in meter
var dLat = rad(lt - p1.lat());
var dLong = rad(lg - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(lt)) * <--- see comment
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
if (d >= 1000)
return Math.round( (d / 1000) * 100) / 100 + "Km";
else
return Math.round( (d * 100) / 100) + "m";
};
comment: <------ p1 curposition gets an google maps object with lat and long where i know that lat() is not a function so this will fail
so even when u get the current position the function above (getDistance()) will fail
Call getPosition first() <--- u need to get the position
edit: i see that u can call console.log and you say it works, so i think its a scoping issue,
I made an example for you -> http://codepen.io/anon/pen/qOBMPj
i'm not able to render the googlemap within the pen, but u can look at the source, on how its done. hope this helps you.
so in order to do this calculation u dont really need google maps u just need the first/ and second coords, but its fun to do something with on on the google map:)
In your script tags, your only call getDistance(lat,lng), but showCurrentPosition(position) is never called! So the variable curPosition is undefined, because it is not defined yet!
You need to call showCurrentPosition(position) for the variable curPosition to hold a value.
Perhaps calling getPosition() at the beginning of your getDistance() function could solve the problem, as it seems to call showCurrentPosition.
Alternative to show the position in HTML (this is just a quick snippet, you can adapt it to whatever you like):
function getPositionHTML() {
navigator.geolocation.getCurrentPosition(function(pos) {
curPosition = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
});
return curPosition;
}
It basically does the same thing as your other function, but it relies on the Single Reponsibility Principle, so once you called this function you can manipulate curPosition however you want.

Trying to write some maths from Wikipedia in Javascript (sun position computation)

I am trying to approximate the position of the sun in XYZ for a threejs project.
I am following the maths found here: http://en.wikipedia.org/wiki/Position_of_the_Sun
Following the above, I have written the following Javascript code:
var n = ((2440587.5 + (this.datemillis / 8.64E7)) - 2451545);
var L = 280.460 + 0.9856474 * n;
var g = 357.528 + 0.9856003 * n;
L = (L + 360) % 360;
g = (g + 360) % 60;
var lambda = L + 1.915 * Math.sin(g) + 0.0020 * Math.sin(2 * g);
var r = 1.00014 - 0.01671 * Math.cos(g) - 0.00014 * Math.cos(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(e) * Math.sin(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * Math.sin(e) * Math.sin(lambda);
this.datemillis is returned by the getMillisecond function of the Javascript date object. It is updated each frame so that time advances at about 1 hour every 2 seconds.
However something must not be correct as this does not produce the expected result. When I apply the computed x y z coordinates to my sun in my threejs project, I can see the sun rotate around the earth (sitting in 0,0,0) but at a very slow rate (rotating the earth in a few days instead of 24 hours).
I'm thinking it might have something to do with the angle calculations that I'm not doing correctly (degrees/radians?) but I'm not very good at maths so I don't really know what I'm doing so maybe I just misinterpreted the Wiki calculations.
If somebody could spot something obvious I'm doing wrong and help me fix this, would be greatly appreciated!
Thanks
EDIT: so my sun currently is not rotating around the earth in a continous way - it rotates clockwise/counterclockwise alternatively and sometimes jumps positions...
I suggest this to get the Julian Date, from Calculating Jday(Julian Day) in javascript
var today = Date();
var JD = Math.floor((today / 86400000) - (today.getTimezoneOffset()/1440) + 2440587.5);
Add to JD the desired amount of days and increment that value at the desired speed. Note that if you add 1 day each millisecond you'll get 1000 days per second, not 1 hour every 2 seconds.
JD += offset;
Then go on with the wikipedia recipe:
var n = JD - 2451545;
//...
To put L and g in the range 0-360 (you have an error here) use
L = L % 360 + ( L < 0 ? 360 : 0 );
g = g % 360 + ( g < 0 ? 360 : 0 );
The wikipedia formulas express angles in degrees. However JavaScript trigonometric functions cos and sin expect radians.
Just write a "degrees" version of them:
function cosD( deg ) {
return Math.cos( deg * Math.PI / 180.0 );
}
function sinD( deg ) {
return Math.sin( deg * Math.PI / 180.0 );
}
Then use sinD() and cosD() in subsequent calculations.
var r = 1.00014 - 0.01671 * cosD(g) - 0.00014 * cosD(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * cosD(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * cosD(e) * sinD(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * sinD(e) * sinD(lambda);
I cannot answer your question but I do know this is a solved problem in threejs. There is an example running in an architecture/engineering workflow on Github on this topic. The sun position code is here https://github.com/radio412/viewer/blob/gh-pages/sun-position.js
You can see it being tapped for a directional light in threejs at line 108 here: https://github.com/radio412/viewer/blob/gh-pages/va3c-viewer.js

Categories

Resources