Instancing PointCloud(ParticleCloud) in THREE.js - javascript

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

Related

Algorithm to determine if Line points are connected to each other and form a Shape

I am drawing on shape on canvas(using HTML5) and need to determine(in javascript, jquery) if drawn Line Points (x,y cordinates) connect or intersect each other and form some shape(like triangle, square etc.). The purpose of this is to fill these shapes with colors, just like painting tools.
Have read few articles like http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/ but did not clearly understand if this can be used as solution for this problem.
Please suggest and algorithm to determine, if line points are connected to each other and form shapes.
Thanks,
Here are some links which has some required guidance for what I was looking out. Sharing the details here can be helpful for others looking for similar info.
https://gist.github.com/lengstrom/8499382
extract from jsfiddle
http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
// if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
var denominator, a, b, numerator1, numerator2, result = {
x: null,
y: null,
onLine1: false,
onLine2: false
};
denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
if (denominator == 0) {
return result;
}
a = line1StartY - line2StartY;
b = line1StartX - line2StartX;
numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
a = numerator1 / denominator;
b = numerator2 / denominator;
// if we cast these lines infinitely in both directions, they intersect here:
result.x = line1StartX + (a * (line1EndX - line1StartX));
result.y = line1StartY + (a * (line1EndY - line1StartY));
/*
// it is worth noting that this should be the same as:
x = line2StartX + (b * (line2EndX - line2StartX));
y = line2StartX + (b * (line2EndY - line2StartY));
*/
// if line1 is a segment and line2 is infinite, they intersect if:
if (a > 0 && a < 1) {
result.onLine1 = true;
}
// if line2 is a segment and line1 is infinite, they intersect if:
if (b > 0 && b < 1) {
result.onLine2 = true;
}
// if line1 and line2 are segments, they intersect if both of the above are true
return result;
};
Test if two lines intersect - JavaScript function

find position of a point with origin, angle and radius

im stuck with a trigonometry problem in a javascript game im trying to make.
with a origin point(xa,ya) a radius and destination point (ya,yb) I need to find the position of a new point.
//calculate a angle in degree
function angle(xa, ya, xb, yb)
{
var a= Math.atan2(yb - ya, xb - xa);
a*= 180 / Math.PI;
return a;
}
function FindNewPointPosition()
{
//radius origine(xa,xb) destination(ya,yb)
var radius=30;
var a = angle(xa, xb, ya, yb);
newpoint.x = xa + radius * Math.cos(a);
newpoint.y = ya + radius * Math.sin(a);
return newpoint;
}
Imagine a image because I dont have enough reputation to post one :
blue square is the map (5000x5000), black square (500x500) what players see (hud).
Cross(400,400) is the origin and sun(4200,4200) the destination.
The red dot (?,?) indicate to player which direction take to find the sun ..
But sun and cross position can be reverse or in different corner or anywhere !
At the moment the red dot do not do that at all ..
Tks for your help.
Why did you use ATAN2? Change to Math.atan() - you will get angle in var A
Where you have to place your red dot? inside hud?
Corrected code
https://jsfiddle.net/ka9xr07j/embedded/result/
var obj = FindNewPointPosition(400,4200,400,4200); - new position 417. 425
Finally I find a solution without using angle.
function newpointposition(origin, destination)
{
// radius distance between cross and red dot
var r=30;
// calculate a vector
var xDistance = destination.x - origin.x;
var yDistance = destination.y - origin.y;
// normalize vector
var length = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
xDistance /= length;
yDistance /= length;
// add the radius
xDistance = xDistance * r;
yDistance = yDistance * r;
var newpoint = { x: 0, y: 0 };
newpoint.x = origin.x + xDistance;
newpoint.y = origin.y + yDistance;
return newpoint;
}
var radar = newpointposition({
x: 500,
y: 800
}, {
x: 3600,
y: 2850
});
alert(radar.x + ' ' + radar.y);
ty Trike, using jsfiddle really help me.

Drawing a line with perpendicular decoration

I need to draw a line in the following manner:
 
