How can wheelnav.js be setup to rotate both clockwise and counterclockwise, whichever is closest? Whenever it goes from 0 to the highest number, it flips around the long way, as seen when you go from 0 to 5 on this demo page after turning on rotation:
http://pmg.softwaretailoring.net/
It needs to always rotate in the closest direction and never flip around the long way.
I am also open to a solution using wheelizate tabs, which uses Wheelnav to accomplish this:
http://wtabs.softwaretailoring.net/
Thank you for your attention on this.
Found the solution by doing a Console.log(rotationAngle), and watching what the rotation value for each particular click. Then I found that I could take the numbers of the situations that went the wrong way, and subtract 360 from it to get it to rotate the opposite direction.
The patch involve adding this to Wheelnav.js line 411:
if (rotationAngle == 288){
rotationAngle = -72;
}
if (rotationAngle == 216){
rotationAngle = -144;
}
You need to replace the next line (line 422 of Wheelnav.js):
navItem.currentRotateAngle -= rotationAngle;
with the following conditional expression:
if (rotationAngle >= 180) {
rotationAngle = 360 - rotationAngle;
navItem.currentRotateAngle += rotationAngle;
} else if (Math.abs(rotationAngle) > 180) {
rotationAngle = 360 + rotationAngle;
navItem.currentRotateAngle -= rotationAngle;
} else {
navItem.currentRotateAngle -= rotationAngle;
}
Related
I am having some trouble with programming hit detection in Processing.JS. I have tried to make a function that checks if something is touching an object and returns true and otherwise returns false. This is that here.
`Box.prototype.checkTouching = function(v){
if(v.position.x > this.position.x - this.width/2 && v.position <
this.position.x + this.width/2 && v.position.y > this.positon.y -
this.height/2 && v.position.y < this.position.y + this.height/2){
return true;
}else{
return false;
}
};`
I am implementing it by creating a new variable "b" in my draw function that holds the value the function returned then using an if statement to check if the value "b" is holding is true. Like so
var b = box3.checkTouching(mos);
if(b === true){
println("It works");
}
What should happen when the two objects touch is that a message saying "it works" gets printed in to the console. Unfortunately even when the object the function is running on is touching the object that is running it nothing happens. I have already checked to see if the logic works and it is valid so I know it has to be my implementation I just can not seem to find out what is wrong with my implementation. Can anyone tell what I am doing wrong? Full program here
You need to check whether the rectangles overlap. You'd do this by checking each side, like this:
if(rectOneRight > rectTwoLeft && rectOneLeft < rectTwoRight && rectOneBottom > rectTwoTop && rectOneTop < rectTwoBottom){
//collision
}
Shameless self-promotion: I've written a tutorial on collision detection in Processing (including rectangle-rectangle collision) available here.
To build on what Kevin posted, say I want to hover my mouse over a rectangle. processing has the built in variables mouseX, mouseY that return the coordinates of the mouse.
so I would check if the mouse X position was greater then the rect X pos, and less than the rect X pos + the rect width. the, do the same with the mouseY, rect Y and rect height
if (mouseX > rectXpos &&
mouseX < rectXpos + rectWidth &&
mouseY > rectYpos &&
mouseY < rectYpos + rectHeight) {
// the button is being hovered over
}
I've been working on a physics engine for about a week now, being stuck for several days trying to work out how to resolve collisions.
My problem is that if there's a box stuck in the middle of 2 other boxes, or between a box and a wall, my application will get stuck in a while loop. It wont resolve the collisions.
This is my code (note: if collision is right side, it means that object A is colliding against object B with its right side. Distance is negative because the objects are inside eachother, and it's in x or y axis depending on side of collision. If you need more code, for example the collision class, which is simply a container of the 2 objects, i can provide that.):
edit: Code edited with new way of dealing with collisions:
//Move colliding objects so they don't collide anymore.
while (getCollidingAmount(objectVector)){
for (int i = 0; i < objectVector.size(); i++){
PhysicsObject* A = objectVector[i];
if (objectVector[i]->getPhysicsType() != PhysicsType::staticT && A->_collision.size() > 0){
Collision collision = A->_collision[A->getDeepestPenetrationCollisionIndex(A->_collision)];
PhysicsObject* B = collision.getObject();
switch (collision.getSide()){
case SideOfCollision::left:
case SideOfCollision::top:
//Opposite velocity
if (A->_saveVelocity.x < 0 && B->_saveVelocity.x > 0){
long double percentageOfVelocity = std::min(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x)) /
std::max(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x));
A->_position.x -= percentageOfVelocity*collision.getVectorPenetration().x;
A->_position.y -= percentageOfVelocity*collision.getVectorPenetration().y;
}
else{
A->_position.x -= collision.getVectorPenetration().x;
A->_position.y -= collision.getVectorPenetration().y;
}
break;
case SideOfCollision::right:
case SideOfCollision::bottom:
//Opposite velocity
if (A->_saveVelocity.x > 0 && B->_saveVelocity.x < 0){
long double percentageOfVelocity = 1 - std::min(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x)) /
std::max(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x));
A->_position.x -= percentageOfVelocity*collision.getVectorPenetration().x;
A->_position.y -= percentageOfVelocity*collision.getVectorPenetration().y;
}
else{
A->_position.x -= collision.getVectorPenetration().x;
A->_position.y -= collision.getVectorPenetration().y;
}
break;
}
updateCollisions(objectVector);
}
}
}
Update
Something wrong with my trigonometry in bottom and top collisions:
sf::Vector2<long double> Collision::getVectorPenetration() const{
long double x;
long double y;
long double velX = _object->getVelocity().x;
long double velY = _object->getVelocity().y;
long double angle = atan2(velY, velX);
if (_side == SideOfCollision::left || _side == SideOfCollision::right){
x = getDistance();
y = x * tan(angle);
return sf::Vector2<long double>(x, y);
}
else if (_side == SideOfCollision::top || _side == SideOfCollision::bottom){
y = getDistance();
x = y / tan(angle);
return sf::Vector2<long double>(x, y);
}
}
Update 2
Thanks to Aiman, i solved my issue. Updated my collisionResponse code aswell to match my new way of dealing with collisions. I'm having another issue now where gravity makes it so i can't move in X direction when touching another object. If anyone familiar with this issue wants to give any tips to solve it, i appreciate it :).
Update 3
So it seems gravity is not actually the problem since i can swap gravity to the x axis, and then be able to slide boxes along the walls. There seems to still be something wrong with the trigonometry.
I can think of many ways to approach the problem.
1-**The more complicated one is to **introduce friction. Here is how I'd implement it, though this is untested and there is a chance I missed something in my train of thought.
Every shape gets a friction constant, and according to those your objects slide when they collide.
First, you need to get the angle that is perpendicular to your surface. To do this, you just get the arctan of the the surface's normal slope. The normal is simply -1/m, where m is the slope of your surface (which you is the ratio/quotient of how much the surface extends in y to/by how much it extends in x). Let's call this angle sNormal for "surface normal". We may also need sAngle-"surface angle" for later (you find that by arctan(m)). There remains some ambiguity in the angle that has to do with whether you're talking about the 'front' or the 'back' of the surface. You'll have to deal with that manually.
Next, you need the angle of the trajectory your object flies in, which you already know how to find (atan2(y,x)). We'll call this angle oAngle for "object's surface angle". Next, you calculate deltaAngle = sNormal - oAngle. This angle represents how much momentum was not blocked completely by the surface. A deltaAngle of 0 means all momentum is gone, and a value of PI/2 or 90 means the 2 surfaces are in parallel touching each other not blocking any momentum at all. Anything in between, we interpolate:
newSpeed = objectSpeed * deltaAngle/(PI/2);
newVelocity.x = cos(sAngle) * objectSpeed;
newVelocity.y = sin(sAngle) * objectSpeed;
Now this assumes 0 friction. If we let a friction of 1 be the maximum friction which doesn't allow the object to "slide", we modify the newSpeed before we apply the newVelocity values, like so: newSpeed *= (1-friction);.
And there we have it! Just give your platform a friction value of less than 1 and your box will be able to slide. If you're dealing with upright boxes, then the surface angle is PI for top wall, 0 for the bottom, PI/2 for the right and -PI/2 for the left wall.
2-The simpler option is to subtract gravity from the object's y-velocity in the solver's calculation.
I'm using the Core Location Framework from apple.
I need to know if CLLocationDirection (course of the GPS) is the way to determine whether the moving vehicle is turning left or right or going straight ? If so, how ?
If not, is there another feature of the framework better suited to identifying turns?
Any kind of help is appreciated.
As I said in the comments CLLocationDirection can work for this if you use it over time.
That said, it's not without issues. newHeading - oldHeading will be positive for right turns and negative for left turns but only when the two headings don't find them selves on either side of north.
Going from 355 to 5 should give a +10Deg (right turn). So you have a corner case to resolve.
The basic assumption you have to make is that the turn happened over the smaller angle. Which will be true if the data collection rate is reasonable and the car isn't tumbling over a cliff. If it is I doubt the passengers will care if the GPS gets confused.
objective-c might have a more elegant way to calculate this but my java polluted brain see's it as:
// Some test data
// deltaH newH oldH expected
// -350 = 5 - 355 should return +10
// -355 = 0 - 355 should return +5
// 5 = 5 - 0 should return +5
// -10 = 5 - 15 should return -10
// 10 = 15 - 5 should return 10
// -181 = 0 - 181 should return 179
// 181 = 181 - 0 should return -179
//
int deltaH = newH - oldH;
//Ensure deltaH takes the shortest path from oldH to newH
if ( -180 < deltaH && deltaH < 180 ) {
return deltaH;
} else if (deltaH <= -180) {
return deltaH + 360;
} else if (deltaH >= 180) {
return deltaH - 360;
} else {
throw new AssertionError("Logic error");
}
I'm sure there's a way translate that into objective-c.
Another issue is precision loss. If CLLocationDirection is calculated from a more raw data source, say GPS positional data, then it is very likely that whatever calculates CLLocationDirection is lossy. Meaning it should be possible to get more accurate results by going back to the raw data and calculating turn direction from that. When calculating derivatives this stuff becomes important.
To find if the point is on a specified line containing two points i do the following checks:
-(Boolean)isOnLine:(Line*) line point:(CGPoint) point{
//If between two dots:
if (((line.first.x <= point.x && point.x <= line.last.x)||(line.first.x >= point.x && point.x >= line.last.x))&&((line.first.y<=point.y && point.y<= line.last.y)||(line.first.y>=point.y && point.y>=line.last.y)) ) {
//Calculate distance:
double dist = (((double)point.y - line.first.y)) / (0.00001+((double)(point.x - line.first.x)))- ((double)(line.last.y - line.first.y)) / (0.00001+((double)(line.last.x - line.first.x)));
NSLog(#"Dist to line: %f", fabs(dist));
return fabs(dist) <0.5;
}else
return NO;
}
}
Somehow, however, the function is not working with vertical lines. My guess is the if clause is invalid in some sense.
I haven't read your code carefully so I'm not entirely sure what you're doing, but fyi the easiest way to do this operation is find the distance of one end of the line to the point, find the distance of the other end of the line to the point, and then add those distances and compare to the length of the line.
Something like:
Boolean isOnLine(line, point) {
var dist1 = dist(line.first, point)
var dist2 = dist(line.last, point)
return abs(line.length - (dist1 + dist2)) < .5
}
For the dist() function I'm guessing CoreGraphics provides that, but if not it's just basic trigonometry.
Here's my implementation of jhockings' solution
return abs([line length] -
(sqrt((line.first.x - point.x)*(line.first.x - point.x)
+ (line.first.y - point.y)*(line.first.y - point.y))
+ sqrt((line.last.x - point.x)*(line.last.x - point.x)
+ (line.last.y - point.y)*(line.last.y - point.y)))) < .5;
Another(my) implementation of #jhocking solution:
- (BOOL)isPoint:(CGPoint)origin nearToLineSegmentPointA:(CGPoint)pointA pointB:(CGPoint)pointB withMarginOfError:(CGFloat)marginOfError {
CGFloat distanceAP = [self distanceBetweenPointA:origin pointB:pointA];
CGFloat distanceBP = [self distanceBetweenPointA:origin pointB:pointB];
CGFloat distanceAB = [self distanceBetweenPointA:pointA pointB:pointB];
if (fabsf(distanceAB - distanceAP - distanceBP) < marginOfError) {
return YES;
} else {
return NO;
}
}
- (CGFloat)distanceBetweenPointA:(CGPoint)pointA pointB:(CGPoint)pointB {
return sqrtf(powf((pointA.x - pointB.x), 2.f) + powf((pointA.y - pointB.y), 2.f));
}
The explanation of why it is not working is you are comparing the tangent of the angles of two triangles - you are not calculating distance at all despite the comments and variable name.
Now as the angle approaches 90 deg the magnitude of the tangent increases rapidly until it reaches infinity at 90 degrees itself. At 90 degrees the difference of the x coordinates is zero and you would end up with a divide-by-zero error where it not for adding in the 0.00001 constant to avoid it. While the relative difference between two tangents near 90 might be small the absolute difference can be huge even for very close angles, so your < 0.5 test fails.
So you need another approach. One is to calculate the distances from the point to the two end points, and the length of the line itself, and compare - if the sum of the two distances from the point is larger than the length of the line the three points form a triangle, if it isn't they are co-linear. (And if the sum is less you've slipped into an alternate dimension...).
You can calculate the length of the lines using Pythagorus: sqrt((x1 - x2)^2 + (y1 - y2)^2).
I am testing a background-loop animation where there will be to images both 1024x768 pixels in dimension, move leftwards, go offscreen, then jump back to the other side, and repeat.
I was able to do this by creating a constant speed for both background image to move (successful), and then I tried the following code to make it jump, but there was a problem:
if((background.center.x) < -511){
background.center = CGPointMake(1536, background.center.y);
}
if((background2.center.x) < -511){
background2.center = CGPointMake(1536, background2.center.y);
}
Somehow this is not working the way I expected. It leaves a few pixels of gap every time, and I am confused why. Does anyone know what's causing this to happen and how to fix it? Thanks!
It seems like you have forgotten to take into account the distance moved. The greater than expression might have been triggered because you moved to far. I guess your movement is larger than 1 pixel/frame.
I am not sure what kind of values that are feeding your movement but I think to take into account the movement you should do something like...
if ((background.center.x) < -511){
CGFloat dist = background.center.x + 512;
background.center = CGPointMake(1536+dist, background.center.y);
}
if ((background2.center.x) < -511){
CGFloat dist = background2.center.x + 512;
background2.center = CGPointMake(1536+dist, background2.center.y);
}
Rather than have the two images move (sort of) independently, I would keep track of a single backgroundPosition variable and then constantly update the position of both images relative to that one position. This should keep everything nice and tidy:
CGFloat const backgroundWidth = 1024;
CGFloat const backgroundSpeed = 2;
- (void)animateBackground {
backgroundPosition -= backgroundSpeed;
if (backgroundPosition < 0) {
backgroundPosition += backgroundWidth;
}
background1.center.x = backgroundPosition - backgroundWidth/2;
background2.center.x = backgroundPosition + backgroundWidth/2;
}