14 Jun, 2009, Runter wrote in the 21st comment:
Votes: 0
Tyche said:
Quote
Hrm. arctan(len QP / len XP) wouldn't be atan(14, 14)

Did you mean len XQ instead of XP?


Yeah. I also meant the angle QXP instead, since XP isn't an angle. ;-)

You also have to express the coordinates in absolute differences, save the signs, and add or subtract the result from your origin.

Going from 3,3 to -10,-4
QP = 13 negative direction from origin
XQ = 7 negative direction from origin


Thanks Tyche!
Got it working great.
Here's the irb to replace my first one.

Quote
irb(main):002:0> a = [2.0, 5.0] # from
=> [2.0, 5.0]
irb(main):003:0> b = [24.0, 10.0] # to
=> [24.0, 10.0]
irb(main):004:0> at = Math::atan((b[0] - a[0])/(b[1] - a[1]))
=> 1.34731972565426
irb(main):005:0> c = a[0] + Math::sin(at) * distance, a[1] + Math::cos(at) * distance
=> [6.8756642789573, 6.10810551794484]


And as Tyche said. Some stuff has to be changed for directions based on direction moving.
14 Jun, 2009, David Haley wrote in the 22nd comment:
Votes: 0
Jamdog said:
Everyone seems to be missing the fact that Pythagoras' Theorem can be used to simply calculate the co-ordinates.

And you seem to have missed post #8. :rolleyes:

As for the general case, my preferred solution is to just use vectors; compute the proportion and then shift one point by the full vector multiplied by the proportion. The trig works too, although personally I find it far easier to remember the vector math than the trig, which I need to keep going back to the definitions for.
14 Jun, 2009, Runter wrote in the 23rd comment:
Votes: 0
David Haley said:
Jamdog said:
Everyone seems to be missing the fact that Pythagoras' Theorem can be used to simply calculate the co-ordinates.

And you seem to have missed post #8. :rolleyes:

As for the general case, my preferred solution is to just use vectors; compute the proportion and then shift one point by the full vector multiplied by the proportion. The trig works too, although personally I find it far easier to remember the vector math than the trig, which I need to keep going back to the definitions for.


I suspect the trig math might be lighter weight for computer instructions. Which was a concern. What say you?
14 Jun, 2009, Cratylus wrote in the 24th comment:
Votes: 0
On a related note, my favorite documentary.

-Crat
14 Jun, 2009, David Haley wrote in the 25th comment:
Votes: 0
Runter said:
David Haley said:
As for the general case, my preferred solution is to just use vectors; compute the proportion and then shift one point by the full vector multiplied by the proportion. The trig works too, although personally I find it far easier to remember the vector math than the trig, which I need to keep going back to the definitions for.


I suspect the trig math might be lighter weight for computer instructions. Which was a concern. What say you?

I kind of doubt it; how could it be lighter-weight than straight additions multiplications? Maybe the sqrt to find the vector norm is what you're worried about, although I'm not sure why that would be more or less expensive than the trig. Plus, the vector math uses one sqrt, whereas the trig uses one atan, one cos, one sin.

Still, there's an easy way to find out: this would be pretty straightforward to profile. Actually I'm kind of curious now, if you don't get to it by the time I get to my desktop, I'll give it a try…
14 Jun, 2009, Runter wrote in the 26th comment:
Votes: 0
Profile for:
100000.times do |i|
Math::sin(Math::atan(i/10))
Math::cos(Math::atan(i/10))
end


ruby -r profile bm.rb

% cumulative self self total
time seconds seconds calls ms/call ms/call name
49.52 4.11 4.11 1 4110.00 8300.00 Integer#times
28.55 6.48 2.37 200000 0.01 0.01 Math.atan
8.07 7.15 0.67 200000 0.00 0.00 Fixnum#/
4.94 7.56 0.41 200000 0.00 0.00 Fixnum#to_f
4.94 7.97 0.41 100000 0.00 0.00 Math.sin
3.98 8.30 0.33 100000 0.00 0.00 Math.cos
0.00 8.30 0.00 2 0.00 0.00 IO#set_encoding
0.00 8.30 0.00 1 0.00 8300.00 #toplevel

edit: Here's a profile just for distance formula.

def dist_form(x1, y1, x2, y2)
Math.sqrt( (x2 - x1)**2 + (y2 - y1)**2)
end

100000.times do |i|
dist_form(i, 10, 10, i)
end