For now, it will be only drawn in code, no user input.
My question is, how to draw perpendiculars to a line, if I draw it point by point? (Obviously, this will be the case, because drawing with bezier curves will not give me the possibility to somehow impact the drawing).
The closest answer I found was possibly this one, but I can't reverse the equations to derive C. Also there is no length of the decoration mentioned, so I think this will not work as I'd like it to.
Find the segment perpendicular to another one is quite easy.
Say we have points A, B.
Compute vector AB.
Normalize it to compute NAB (== the 'same' vector, but having a length of 1).
Then if a vector has (x,y) as coordinates, its normal vector has (-y,x) as coordinates, so
you can have PNAB easily (PNAB = perpendicular normal vector to AB).
// vector AB
var ABx = B.x - A.x ;
var ABy = B.y - A.y ;
var ABLength = Math.sqrt( ABx*ABx + ABy*ABy );
// normalized vector AB
var NABx = ABx / ABLength;
var NABy = ABy / ABLength;
// Perpendicular + normalized vector.
var PNABx = -NABy ;
var PNABy = NABx ;
last step is to compute D, the point that is at a distance l of A : just add l * PNAB to A :
// compute D = A + l * PNAB
var Dx = A.x + l* PNAB.x;
var Dy = A.y + l *PNAB.y;
Updated JSBIN :
http://jsbin.com/bojozibuvu/1/edit?js,output
Edit :
A second step is to draw the decorations at regular distance, since it's Christmas time, here's how i would do it :
http://jsbin.com/gavebucadu/1/edit?js,console,output
function drawDecoratedSegment(A, B, l, runningLength) {
// vector AB
var ABx = B.x - A.x;
var ABy = B.y - A.y;
var ABLength = Math.sqrt(ABx * ABx + ABy * ABy);
// normalized vector AB
var NABx = ABx / ABLength;
var NABy = ABy / ABLength;
// Perpendicular + normalized vector.
var PNAB = { x: -NABy, y: NABx };
//
var C = { x: 0, y: 0 };
var D = { x: 0, y: 0 };
//
drawSegment(A, B);
// end length of drawn segment
var endLength = runningLength + ABLength;
// while we can draw a decoration on this line
while (lastDecorationPos + decorationSpacing < endLength) {
// compute relative position of decoration.
var decRelPos = (lastDecorationPos + decorationSpacing) - runningLength;
// compute C, the start point of decoration
C.x = A.x + decRelPos * NABx;
C.y = A.y + decRelPos * NABy;
// compute D, the end point of decoration
D.x = C.x + l * PNAB.x;
D.y = C.y + l * PNAB.y;
// draw
drawSegment(C, D);
// iterate
lastDecorationPos += decorationSpacing;
}
return ABLength;
}
All you need is direction of curve (or polyline segment) in every point, where you want to draw perpendicular.
If direction vector in point P0 is (dx, dy), then perpendicular (left one) will have direction vector (-dy, dx). To draw perpendicular with length Len, use this pseudocode:
Norm = Sqrt(dx*dx + dy*dy) //use Math.Hypot if available
P1.X = P0.X - Len * dy / Norm
P1.Y = P0.Y + Len * dx / Norm
P.S. If you know direction angle A, then direction vector
(dx, dy) = (Cos(A), Sin(A))
and you don't need to calculate Norm, it is equal to 1.0

how to draw curve through N points using javascript HTML5 canvas?

