javascript function distance between two points - javascript

i have been learning javascript for a few days. and im having problems with the sintaxis and the semantics of my programs, i can make run this simple problem. i dont know whats wrong with it
//2. **Distance between two points**. Create a
//function that calculate the distance between two points
//(every point have two coordinates: x, y). _HINT: Your function
//Should receive four parameters_.
function Point(x,y,x1,y1){
this.x = x;
this.y = y;
this.x1 = x1;
this.y1 = y1;
this.distanceTo = function (point)
{
var distance = Math.sqrt((Math.pow(this.x1-this.x,2))+(Math.pow(this.y1-this.y,2)))
return distance;
};
}
var newPoint = new Point (10,100);
var nextPoint = new Point (25,5);
console.log(newPoint.distanceTo(nextPoint));

Try This instead:
function Point(x,y){
this.x = x;
this.y = y;
this.distanceTo = function (point)
{
var distance = Math.sqrt((Math.pow(point.x-this.x,2))+(Math.pow(point.y-this.y,2)))
return distance;
};
}
var newPoint = new Point (10,100);
var nextPoint = new Point (20,25);
console.log(newPoint.distanceTo(nextPoint))
In your distanceTo function you needed to refer to point.x and point.y instead as those are the points of nextPoint.
Hope this Helped :3

You're applying the hint in the wrong place. It's the distanceTo function that should take four parameters.
Given the hint, I wouldn't bother with the Point constructor (although I do like that thinking in general, it just doesn't seem to be what this question's looking for. Just go with distanceTo(x,y,x1,y1), and I don't think you'll have any trouble.

There's a few different ways to do this based on your code but since your function is expecting 4 inputs I went with that one.
function Point(x,y,x1,y1){
this.x = x;
this.y = y;
this.x1 = x1;
this.y1 = y1;
this.distanceTo = function() {
return Math.sqrt((Math.pow(this.x1-this.x,2))+(Math.pow(this.y1-this.y,2)))
};
}
var points = new Point (10,100,25,5);
console.log(points.distanceTo()
);
You also don't need to set the variable and then return it, you can just return the equation.

Your function function Point(x,y,x1,y1) gets four parameters, but you're declaring it with only two of them.
At the distanceTo function you should relate to point which's parameter of your invoked function.
It should go like this; point.x gives you 'X' value of passed object.
#Edit: My solution for this "problem" is;
var Point = function (x,y) {
this.x = x;
this.y = y;
this.distanceTo = function (point) {
let calculations = Math.sqrt((Math.pow(point.x-this.x,2))+(Math.pow(point.y-this.y,2)));
return calculations;
}
}
var firstPoint = new Point(0,0);
var secPoint = new Point(2,2);
console.log(firstPoint.distanceTo(secPoint));

Point constructor should have just two arguments x and y. And distanceTo should use the x and y of this point ant the other point (the one passed as parametter).
function Point(x, y){ // only x and y
this.x = x;
this.y = y;
this.distanceTo = function (point)
{
var dx = this.x - point.x; // delta x
var dy = this.y - point.y; // delta y
var dist = Math.sqrt(dx * dx + dy * dy); // distance
return dist;
};
}
var newPoint = new Point (10,100);
var nextPoint = new Point (25,5);
console.log(newPoint.distanceTo(nextPoint));
Note: Since all Point instances have the exact same distanceTo function, it is better to define it on the prototype instead of redefining it for each instance which will only increase creation time and waste a lot of ressources.
This is better:
function Point(x, y){ // only x and y
this.x = x;
this.y = y;
}
Point.prototype.distanceTo = function (point)
{
var dx = this.x - point.x; // delta x
var dy = this.y - point.y; // delta y
var dist = Math.sqrt(dx * dx + dy * dy); // distance
return dist;
};
var newPoint = new Point (10,100);
var nextPoint = new Point (25,5);
console.log(newPoint.distanceTo(nextPoint));
More about prototpes here!

Related

Gravity Simulation Isn't Working Correctly