ruby -r profile bm.rb
% cumulative self self total
time seconds seconds calls ms/call ms/call name
48.06 3.97 3.97 100000 0.04 0.07 Object#dist_form
19.01 5.54 1.57 200000 0.01 0.01 Fixnum#**
10.05 6.37 0.83 100000 0.01 0.01 Math.sqrt
9.81 7.18 0.81 1 810.00 8260.00 Integer#times
6.30 7.70 0.52 200000 0.00 0.00 Fixnum#-
4.00 8.03 0.33 100000 0.00 0.00 Fixnum#+
2.78 8.26 0.23 100000 0.00 0.00 Fixnum#to_f
0.00 8.26 0.00 1 0.00 0.00 Module#method_added
0.00 8.26 0.00 2 0.00 0.00 IO#set_encoding
0.00 8.26 0.00 1 0.00 8260.00 #toplevel
14 Jun, 2009, David Haley wrote in the 27th comment:
Votes: 0
If I'm reading that output correctly, it's saying that the two are more or less the same, right?
14 Jun, 2009, Runter wrote in the 28th comment:
Votes: 0
David Haley said:
If I'm reading that output correctly, it's saying that the two are more or less the same, right?


That's what I'm getting out of it. Negligible in any case in Ruby. The method call in the second example seems to dwarf the actual code ran.
14 Jun, 2009, Runter wrote in the 29th comment:
Votes: 0
require "inline"
class MyTest
inline do |builder|
builder.c "
int dist_form(int x1, int y1, int x2, int y2) {
return sqrt( (double)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) );
}"
end
end

t = MyTest.new

100000.times do |i|
t.dist_form(i, 10, 10, i)
end


Using C in ruby inline from similar code for distance formula I'm getting:

% cumulative self self total
time seconds seconds calls ms/call ms/call name
67.55 1.02 1.02 1 1020.00 1300.00 Integer#times
18.54 1.30 0.28 100000 0.00 0.00 MyTest#dist_form
4.64 1.37 0.07 54 1.30 6.30 Kernel.require
1.99 1.40 0.03 230 0.13 0.17 String#gsub!
1.32 1.42 0.02 1099 0.02 0.02 Module#method_added
0.66 1.43 0.01 90 0.11 0.11 Array#include?
0.66 1.44 0.01 485 0.02 0.02 BasicObject#singleton_method_added
0.66 1.45 0.01 30 0.33 1.33 Array#each
0.66 1.46 0.01 161 0.06 0.06 Kernel.dup
0.66 1.47 0.01 66 0.15 0.15 IO#set_encoding
0.66 1.48 0.01 47 0.21 0.21 Kernel.freeze
0.66 1.49 0.01 4 2.50 2.50 Inline.rootdir

Which looks a lot better.
14 Jun, 2009, Runter wrote in the 30th comment:
Votes: 0
require "inline"
class MyTest
inline do |builder|
builder.c "
/* right number of calls anyways */
int trigcalls(double d1) {
return sin(atan(d1/10)) + cos(atan(d1/10));
}"
end
end

t = MyTest.new

100000.times do |i|
t.trigcalls(i)
end


ruby -rprofile inline2.rb
% cumulative self self total
time seconds seconds calls ms/call ms/call name
57.69 0.90 0.90 1 900.00 1350.00 Integer#times
28.85 1.35 0.45 100000 0.00 0.00 MyTest#trigcalls
3.85 1.41 0.06 54 1.11 5.74 Kernel.require
1.28 1.43 0.02 29 0.69 1.38 Array#each
1.28 1.45 0.02 230 0.09 0.09 String#gsub!
1.28 1.47 0.02 161 0.12 0.12 Kernel.dup
0.64 1.48 0.01 11 0.91 0.91 File#join
0.64 1.49 0.01 27 0.37 0.37 YAML.tag_class
0.64 1.50 0.01 21 0.48 0.48 Gem::Specification#attribute
0.64 1.51 0.01 2 5.00 5.00 Enumerable.sort_by
0.64 1.52 0.01 226 0.04 0.13 RbConfig.expand
0.64 1.53 0.01 40 0.25 0.25 Module#private_class_method
0.64 1.54 0.01 20 0.50 0.50 Module#include
0.64 1.55 0.01 60 0.17 0.17 Kernel.object_id
0.00 1.55 0.00 1 0.00 0.00 Inline::C#c2ruby


Just in case someone was interested in the other ruby inline performance.
14 Jun, 2009, Sandi wrote in the 31st comment:
Votes: 0
All of which is why I'm a proponent of using vectors rather than Cartesian space for modeling location.
14 Jun, 2009, Runter wrote in the 32nd comment:
Votes: 0
Sandi said:
All of which is why I'm a proponent of using vectors rather than Cartesian space for modeling location.


Explain for a noob like me? :)
14 Jun, 2009, David Haley wrote in the 33rd comment:
Votes: 0
Not sure I follow either. A point in 2d space and a vector are basically interchangeable.
15 Jun, 2009, flumpy wrote in the 34th comment:
Votes: 0
Runter said:
Both David and Tyche posted code that works in all cases given a vector.


Aagggh in my skim reading stupor I had fallaciously assumed that David was solving the problem using trig. I hadn't read it all properly!!

That'll teach me.
20.0/34