For a drawing application I'm saving the mouse movement coordinates to an array then drawing them with lineTo. The resulting line is not smooth. How can I produce a single curve between all the gathered points?
I've googled but I have only found 3 functions for drawing lines: For 2 sample points, simply use lineTo. For 3 sample points quadraticCurveTo, for 4 sample points, bezierCurveTo.
(I tried drawing a bezierCurveTo for every 4 points in the array, but this leads to kinks every 4 sample points, instead of a continuous smooth curve.)
How do I write a function to draw a smooth curve with 5 sample points and beyond?
You can use cardinal spline to do this:
The function for this is like this with array of points ordered as [x1, y1, x2, y2, ... xn, yn], tension between [0.0, 1.0] and optionally number of segments which dictates the resolution between each point.
Here's an online demo of this in action
UPDATE posted wrong version of my cardinal implementation, this is the correct one -
The result will be a new array with the smoothed line that you iterate -
function getCurvePoints(ptsa, tension, numOfSegments) {
// use input value if provided, or use a default value
tension = (tension != 'undefined') ? tension : 0.5;
numOfSegments = numOfSegments ? numOfSegments : 16;
var _pts = [], res = [], // clone array
x, y, // our x,y coords
t1x, t2x, t1y, t2y, // tension vectors
c1, c2, c3, c4, // cardinal points
st, t, i; // steps based on num. of segments
// clone array so we don't change the original
_pts = ptsa.slice(0);
_pts.unshift(pts[1]); //copy 1. point and insert at beginning
_pts.unshift(pts[0]);
_pts.push(pts[pts.length - 2]); //copy last point and append
_pts.push(pts[pts.length - 1]);
// ok, lets start..
// 1. loop goes through point array
// 2. loop goes through each segment between the two points + one point before and after
for (i=2; i < (_pts.length - 4); i+=2) {
// calc tension vectors
t1x = (_pts[i+2] - _pts[i-2]) * tension;
t2x = (_pts[i+4] - _pts[i]) * tension;
t1y = (_pts[i+3] - _pts[i-1]) * tension;
t2y = (_pts[i+5] - _pts[i+1]) * tension;
for (t=0; t <= numOfSegments; t++) {
// calc step
st = t / numOfSegments;
// calc cardinals
c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1;
c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2);
c3 = Math.pow(st, 3) - 2 * Math.pow(st, 2) + st;
c4 = Math.pow(st, 3) - Math.pow(st, 2);
// calc x and y cords with common control vectors
x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x;
y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y;
//store points in array
res.push(x);
res.push(y);
}
}
return res;
}

Detecting if a point is of a line segment

