eric256 has asked for the wisdom of the Perl Monks concerning the following question:
I've been fighting with it for a while now. Basicaly I just want the springs to dampen out gradualy so that they don't ossiclate forever. Unfortunatly the physics math is over my head and trying to add a dampening force to Physics::Springs just gave me a headache and some pretty amazing images. So here is a Tk app that generates springs. Left click to place a massive immobile node, then middle click a fair distance away to put a light weight particle attatched to it by a spring. The spring has a desired length of 50 and k=1. Unless you get the second particle very nery the target distance of 50 the bounce increases every occilation. I've tried different variations of k and mass, but I think I realy need to figure out how to add the dampening feild. Any help would be appreciated.
use strict; use warnings; use Tk; use Tk::WorldCanvas; use Physics::Springs; my $sim = Physics::Springs->new(); use Data::Dumper; my $mw = MainWindow->new(); my $worldcanvas = $mw->WorldCanvas(-width=>400,-height=>400); my $i = 1; $worldcanvas->configure(-bandColor => 'purple'); $worldcanvas->CanvasBind('<3>' => sub {$worldcanvas->Can +vasFocus; $worldcanvas->rub +berBand(0) }); my $spring_start = undef; + $worldcanvas->CanvasBind('<1>' => sub { my ($x,$y) = $worldcanvas->eventLocation; my $name = "Sun_" . $i++; print "Inserting at $name ($x,$y)\n"; $worldcanvas->createOval( $x-5,$y-5,$x+5,$y+5, -fill=>'yellow' +, -tag=> $name); my $spring_end = $sim->add_particle( x=> $x, y=> $y, z=>0, xv +=> 1, yv => 0, m=>10_000, n => $name); $sim->add_spring(k=>1,p1=>$spring_start, p2=>$spring_end,l=>un +def) if defined $spring_start; $spring_start = $spring_end; } ); $worldcanvas->CanvasBind('<2>' => sub { my ($x,$y) = $worldcanvas->eventLocation; my $name = "Vertex_" . $i++; print "Inserting at $name ($x,$y)\n"; $worldcanvas->createOval( $x-5,$y-5,$x+5,$y+5, -fill=>'red', - +tag=> $name); my $spring_end = $sim->add_particle( x=> $x, y=> $y, z=>0, xv +=> 1, yv => 0, m=>50, n => $name); $sim->add_spring(k=>1,p1=>$spring_start, p2=>$spring_end, l=>5 +0) if defined $spring_start; $spring_start = $spring_end; } ); $worldcanvas->CanvasBind('<B3-Motion>' => sub {$worldcanvas->rub +berBand(1)}); $worldcanvas->CanvasBind('<ButtonRelease-3>' => sub {my @box = $worldc +anvas->rubberBand(2); my @ids = $worldc +anvas->find('enclosed', @box); foreach my $id (@ +ids) {$worldcanvas->delete($id)} }); $worldcanvas->CanvasBind('<Up>' => sub {$worldcanvas->rubberBand(1);}) +; $worldcanvas->CanvasBind('<Down>' => sub {$worldcanvas->rubberBand(1); +}); $worldcanvas->CanvasBind('<Left>' => sub {$worldcanvas->rubberBand(1); +}); $worldcanvas->CanvasBind('<Right>' => sub {$worldcanvas->rubberBand(1) +;}); $worldcanvas->CanvasBind('<i>' => sub {$worldcanvas->zoom(1.25); $worl +dcanvas->rubberBand(1);}); $worldcanvas->CanvasBind('<o>' => sub {$worldcanvas->zoom(0.8); $worl +dcanvas->rubberBand(1);}); $worldcanvas->pack(); $worldcanvas->CanvasFocus; $worldcanvas->repeat(100, sub { $sim->iterate_step(1); foreach my $p (@{ $sim->{p} }) { $worldcanvas->coords($p->{n}, $p->{x} - 5 , $p->{y} - + 5, $p->{x} + 5 , $p->{y} + 5 ); } foreach my $spring (@{$sim->{_PhSprings_springs}}) { my $p1 = $sim->{p}[$spring->{p1}]; my $p2 = $sim->{p}[$spring->{p2}]; my $spring_name = 'spring_' . $spring; if ($worldcanvas->find('withtag',$spring_name)) { $worldcanvas->coords($spring_name, $p1->{x}, $p1-> +{y}, $p2->{x}, $p2->{y}); #print "$spring_name ", $spring->{strech}, "\n"; } else { $worldcanvas->createLine($p1->{x}, $p1->{y}, $p2-> +{x}, $p2->{y}, -tag=>$spring_name); } } }); MainLoop;
The code for dampening almost certainly has to go in the spring modules iterate function, somewhere around the followwing:
foreach my $spring (@{$self->{_PhSprings_springs}}) { my $p1 = $self->{p}[$spring->{p1}]; my $p2 = $self->{p}[$spring->{p2}]; my $l = $spring->{len}; my $k = $spring->{k}; my $dist = sqrt( ( ($p1->{x} - $p2->{x}) )**2 + ( ($p1->{y} - $p2->{y}) )**2 + ( ($p1->{z} - $p2->{z}) )**2 ); my $force1 = $k * ($dist-$l); my $force2 = -$force1; my $dx = ($p2->{x} - $p1->{x}) / $dist; my $dy = ($p2->{y} - $p1->{y}) / $dist; my $dz = ($p2->{z} - $p1->{z}) / $dist; $p1->{_fx} += $force1 * $dx; $p1->{_fy} += $force1 * $dy; $p1->{_fz} += $force1 * $dz; $p2->{_fx} += $force2 * $dx; $p2->{_fy} += $force2 * $dy; $p2->{_fz} += $force2 * $dz; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Adding a dampening force to Physics::Springs
by Anonymous Monk on Aug 29, 2006 at 13:58 UTC | |
by eric256 (Parson) on Aug 29, 2006 at 15:00 UTC | |
|
Re: Adding a dampening force to Physics::Springs
by eric256 (Parson) on Aug 29, 2006 at 17:46 UTC |