// if it's on the inside of the ring, in circle. // if it's on the outside of the ring, standard collision class CollideWithRing extends UnaryForce{ Vector3D position; float diameter, thickness; float SQRT_2 = sqrt(2); CollideWithRing(ParticleSystem s, Vector3D p, float d, float t){ super(s,1); position = p; diameter = d; thickness = t; } void apply(){ Vector3D a2b = a.position().copy().subtract(position); float a2bDistance = a2b.length(); if( a2bDistance < diameter*0.5 ){ inRing(); } else{ outRing(); } } void inRing(){ float maxDist = ( (diameter-thickness) - a.size())*0.5; float bounded = (diameter-thickness)/(2*SQRT_2); float maxDistSq = bounded - a.size()*0.5; //test if bounding box of point is outside of bounded box of circle if( Math.abs( a.position().x() - position.x() ) < maxDistSq && Math.abs( a.position().y() - position.y() ) < maxDistSq ) return; Vector3D a2b = a.position().copy().subtract(position); float a2bDistance = a2b.length(); if( a2bDistance < maxDist ) return; if( a2bDistance == 0 ){ a2b.set( (new Vector3D((float)Math.random(), (float)Math.random(), 0)).unit() ); } else{ a2b.divide(a2bDistance); } float force = (maxDist - a2bDistance); a2b.multiply(force); // add on the forces addForce( a2b ); } void outRing(){ float maxDist = (a.size() + (diameter+thickness))*0.5f; if( Math.abs( a.position().x() - position.x()) > maxDist ) return; if( Math.abs( a.position().y() - position.y()) > maxDist ) return; Vector3D a2b = a.position().copy().subtract(position); float a2bDistance = a2b.length(); if( a2bDistance > maxDist ) return; if( a2bDistance == 0 ){ a2b.set( (new Vector3D((float)Math.random(), (float)Math.random(), 0)).unit() ); } else{ a2b.divide(a2bDistance); } float force = (maxDist - a2bDistance); a2b.multiply(force); // add on the forces addForce( a2b ); } }