If I have a line, with the points x,y,endx and endy how can I detect if another point is on the line? A simple equation, or example functions in JavaScript or pseudocode will be most helpful.
EDIT:
This is for a game I'm working on, I'm trying to detect if a laser is colliding with an object, Here is the sample http://jefnull.com/references/lasers/ The file that will be most descriptive is http://jefnull.com/references/lasers/lasers.js
Since my previous answer said how to determine if a point was on the line, and the real question appears to be "how can I tell if the point is near the line segment", I'm adding a new answer.
Here's the trick: first find the distance from your obstacle to each of the two endpoints of your line segment. These two distances don't uniquely determine the location of the obstacle, but they do uniquely determine a triangle with three specific side lengths, and then we can immediately use a bunch of geometry.
I fiddled with the colors a little. Anyway, I mentioned in a comment above that you should use the point-line distance formula to find the distance between the obstacle and the line. But that won't actually work. The reason is that is is the point-line distance. So, for both examples below, the formula will calculate the bold distance H in the picture.
That isn't right!!
So instead, here is the pseudocode for finding the distance from your obstacle to the line segment formed by the laser:
Find the distance from my point to the line segment!
if the angle at (x,y) is obtuse
return A
else if the angle at (endx,endy) is obtuse
return B
else
return H
Here is the math you can use to implement the above pseudocode:
To see if the angle at (x,y) is obtuse, find whether B^2 > A^2 + C^2. If so, the angle is obtuse.
To see if the angle at (endx, endy) is obtuse, find whether A^2 > B^2 + C^2. If so, the angle is obtuse.
To calculate H, use two different methods for finding the area of the triangle -- the usual base*height/2 and Heron's Formula.
This means you should:
set s = (A+B+C)/2
The area of the triangle is C*H/2
The area of the triangle is also sqrt(s*(s-A)*(s-B)*(s-C))
So H = 2/C * sqrt(s*(s-A)*(s-B)*(s-C)).
The end result is something like:
if B^2 > A^2 + C^2
return A
else if A^2 > B^2 + C^2
return B
else
s = (A+B+C)/2
return 2/C * sqrt(s*(s-A)*(s-B)*(s-C))
I think that should give you enough to accomplish what you are actually setting out to do. Good luck, and don't give up!
First of all, the answer provided by Razack was the most mathematically sound answer, though highly theoretical. If you are upvoting this answer, please consider upvoting his answer too.
I have implemented his methods in the following useful javascript functions. Have a look in particular at function calcIsInsideThickLineSegment(...). Use as you please.
//Returns {.x, .y}, a projected point perpendicular on the (infinite) line.
function calcNearestPointOnLine(line1, line2, pnt) {
var L2 = ( ((line2.x - line1.x) * (line2.x - line1.x)) + ((line2.y - line1.y) * (line2.y - line1.y)) );
if(L2 == 0) return false;
var r = ( ((pnt.x - line1.x) * (line2.x - line1.x)) + ((pnt.y - line1.y) * (line2.y - line1.y)) ) / L2;
return {
x: line1.x + (r * (line2.x - line1.x)),
y: line1.y + (r * (line2.y - line1.y))
};
}
//Returns float, the shortest distance to the (infinite) line.
function calcDistancePointToLine(line1, line2, pnt) {
var L2 = ( ((line2.x - line1.x) * (line2.x - line1.x)) + ((line2.y - line1.y) * (line2.y - line1.y)) );
if(L2 == 0) return false;
var s = (((line1.y - pnt.y) * (line2.x - line1.x)) - ((line1.x - pnt.x) * (line2.y - line1.y))) / L2;
return Math.abs(s) * Math.sqrt(L2);
}
//Returns bool, whether the projected point is actually inside the (finite) line segment.
function calcIsInsideLineSegment(line1, line2, pnt) {
var L2 = ( ((line2.x - line1.x) * (line2.x - line1.x)) + ((line2.y - line1.y) * (line2.y - line1.y)) );
if(L2 == 0) return false;
var r = ( ((pnt.x - line1.x) * (line2.x - line1.x)) + ((pnt.y - line1.y) * (line2.y - line1.y)) ) / L2;
return (0 <= r) && (r <= 1);
}
//The most useful function. Returns bool true, if the mouse point is actually inside the (finite) line, given a line thickness from the theoretical line away. It also assumes that the line end points are circular, not square.
function calcIsInsideThickLineSegment(line1, line2, pnt, lineThickness) {
var L2 = ( ((line2.x - line1.x) * (line2.x - line1.x)) + ((line2.y - line1.y) * (line2.y - line1.y)) );
if(L2 == 0) return false;
var r = ( ((pnt.x - line1.x) * (line2.x - line1.x)) + ((pnt.y - line1.y) * (line2.y - line1.y)) ) / L2;
//Assume line thickness is circular
if(r < 0) {
//Outside line1
return (Math.sqrt(( (line1.x - pnt.x) * (line1.x - pnt.x) ) + ( (line1.y - pnt.y) * (line1.y - pnt.y) )) <= lineThickness);
} else if((0 <= r) && (r <= 1)) {
//On the line segment
var s = (((line1.y - pnt.y) * (line2.x - line1.x)) - ((line1.x - pnt.x) * (line2.y - line1.y))) / L2;
return (Math.abs(s) * Math.sqrt(L2) <= lineThickness);
} else {
//Outside line2
return (Math.sqrt(( (line2.x - pnt.x) * (line2.x - pnt.x) ) + ( (line2.y - pnt.y) * (line2.y - pnt.y) )) <= lineThickness);
}
}
To see some of this code in action using a nice SVG, see this fiddle which I used to debug:
https://jsfiddle.net/c06zdxtL/2/
You want to check whether the slopes are the same between the pairs of points. But you should be careful not to ever divide by zero, so check by checking the cross-multiplied version of the equations.
More explicitly, if your points are A = (Ax, Ay), B = (Bx, By), C = (Cx, Cy), then you would like to check that
(Cy - Ay) / (Cx - Ax) = (By - Ay) / (Bx - Ax)
But instead you should check that
(Cy - Ay) * (Bx - Ax) = (By - Ay) * (Cx - Ax).
function isOnLine(x, y, endx, endy, px, py) {
var f = function(somex) { return (endy - y) / (endx - x) * (somex - x) + y; };
return Math.abs(f(px) - py) < 1e-6 // tolerance, rounding errors
&& px >= x && px <= endx; // are they also on this segment?
}
x, y, endx and endy are the points that define the line, using which you can build the equation of that line. Then, fill in px and see if f(px) = py (in fact checking for small enough due to rounding errors). Lastly, check whether the line segment is defined on the interval x ... endx.
Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
Let P be the point of perpendicular projection of C on AB. The parameter
r, which indicates P's position along AB, is computed by the dot product
of AC and AB divided by the square of the length of AB:
(1) AC dot AB
r = ---------
||AB||^2
r has the following meaning:
r=0 P = A
r=1 P = B
r<0 P is on the backward extension of AB
r>1 P is on the forward extension of AB
0<r<1 P is interior to AB
The length of a line segment in d dimensions, AB is computed by:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)
so in 2D:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
and the dot product of two vectors in d dimensions, U dot V is computed:
D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
So (1) expands to:
(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
r = -------------------------------
L^2
The point P can then be found:
Px = Ax + r(Bx-Ax)
Py = Ay + r(By-Ay)
And the distance from A to P = r*L.
Use another parameter s to indicate the location along PC, with the
following meaning:
s<0 C is left of AB
s>0 C is right of AB
s=0 C is on AB
Compute s as follows:
(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
s = -----------------------------
L^2
Then the distance from C to P = |s|*L.
function is_point_on_segment (startPoint, checkPoint, endPoint) {
return ((endPoint.y - startPoint.y) * (checkPoint.x - startPoint.x)).toFixed(0) === ((checkPoint.y - startPoint.y) * (endPoint.x - startPoint.x)).toFixed(0) &&
((startPoint.x > checkPoint.x && checkPoint.x > endPoint.x) || (startPoint.x < checkPoint.x && checkPoint.x < endPoint.x)) &&
((startPoint.y >= checkPoint.y && checkPoint.y >= endPoint.y) || (startPoint.y <= checkPoint.y && checkPoint.y <= endPoint.y));
}
Test:
var startPoint = {x:30,y:30};
var checkPoint = {x:40,y:40};
var endPoint = {x:50,y:50};
console.log(is_point_on_segment(startPoint ,checkPoint ,endPoint ));
According to the straight line equation y = mx + b where m is slope, x is value of point at x axis and b is y intercept (the point where line intercept y axis).
m(slope) = endy - y/endx - x;
e.g. if a line starts at (0, 0) and ends (4,2) then m = 4-0/2-0 = 2;
b (y intercept) = 0 ;
now for example you are provided with a point(1,2) to see if it lies on line. okay calculate your y coordinate with the help of x coordinate. i.e.
y = mx+b
y= 2(1) + 0; // here x is the x coordinate of the given point
y = 2; which is exactly the same as the y- coordinate of your given point so we can conclude this lies on the line. If the point had value (2,2) according to equation it will evaluate to y= 4 which is not equal to the y-coordinate of the point you were given so it doesn't lie on the line.
function isOnLine(initial_x, initial_y, endx, endy, pointx, pointy, tolerate) {
var slope = (endy-initial_y)/(endx-initial_x);
var y = slope * pointx + initial_y;
if((y <= pointy+tolerate && y >= pointy-tolerate) && (pointx >= initial_x && pointx <= endx)) {
return true;
}
return false;
}
Here is my implementation of isOnLine
function isOnLine(a, b, p, tolerance) {
var dy = a.y - b.y;
var dx = a.x - b.x;
if(dy == 0) { //horizontal line
if(p.y == a.y) {
if(a.x > b.x) {
if(p.x <= a.x && p.x >= b.x)
return true;
}
else {
if(p.x >= a.x && p.x <= b.x)
return true;
}
}
}
else if(dx == 0) { //vertical line
if(p.x == a.x) {
if(a.y > b.y) {
if(p.y <= a.y && p.y >= b.y)
return true;
}
else {
if(p.y >= a.y && p.y <= b.y)
return true;
}
}
}
else { //slope line
var s = dy/dx;
var py = s * p.x;
if(py <= p.y + tolerance && py >= p.y - tolerance) {
if(a.x > b.x) {
if(p.x <= a.x && p.x >= b.x)
return true;
}
else {
if(p.x >= a.x && p.x <= b.x)
return true;
}
}
}
return false;
}

Categories

Resources