I am trying to make a simulation of gravity and the sort. I am just starting off right now, but I've already encountered a problem I can't seem to find the answer to. I am trying to make it so my particle speeds up exponentially by the gravity variable using another variable. But when I run this code, it makes the particle[0].y = NaN. Help is very appreciated.
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var gravity, objectDensity, force, parVelo;
gravity = 9.8;
function Object(mass, x, y, w, h) {
this.m = mass;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
};
var particle = [];
particle.push(new Object(10,10,10,20,20));
function draw() {
parVelo += gravity;
ctx.clearRect(0,0,c.width,c.height);
for(let i = 0, len = particle.length; i < len; i++) {
ctx.fillRect(particle[i].x,particle[i].y,particle[i].w,particle[i].h)
particle[i].y += parVelo;
}
}
setInterval(draw,1000);
You need to set parVelo = 0; probably at the same time as setting the initial value for gravity.

Canvas get perspective point

i've a canvas dom element inside a div #content with transform rotateX(23deg) and #view with perspective 990px
<div id="view">
<div id="content">
<canvas></canvas>
</div>
</div>
if i draw a point (300,300) inside canvas, the projected coordinates are different (350, 250).
The real problem is when an object drawn in a canvas is interactive (click o drag and drop), the hit area is translated.
Which equation i've to use? Some kind of matrix?
Thanks for your support.
This is something I am dealing with now. Lets start out with something simple. Let's say your canvas is right up against the top left corner. If you click the mouse and make an arc on that spot it will be good.
canvasDOMObject.onmouseclick = (e) => {
const x = e.clientX;
const y = e.clientY;
}
If your canvas origin is not at client origin you would need to do something like this:
const rect = canvasDOMObject.getBoundingRect();
const x = e.clientX - rect.x;
const y = e.clientY - rect.y;
If you apply some pan, adding pan, when drawing stuff you need to un-pan it, pre-subtract the pan, when capturing the mouse point:
const panX = 30;
const panY = 40;
const rect = canvasDOMObject.getBoundingRect();
const x = e.clientX - rect.x - panX;
const y = e.clientY - rect.y - panY;
...
ctx.save();
ctx.translate(panX, panY);
ctx.beginPath();
ctx.strokeArc(x, y);
ctx.restore();
If you apply, for instance, a scale when you draw it, you would need to un-scale it when capturing the mouse point:
const panX = 30;
const panY = 40;
const scale = 1.5;
const rect = canvasDOMObject.getBoundingRect();
const x = (e.clientX - rect.x - panX) / scale;
const y = (e.clientY - rect.y - panY) / scale;
...
ctx.save();
ctx.translate(panX, panY);
ctx.scale(scale);
ctx.beginPath();
ctx.strokeArc(x, y);
ctx.restore();
The rotation I have not figured out yet but I'm getting there.
Alternative solution.
One way to solve the problem is to trace the ray from the mouse into the page and finding the point on the canvas where that ray intercepts.
You will need to transform the x and y axis of the canvas to match its transform. You will also have to project the ray from the desired point to the perspective point. (defined by x,y,z where z is perspective CSS value)
Note: I could not find much info about CSS perspective math and how it is implemented so it is just guess work from me.
There is a lot of math involved and i had to build a quick 3dpoint object to manage it all. I will warn you that it is not well designed (I dont have the time to inline it where needed) and will incur a heavy GC toll. You should rewrite the ray intercept and remove all the point clone calls and reuse points rather than create new ones each time you need them.
There are a few short cuts. The ray / face intercept assumes that the 3 points defining the face are the actual x and y axis but it does not check that this is so. If you have the wrong axis you will not get the correct pixel coordinate. Also the returned coordinate is relative to the point face.p1 (0,0) and is in the range 0-1 where 0 <= x <= 1 and 0 <= y <= 1 are points on the canvas.
Make sure the canvas resolution matches the display size. If not you will need to scale the axis and the results to fit.
DEMO
The demo project a set of points creating a cross through the center of the canvas. You will notice the radius of the projected circle will change depending on distance from the camera.
Note code is in ES6 and requires Babel to run on legacy browsers.
var divCont = document.createElement("div");
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 400;
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var ctx = canvas.getContext("2d");
// perspectiveOrigin
var px = cw; // canvas center
var py = 50; //
// perspective
var pd = 700;
var mat;
divCont.style.perspectiveOrigin = px + "px "+py+"px";
divCont.style.perspective = pd + "px";
divCont.style.transformStyle = "preserve-3d";
divCont.style.margin = "10px";
divCont.style.border = "1px black solid";
divCont.style.width = (canvas.width+8) + "px";
divCont.style.height = (canvas.height+8) + "px";
divCont.appendChild(canvas);
document.body.appendChild(divCont);
function getMatrix(){ // get canvas matrix
if(mat === undefined){
mat = new DOMMatrix().setMatrixValue(canvas.style.transform);
}else{
mat.setMatrixValue(canvas.style.transform);
}
}
function getPoint(x,y){ // get point on canvas
var ww = canvas.width;
var hh = canvas.height;
var face = createFace(
createPoint(mat.transformPoint(new DOMPoint(-ww / 2, -hh / 2))),
createPoint(mat.transformPoint(new DOMPoint(ww / 2, -hh / 2))),
createPoint(mat.transformPoint(new DOMPoint(-ww / 2, hh / 2)))
);
var ray = createRay(
createPoint(x - ww / 2, y - hh / 2, 0),
createPoint(px - ww / 2, py - hh / 2, pd)
);
return intersectCoord3DRayFace(ray, face);
}
// draw point projected onto the canvas
function drawPoint(x,y){
var p = getPoint(x,y);
if(p !== undefined){
p.x *= canvas.width;
p.y *= canvas.height;
ctx.beginPath();
ctx.arc(p.x,p.y,8,0,Math.PI * 2);
ctx.fill();
}
}
// main update function
function update(timer){
ctx.setTransform(1,0,0,1,0,0); // reset transform
ctx.globalAlpha = 1; // reset alpha
ctx.fillStyle = "green";
ctx.fillRect(0,0,w,h);
ctx.lineWidth = 10;
ctx.strokeRect(0,0,w,h);
canvas.style.transform = "rotateX("+timer/100+"deg)" + " rotateY("+timer/50+"deg)";
getMatrix();
ctx.fillStyle = "gold";
drawPoint(cw,ch);
for(var i = -200; i <= 200; i += 40){
drawPoint(cw + i,ch);
drawPoint(cw ,ch + i);
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
// Math functions to find x,y pos on plain.
// Warning this code is not built for SPEED and will incure a lot of GC hits
const small = 1e-6;
var pointFunctions = {
add(p){
this.x += p.x;
this.y += p.y;
this.z += p.z;
return this;
},
sub(p){
this.x -= p.x;
this.y -= p.y;
this.z -= p.z;
return this;
},
mul(mag){
this.x *= mag;
this.y *= mag;
this.z *= mag;
return this;
},
mag(){ // get length
return Math.hypot(this.x,this.y,this.z);
},
cross(p){
var p1 = this.clone();
p1.x = this.y * p.z - this.z * p.y;
p1.y = this.z * p.x - this.x * p.z;
p1.z = this.x * p.y - this.y * p.x;
return p1;
},
dot(p){
return this.x * p.x + this.y * p.y + this.z * p.z;
},
isZero(){
return Math.abs(this.x) < small && Math.abs(this.y) < small && Math.abs(this.z) < small;
},
clone(){
return Object.assign({
x : this.x,
y : this.y,
z : this.z,
},pointFunctions);
}
}
function createPoint(x,y,z){
if(y === undefined){ // quick add overloaded for DOMPoint
y = x.y;
z = x.z;
x = x.x;
}
return Object.assign({
x, y, z,
}, pointFunctions);
}
function createRay(p1, p2){
return { p1, p2 };
}
function createFace(p1, p2, p3){
return { p1,p2, p3 };
}
// Returns the x,y coord of ray intercepting face
// ray is defined by two 3D points and is infinite in length
// face is 3 points on the intereceptin plane
// For correct intercept point face p1-p2 should be at 90deg to p1-p3 (x, and y Axis)
// returns unit coordinates x,y on the face with the origin at face.p1
// If there is no solution then returns undefined
function intersectCoord3DRayFace(ray, face ){
var u = face.p2.clone().sub(face.p1);
var v = face.p3.clone().sub(face.p1);
var n = u.cross(v);
if(n.isZero()){
return; // return undefined
}
var vr = ray.p2.clone().sub(ray.p1);
var b = n.dot(vr);
if (Math.abs(b) < small) { // ray is parallel face
return; // no intercept return undefined
}
var w = ray.p1.clone().sub(face.p1);
var a = -n.dot(w);
var uDist = a / b;
var intercept = ray.p1.clone().add(vr.mul(uDist)); // intersect point
var uu = u.dot(u);
var uv = u.dot(v);
var vv = v.dot(v);
var dot = uv * uv - uu * vv;
w = intercept.clone().sub(face.p1);
var wu = w.dot(u);
var wv = w.dot(v);
var x = (uv * wv - vv * wu) / dot;
var y = (uv * wu - uu * wv) / dot;
return {x,y};
}

this keyword inside anonymous function/constructor

To some extent I know whats happening in the code,just to clear my doubts I have posted this question
JavaScript
Point = function (x, y) //Here anonymous constructor is define
{
this.x = x;
this.y = y;
}
var points=[]
points.push(new Point(centerX + radius * Math.sin(angle),centerY - radius * Math.cos(angle))); //object is created and push in the array
And to access the value of points array,I can write points[i].x?
Yes, check this
var Point = function (x, y) //Here anonymous constructor is define
{
this.x = x;
this.y = y;
}
var points = [];
points.push(new Point(2,5));
points.push(new Point(3,11));
points.push(new Point(9,1));
for(var i = 0; i <points.length; i++){
console.log(points[i].x);
console.log(points[i].y);
};
Correct, you can access the object using its index i, and then you are dereferencing the object to access it's attribute/member
var Point = function (x, y)
{
this.x = x;
this.y = y;
}
var points = [];
points.push(new Point(1, 2));
var point = points[0];
alert(point.x == point[0].x);

Why var a is undefined? Javascript OOP

I have this code. It creates an object with x and y field. I want to add a method, which creates new object with additional width and height fields. But despite my tryings it keeps returning undefined. What is wrong?
JSFiddle
function $ (x, y) {
this.x = x;
this.y = y;
return this;
}
$.prototype.$ = function (x, y) {
this.width = x - this.x;
this.height = y - this.y;
return this;
}
var a = $(10,10).$(30,30);
alert(a.width);
var a = (new $(10,10)).$(30,30); //You need new
alert(a.width);
Also it might not be a good idea to have an instance function of a class to have the same name as the class -- it is a little confusing.
Here is how you can do what you want to do with 2 "Point" objects (as asked for in the comments):
var Point = (function(){
var Point = function(x, y) {
this.width = x;
this.height = y;
}
Point.prototype.removePoint = function(point) {
return new Point(point.width - this.width, point.height - this.height);
}
return Point;
})()
var a = new Point(10,10);
var b = new Point(30,30);
var c = a.removePoint(b);
alert(c.width);
Fiddle: http://jsfiddle.net/maniator/d3fx7/
You missed the new before $; This works:
var a = new $(10,10).$(30,30);

How to instantiate a class(ClassA) inside another class(ClassB) and use the ClassA object as a property in ClassB in JavaScript?

Consider the following code:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse() {
this.Text = Text;
this.Cx = Cx;
this.Cy = Cy;
this.Rx = Rx;
this.Ry = Ry;
}
Now in the function Ellipseinstead of using Cx, Cy etc. I want to instantiate the function Coord for each pair to achieve something as follows:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse() {
this.Text = Text;
Coord C = new C(); // where C has its own properties x and y
Coord R = new R(); // where R has its own properties x and y
}
Try this:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse(text, cx, cy, rx, ry) {
this.text = text;
var c = new Coord(cx, cy);
var r = new Coord(rx, ry);
}
I don't know how you thought of Coord C = new C() but it's absolutely wrong. JavaScript variables have no types.
Also from where are you getting Text, Cx, Cy, etc? Shouldn't they be passed as arguments to the constructor?

Categories

Resources