[Bprocessor-commit] bprocessor/src/net/sourceforge/bprocessor/packages/physics PhysicsSurface.java
Status: Pre-Alpha
Brought to you by:
henryml
|
From: Sebastian G. <sg...@us...> - 2011-05-16 06:11:07
|
Update of /cvsroot/bprocessor/bprocessor/src/net/sourceforge/bprocessor/packages/physics
In directory vz-cvs-2.sog:/tmp/cvs-serv11353/src/net/sourceforge/bprocessor/packages/physics
Added Files:
PhysicsSurface.java PhysicsNet.java PhysicsPlane.java
PhysicsSpring.java PhysicsParticle.java PhysicsPackage.java
Log Message:
Hanging Chain Tools, Volume Calc
--- NEW FILE: PhysicsSpring.java ---
package net.sourceforge.bprocessor.packages.physics;
import net.sourceforge.bprocessor.model.Vertex;
//import net.sourceforge.bprocessor.model.plugin.PhysicsParticle;
public class PhysicsSpring {
//properties
PhysicsParticle pA; //Particle at one end of the spring
PhysicsParticle pB; //Particle at other end of the spring
double startL; //original starting length of Spring (generated from b-net)
double eql; //equilibrium length of the spring
double l; //actual length of the spring
double lLast; //last length of the spring
double c; //spring constant
double sf; //force value
double sf_damped; //force value
double restLengthFactor;//global factor - eql length in relation to cNet edge length
double restLengthScale; //local scaling of restlength (unique to spring)
Vertex fA; //force of the spring acting on Particle A
Vertex fB; //force of the spring acting on Particle B
//Constructor
PhysicsSpring(PhysicsParticle pA, PhysicsParticle pB, double eql, double c) {
this.pA = pA;
this.pB = pB;
this.eql = eql;
this.c = c;
this.l = getLength();
this.startL = this.l;
lLast = l;
sf = 0;
sf_damped = 0;
fA = new Vertex(0,0,0);
fB = new Vertex(0,0,0);
pA.connectSpring(this);
pB.connectSpring(this);
sf=0;
sf_damped = 0;
restLengthScale = 1.0;
}
//compute current length of spring
double getLength() {
double sl;
sl = pA.pos.distance(pB.pos);
return sl;
}
//compute current damping factor
double calcDamping(double time, double spring_damping) {
double damping;
//damping = v * spring_d = (distance / time) * spring_d
damping = (l-lLast)*spring_damping / time;
lLast = l;
return damping;
}
//compute spring force
void calcForce(double time, double spring_damping) {
sf = (l-(eql*restLengthFactor*restLengthScale))*c;
sf_damped = sf + calcDamping(time, spring_damping);
//get Vector from A to B and vice versa
fA = pB.pos.minus(pA.pos);
fB = pA.pos.minus(pB.pos);
//normalize force Vectors
fA.normalize();
fB.normalize();
//scale force Vectors to force value
fA.scaleIt(sf_damped);
fB.scaleIt(sf_damped);
}
void update(double time, double spring_damping) {
l = getLength();
calcForce(time, spring_damping);
}
}
--- NEW FILE: PhysicsParticle.java ---
package net.sourceforge.bprocessor.packages.physics;
import net.sourceforge.bprocessor.model.Vertex;
import java.util.*;
public class PhysicsParticle {
//properties
Vertex pos; //position
Vertex nPos; // new position
Vertex vel; //velocity
Vertex a; //acceleration
double m; //mass
Vertex f; //force acting on particle
boolean fix; //fix or movable particle?
int ID; //Particle ID for identification
Vertex aForce; //additional force - sum of other calculations. Is added to acceleration calculation.
Vertex lastPos; //last position of vertex
ArrayList<PhysicsSpring> springs = new ArrayList(); //springs connected to particle
//constructor
PhysicsParticle (Vertex node, Vertex velocity, Vertex acceleration, double mass, int ID) {
pos = node;
vel = velocity;
a = acceleration;
m = mass;
fix = node.isCorner();
nPos = new Vertex(pos.getX(),pos.getY(),pos.getZ());
this.ID = ID;
aForce = new Vertex(0,0,0);
lastPos = nPos;
}
//add a spring connected to Particle
void connectSpring(PhysicsSpring s) {
springs.add(s);
}
//add force
void addForce(Vertex force) {
aForce = aForce.add(force);
}
//calculate acceleration
void calcAcc(double gravity, double particle_drag) {
f = new Vertex(0,0,0);
//spring forces
for (int i = 0; i<springs.size(); i++) {
PhysicsSpring s = (PhysicsSpring) springs.get(i);
//check paricles of force
if (ID == s.pA.ID) {
f=f.add(s.fA);
}
else {
f=f.add(s.fB);
}
}
//gravity
f = f.add(new Vertex(0,0,gravity*m));
//any other force
f = f.add(aForce);
aForce = new Vertex(0,0,0);
//coefficient of drag, damping
//f = v * -coefficient of damping
f = f.add(vel.scale(-1*particle_drag));
//acceleration
a=f.scale(1.0/m);
}
//move particle
void move(double time, double gravity, double particle_drag) {
if ((fix == false) && (pos.isCorner() != true)) {
nPos = new Vertex(pos.getX(),pos.getY(),pos.getZ());
//calculate acceleration
calcAcc(gravity, particle_drag);
//calculate new position
//pos new = pos old + vel * time + 0.5 * acceleration * time * time
nPos = nPos.add(vel.scale(time));
nPos = nPos.add(a.scale(0.5*time*time));
//calculate new velocity
//vel = acceleration * time
vel = vel.add(a.scale(time));
lastPos = nPos;
}
}
}
--- NEW FILE: PhysicsSurface.java ---
package net.sourceforge.bprocessor.packages.physics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.*;
import com.sun.net.ssl.internal.ssl.Debug;
import net.sourceforge.bprocessor.model.Edge;
import net.sourceforge.bprocessor.model.Space;
import net.sourceforge.bprocessor.model.Vertex;
import net.sourceforge.bprocessor.model.Surface;
public class PhysicsSurface {
Surface bSurf; //the original bNet Surface
PhysicsPlane avPlane; //average Plane of Surface
HashMap<Vertex,PhysicsParticle> particles = new HashMap(); //maps the surface vertices to the corresponding particles
HashMap<Edge,PhysicsSpring> springs = new HashMap(); //maps the surface edges to the corresponding springs
HashMap<Vertex, Double> lastPlaneDist = new HashMap(); //maps the surface vertices to their last average plane distance
double lastLength;
double lastDiaLength;
//constructors
PhysicsSurface (Surface bNetSurface, HashMap<Vertex,PhysicsParticle> VPmap, HashMap<Edge,PhysicsSpring> ESmap) {
bSurf = bNetSurface;
particles = VPmap;
springs = ESmap;
List<Edge> edges = bSurf.getEdges();
//get current average length
double l = 0;
for (Edge e : edges) {
l += e.getLength();
}
l = l/edges.size();
lastLength = l;
//get current average diagonal length
double dl = 0;
List<Vertex> vertices = bSurf.getVertices();
if (vertices.size() == 4) {
dl = vertices.get(0).distance(vertices.get(2)) + vertices.get(1).distance(vertices.get(3));
dl = dl / 2;
}
lastDiaLength = dl;
for (Vertex v : vertices) {
lastPlaneDist.put(v,new Double(0));
}
}
void equalizeEdges(double time, double spring_constant, double damping) {
List<Edge> edges = bSurf.getEdges();
//get average (desired) edge length
double l = 0;
for (Edge e : edges) {
l += e.getLength();
}
l = l/edges.size();
for (Edge e : edges) {
//calculate force on particles using spring equation incl. damping
double sf = (l-e.getLength())*spring_constant;
sf = sf + ((l-lastLength)*damping / time);
lastLength = l;
//get Vector from A to B and vice versa
Vertex fB = e.getTo().minus(e.getFrom());
Vertex fA = e.getFrom().minus(e.getTo());
//normalize force Vectors
fA.normalize();
fB.normalize();
//scale force Vectors to force value
fA.scaleIt(sf);
fB.scaleIt(sf);
//add forces to corresponding particles
PhysicsParticle pA = particles.get(e.getFrom());
PhysicsParticle pB = particles.get(e.getTo());
pA.addForce(fA);
pB.addForce(fB);
}
}
Vertex averageNormal() {
bSurf.calcNormals();
return bSurf.normal();
/*
//* @Michael: algorithm for Normal seems to be so complicated... why?
Vertex nV = new Vertex(0,0,0);
List<Vertex> vertices = bSurf.getVertices();
double num = vertices.size();
if (num>3) {
//if surface has more than 3 vertices
//add first two vertices to the end of the list for loop
vertices.add(vertices.get(0));
vertices.add(vertices.get(1));
for (int i=0; i<num; i++) {
Vertex a = vertices.get(0).minus(vertices.get(1));
Vertex b = vertices.get(2).minus(vertices.get(1));
Vertex n = a.cross(b);
n.normalize();
nV = nV.add(n);
}
nV.normalize();
}
if (num == 3) {
//surface is triangular - there is only one normal
Vertex a = vertices.get(0).minus(vertices.get(1));
Vertex b = vertices.get(2).minus(vertices.get(1));
nV = nV.add(a.cross(b));
//nV = nV.scale(1/3);
nV.normalize();
}
return nV;
*/
}
double calcArea() {
double area = 0.0;
List<Vertex> vertices = bSurf.getVertices();
double num = vertices.size();
vertices.add(vertices.get(0));
List<Vertex> crossProducts = new ArrayList<Vertex>();
for (int i=0; i<num; i++) {
Vertex p1 = vertices.get(i);
Vertex p2 = vertices.get(i+1);
Vertex cP = p1.cross(p2);
crossProducts.add(cP);
}
Vertex sum = new Vertex(0,0,0);
for (Vertex cP : crossProducts) {
sum = sum.add(cP);
}
double dotP;
dotP = Math.abs(averageNormal().dot(sum));
area = 0.5 * dotP;
return area;
}
void normalForce(Space guides, double time, double force) {
List<Vertex> vertices = bSurf.getVertices();
Vertex n = averageNormal();
n.normalize();
n = n.scale(force);
//display force vector
Vertex c = bSurf.center();
Edge eA = new Edge(c,c.add(n));
guides.add(eA);
for (Vertex v : vertices) {
//get corresponding Particle
PhysicsParticle pA = particles.get(v);
//add force to particle
pA.addForce(n);
}
}
void planarize(Space guides, double time, double spring_constant, double spring_damping) {
if (spring_constant!=0) {
List<Vertex> vertices = bSurf.getVertices();
avPlane = new PhysicsPlane(averageNormal(),bSurf.center()); //vertices.get(0));
for (Vertex v : vertices) {
//get corresponding Particle
PhysicsParticle pA = particles.get(v);
//get vector to average plane
Vertex nV = avPlane.PointNormalToPlane(v);
//calculate spring force and damping
double pl = nV.length();
double lastPl = (double) lastPlaneDist.get(v);
double sf = (pl)*spring_constant;
sf = sf + ((pl-lastPl)*spring_damping / time);
//save current length for next calculation
lastPlaneDist.put(v, new Double(pl));
//add force to particle
nV.normalize();
nV = nV.scale(sf);
pA.addForce(nV);
//display force vector
Edge eA = new Edge(v,avPlane.PointProjectToPlane(v));
guides.add(eA);
}
}
}
void quadToRect(Space guides, double time, double spring_constant, double spring_damping) {
//make a quad surface rectangular by equalizing the length of both diagonals
List<Vertex> vertices = bSurf.getVertices();
//these forces are only applied if surface is quad
if (vertices.size() == 4) {
//create List of diagonals
ArrayList<Edge> dEdges = new ArrayList<Edge>();
Edge eA = new Edge(vertices.get(0), vertices.get(2));
guides.add(eA);
dEdges.add(eA);
Edge eB = new Edge(vertices.get(1), vertices.get(3));
guides.add(eB);
dEdges.add(eB);
//get average diagonal length
double dl = (eA.getLength() + eB.getLength()) / 2;
//add spring forces to diagonals
for (Edge e : dEdges) {
//calculate force on particles using spring equation incl. damping
double sf = (dl-e.getLength())*spring_constant;
sf = sf + ((dl-lastDiaLength)*spring_damping / time);
lastDiaLength = dl;
//get Vector from A to B and vice versa
Vertex fB = e.getTo().minus(e.getFrom());
Vertex fA = e.getFrom().minus(e.getTo());
//normalize force Vectors
fA.normalize();
fB.normalize();
//scale force Vectors to force value
fA.scaleIt(sf);
fB.scaleIt(sf);
//add forces to corresponding particles
PhysicsParticle pA = particles.get(e.getFrom());
PhysicsParticle pB = particles.get(e.getTo());
pA.addForce(fA);
pB.addForce(fB);
}
}
}
}
--- NEW FILE: PhysicsPackage.java ---
package net.sourceforge.bprocessor.packages.physics;
import net.sourceforge.bprocessor.gl.Editor;
import net.sourceforge.bprocessor.gl.tool.AbstractTool;
import net.sourceforge.bprocessor.model.Command;
import net.sourceforge.bprocessor.model.Edge;
import net.sourceforge.bprocessor.model.Geometric;
import net.sourceforge.bprocessor.model.Item;
import net.sourceforge.bprocessor.model.Operation;
import net.sourceforge.bprocessor.model.Space;
import net.sourceforge.bprocessor.model.Vertex;
import net.sourceforge.bprocessor.model.Surface;
import net.sourceforge.bprocessor.model.plugin.NetCommand;
import net.sourceforge.bprocessor.packages.physics.PhysicsNet;
import net.sourceforge.bprocessor.packages.skeleton.SkeletonPackage.SkeletonTool;
import java.awt.event.MouseEvent;
import java.util.*;
/*
* To Do
* Michael:
* parameters additional parameters should be saved when added, change function , the display of the value is not automatically updated.
* Plugin Parameters and Selection Parameters: they should not be displayed in the same panel. Rather split the existing panel. So there can be a selection and a tool running at the same time and all information is visible.
* Sliders, Checkboxes, etc. for the plugin controls
* A plugin button should be able to run a tool with a selection / mouse interaction.
*
* Modify new net while simulation is running, i.e. corner property, etc.
* Planarity and regularity of panels, add bending stiffness!
* Rectangularity needs improvement, bending stiffness!
* Add parameters to b-net and save them! - see above, Michael, add and save parameters to original net
* Subdivision
* Selection => parameter changes to vertices and edges, not only global
* Volume calculation and inflation force
* Auto-detect corners of net (vertices that are only connected to 2 edges)
* time settings and parameters
*/
public class PhysicsPackage {
public static class Springsystem extends NetCommand {
private physicsChangeSpringTool changeSpringTool;
private physicsChangeWeightTool changeWeightTool;
Space union; //Union containing Objects created by script
Space cNet; //copy of b-Net, graphical representation of Physics Net
PhysicsNet pN; //Physics Net = Simulation Object
HashMap<Edge, Edge> edges = new HashMap();
HashMap<Vertex, Vertex> vertices = new HashMap();
//parameters
double gravity;
double mass;
double pDamp;
double cDamp;
double restLengthFactor;
double springConstant;
double equalConstant;
double equalDamping;
double rectConstant;
double rectDamping;
double planeConstant;
double planeDamping;
//double normalForce;
double volume;
//boolean editNet;
public void initialize(Space net) {
//parameters
gravity = -9.81;
parameters.put("Gravity [m/s2]", gravity);
mass = 1;
parameters.put("Particle Mass [kg]", mass);
pDamp = 2.0;
parameters.put("Particle Damping [N sec/m]",pDamp);
cDamp = 2.0;
parameters.put("Spring Damping [N sec/m]",cDamp);
restLengthFactor = 0.5;
parameters.put("Spring Restlength Factor",restLengthFactor);
springConstant = 20.0;
parameters.put("Spring Constant c [N/m]",springConstant);
equalConstant = 0.0;
parameters.put("Equal Edges Spring Constant ec [N/m]",equalConstant);
equalDamping = 2.0;
parameters.put("Equal Edges Damping [N sec/m]", equalDamping);
rectConstant = 0.0;
parameters.put("Equal Diagonals Spring Constant rc [N/m]",rectConstant);
rectDamping = 2.0;
parameters.put("Equal Diagonals Damping [N sec/m]", rectDamping);
planeConstant = 0.0;
parameters.put("Planarity Spring Constant pc [N/m]",planeConstant);
planeDamping = 2.0;
parameters.put("Planarity Damping [N sec/m]", planeDamping);
//normalForce = 0.0;
//parameters.put("Normal Surface Force [N]", normalForce);
volume = 1.0;
parameters.put("Volume [m3]", volume);
//editNet = true;
//parameters.putBoolean("Edit B-Net", editNet);
super.initializeNoItem(net);
//create copy of b-Net
Map map = new HashMap();
//map = net.getOwnParameters();
cNet = net.copy(map);
cNet.setName(net.getName()+"- Physics Net");
//cNet.edit();
//copy corner points
Collection<Vertex> nVertices = net.getVertices();
Collection<Vertex> cVertices = cNet.getVertices();
for (Vertex nV : nVertices) {
for (Vertex cV : cVertices) {
if (nV.coincides(cV)) {
cV.setCorner(nV.isCorner());
vertices.put(nV,cV);
}
}
}
//create Edges HashMap
Collection<Edge> nEdges = net.getEdges();
Collection<Edge> bEdges = cNet.getEdges();
for (Edge nE : nEdges) {
for (Edge cE : bEdges) {
if (nE.equivalent(cE)) {
edges.put(nE,cE);
}
}
}
//create physics Net
pN = new PhysicsNet(cNet, gravity, springConstant, cDamp, pDamp, mass, restLengthFactor);
//tools
changeSpringTool = new physicsChangeSpringTool(cNet,pN,edges);
parameters.put("Change Spring Restlength", new Operation() {
@Override
public void perform() {
System.out.println("activate tool");
cNet.edit();
Editor.instance().changeTool(changeSpringTool);
}
});
changeWeightTool = new physicsChangeWeightTool(pN);
parameters.put("Change Particle Weight", new Operation() {
@Override
public void perform() {
System.out.println("activate tool");
cNet.edit();
Editor.instance().changeTool(changeWeightTool);
}
});
}
public void evaluate() {
//remove all elements of last iteration
//clear();
//////////////////////////////////////////////////////////////////
//get changed parameters
//gravity
gravity = (Double) parameters.getDouble("Gravity [m/s2]");
pN.gravity = gravity;
//particle Mass
double oldMass = mass;
mass = (Double) parameters.getDouble("Particle Mass [kg]");
if (mass!=oldMass) {
pN.updateMass(mass);
}
//particle Damping
pDamp = (Double) parameters.getDouble("Particle Damping [N sec/m]");
pN.particle_d =pDamp;
//spring damping
cDamp = (Double) parameters.getDouble("Spring Damping [N sec/m]");
pN.spring_d = cDamp;
//spring restlength factor
restLengthFactor = (Double) parameters.getDouble("Spring Restlength Factor");
//spring constant
Double oldSpringConstant = springConstant;
springConstant = (Double) parameters.get("Spring Constant c [N/m]");
if (oldSpringConstant!=springConstant) {
pN.updateSpringConstant(springConstant);
}
//equal edges parameters
equalConstant = (Double) parameters.get("Equal Edges Spring Constant ec [N/m]");
equalDamping = (Double) parameters.get("Equal Edges Damping [N sec/m]");
//rectangular quads parameters
rectConstant = (Double) parameters.get("Equal Diagonals Spring Constant rc [N/m]");
rectDamping = (Double) parameters.get("Equal Diagonals Damping [N sec/m]");
//Planarity
planeConstant = (Double) parameters.get("Planarity Spring Constant pc [N/m]");
planeDamping = (Double) parameters.get("Planarity Damping [N sec/m]");
//normal Force
//normalForce = (Double) parameters.get("Normal Surface Force [N]");
//boolean parameters
//editNet = (Boolean) parameters.getBoolean("Edit B-Net");
//Desired Volume
volume = (Double) parameters.get("Volume [m3]");
/////////////////////////////////////////////////////////////////////////////////////////////
//track changes of bNet and modify Physics Net accordingly
//update vertices
Collection<Vertex> bVertices = net.getVertices();
for (Vertex bV : bVertices) {
if (bV.isCorner()) {
Vertex pV = vertices.get(bV);
pV.setX(bV.getX());
pV.setY(bV.getY());
pV.setZ(bV.getZ());
pN.updatePos(pV);
}
}
//update edges
Collection<Edge> bEdges = net.getEdges();
for (Edge bE : bEdges) {
pN.updateRestLength(edges.get(bE), bE.getLength());
pN.setRestLengthFactor(edges.get(bE), restLengthFactor);
}
//add a union space containing all new elements
union = (Space) net.getOwner().find("PhysicsSystem");
//check if space was already created
if (union == null) {
union = Item.createUnion("PhysicsSystem");
net.getOwner().add(union);
} else {
union.clear();
}
//add guidelines
Space guides = Item.createUnion("Guidelines");
union.add(guides);
//change p-net
/*if (editNet) {
net.edit();
} else {
cNet.edit();
}*/
pN.update(guides, 0.02, equalConstant, equalDamping, rectConstant, rectDamping, planeConstant, planeDamping, volume);
union.add(cNet);
}
public String title() {
return "Springsystem";
}
}
public PhysicsPackage() {
Command.register(Springsystem.class);
}
//Tool
public static class physicsChangeSpringTool extends AbstractTool {
Space cNet; //copy of b-Net, graphical representation of Physics Net
PhysicsNet pN; //Physics Net = Simulation Object
HashMap<Edge, Edge> edges = new HashMap();
public physicsChangeSpringTool() {
// TODO Auto-generated constructor stub
}
public physicsChangeSpringTool(Space cNet, PhysicsNet pN, HashMap<Edge, Edge> edges) {
this.cNet = cNet;
this.pN = pN;
this.edges = edges;
}
@Override
protected void dragged(MouseEvent event) {
// TODO Auto-generated method stub
}
@Override
protected void moved(MouseEvent event) {
findTarget(event);
if (target instanceof Geometric) {
if (target instanceof Surface) {
editor.getView().makeTarget(target);
}
if (target instanceof Edge) {
editor.getView().makeTarget(target);
}
}
}
@Override
protected void pressed(MouseEvent event) {
findTarget(event);
if (target instanceof Geometric) {
if (target instanceof Surface) {
editor.getView().makeTarget(target);
Surface bS = (Surface) target;
Collection<Edge> bEdges = bS.getEdges();
for (Edge bE : bEdges) {
pN.scaleRestLengthFactor(bE, 1.1);
}
}
if (target instanceof Edge) {
editor.getView().makeTarget(target);
Edge bE = (Edge) target;
pN.scaleRestLengthFactor(bE, 1.1);
}
}
}
@Override
protected void released(MouseEvent event) {
// TODO Auto-generated method stub
}
}
public static class physicsChangeWeightTool extends AbstractTool {
PhysicsNet pN; //Physics Net = Simulation Object
public physicsChangeWeightTool() {
// TODO Auto-generated constructor stub
}
public physicsChangeWeightTool(PhysicsNet pN) {
this.pN = pN;
}
@Override
protected void dragged(MouseEvent event) {
// TODO Auto-generated method stub
}
@Override
protected void moved(MouseEvent event) {
findTarget(event);
if (target instanceof Geometric) {
if (target instanceof Vertex) {
editor.getView().makeTarget(target);
}
}
}
@Override
protected void pressed(MouseEvent event) {
findTarget(event);
if (target instanceof Geometric) {
if (target instanceof Vertex) {
editor.getView().makeTarget(target);
Vertex bV = (Vertex) target;
pN.scaleParticleMass(bV,1.2);
}
}
}
@Override
protected void released(MouseEvent event) {
// TODO Auto-generated method stub
}
}
}
--- NEW FILE: PhysicsNet.java ---
package net.sourceforge.bprocessor.packages.physics;
import java.util.*;
import net.sourceforge.bprocessor.model.Edge;
import net.sourceforge.bprocessor.model.ParameterBlock;
import net.sourceforge.bprocessor.model.Space;
import net.sourceforge.bprocessor.model.Vertex;
import net.sourceforge.bprocessor.model.Surface;
public class PhysicsNet {
//properties
Space cNet;
double gravity = -9.81;
double globalParticleMass = 1.0;
double spring_c = 4.4; //spring constant
double spring_d = 0.5; //spring damping
double particle_d = 3; //particle damping coefficient of drag
boolean solid = false;
HashMap<Vertex,PhysicsParticle> particles = new HashMap();
HashMap<Edge,PhysicsSpring> springs = new HashMap();
HashMap<Surface, PhysicsSurface> surfaces = new HashMap();
//constructor
PhysicsNet(Space cNet, double gravity, double spring_constant, double spring_damping, double particle_damping, double mass, double restLengthFactor) {
Map pMap = new HashMap();
globalParticleMass = mass;
//this.bNet = (Space) bNet.copy(pMap);
this.cNet = cNet;
this.spring_c = spring_constant;
this.spring_d = spring_damping;
this.particle_d = particle_damping;
this.solid = isSolid();
//create Particles and Springs from Vertices of b-Net
Collection<Vertex> bVertices = cNet.getVertices();
Map<Vertex, List<Edge>> edgeMap = cNet.getEdgeMap(bVertices);
int counter = 0;
for (Vertex bV : bVertices) {
particles.put(bV, new PhysicsParticle(bV, new Vertex(0,0,0), new Vertex(0,0,0), mass, counter));
counter++;
}
//create Springs
Collection<Edge> bEdges = cNet.getEdges();
for (Edge bE : bEdges) {
PhysicsParticle pA = particles.get(bE.getFrom());
PhysicsParticle pB = particles.get(bE.getTo());
PhysicsSpring pS = new PhysicsSpring(pA,pB,pA.pos.distance(pB.pos),spring_c);
pS.restLengthFactor = restLengthFactor;
springs.put(bE, pS);
pA.connectSpring(pS);
pB.connectSpring(pS);
counter++;;
saveSpringParameter(bE,pS);
}
//create PhysicsSurfaces
Collection<Surface> bSurfaces = cNet.getSurfaces();
for (Surface bS : bSurfaces) {
//create HashMaps for Surface
//edges - springs
//vertices - Particles
List<Vertex> bSV = bS.getVertices();
HashMap<Vertex, PhysicsParticle> bSVP= new HashMap();
for (Vertex v : bSV) {
PhysicsParticle p = (PhysicsParticle) particles.get(v);
bSVP.put(v,p);
}
List<Edge> bSE = bS.getEdges();
HashMap<Edge, PhysicsSpring> bSES = new HashMap();
for (Edge e : bSE) {
PhysicsSpring s = (PhysicsSpring) springs.get(e);
bSES.put(e,s);
}
PhysicsSurface pS = new PhysicsSurface(bS,bSVP,bSES);
surfaces.put(bS, pS);
}
}
void saveSpringParameter(Edge e, PhysicsSpring pS) {
ParameterBlock block = e.getParameters();
if (block == null) {
block = new ParameterBlock();
e.setParameters(block);
block.putDouble("Spring current Length", e.getLength());
block.putDouble("Spring Restlength", pS.eql);
block.putDouble("Spring Constant", pS.c);
}
block.changeDouble("Spring current Length", e.getLength());
block.changeDouble("Spring Restlength", pS.eql);
block.changeDouble("Spring Constant", pS.c);
}
void saveParticleParameter(Vertex v, PhysicsParticle pP) {
ParameterBlock block = v.getParameters();
if (block == null) {
block = new ParameterBlock();
v.setParameters(block);
block.putDouble("Particle Weight [kg]", pP.m);
}
block.changeDouble("Particle Weight [kg]", pP.m);
}
double saveVolume (Space cNet) {
double volume = 0.0;
if (solid) {
volume = calcVolume();
ParameterBlock block = cNet.getParameters();
if (block == null) {
block = new ParameterBlock();
cNet.setParameters(block);
block.putDouble("Volume", volume);
}
block.changeDouble("Volume", volume);
}
return volume;
}
void saveArea (Surface s) {
ParameterBlock block = s.getParameters();
PhysicsSurface pS = surfaces.get(s);
if (block == null) {
block = new ParameterBlock();
s.setParameters(block);
block.putDouble("Area", pS.calcArea());
}
block.changeDouble("Area", pS.calcArea());
}
void updatePos(Vertex cV) {
PhysicsParticle pA = particles.get(cV);
pA.pos = new Vertex(cV.getX(),cV.getY(), cV.getZ());
pA.nPos = new Vertex(cV.getX(),cV.getY(), cV.getZ());
pA.lastPos = new Vertex(cV.getX(),cV.getY(), cV.getZ());
}
void updateMass(double mass) {
Iterator it = particles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
PhysicsParticle p = (PhysicsParticle)ee.getValue();
//only change value if mass of particle wasn't changed locally.
if (p.m == globalParticleMass) {
p.m = mass;
}
}
//set globalParticleMass to current value.
globalParticleMass = mass;
}
void scaleParticleMass(Vertex v, double scale) {
PhysicsParticle p = (PhysicsParticle)particles.get(v);
p.m = p.m * scale;
}
void updateRestLength(Edge e, double eql) {
PhysicsSpring s = (PhysicsSpring)springs.get(e);
s.eql = eql;
}
void setRestLengthFactor (Edge e, double restLengthFactor) {
PhysicsSpring s = (PhysicsSpring)springs.get(e);
s.restLengthFactor = restLengthFactor;
}
void scaleRestLengthFactor (Edge e, double scale) {
PhysicsSpring s = (PhysicsSpring)springs.get(e);
s.restLengthScale = s.restLengthScale * scale;
}
void updateSpringConstant(double springConstant) {
Iterator it = springs.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
PhysicsSpring s = (PhysicsSpring)ee.getValue();
s.c = springConstant;
}
}
void update(Space guides, double time, double equalConstant, double equalDamping, double rectConstant, double rectDamping, double planeConstant, double planeDamping, double volume) {
Iterator it;
//calculate surface forces
double currentVolume = saveVolume(cNet);
it = surfaces.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
PhysicsSurface s = (PhysicsSurface)ee.getValue();
s.equalizeEdges(time, equalConstant, equalDamping);
s.quadToRect(guides, time, rectConstant, rectDamping);
s.planarize(guides, time, planeConstant, planeDamping);
if ((volume>0) && (solid)) {
double normalForce = s.calcArea()*volume/currentVolume;
s.normalForce(guides, time, normalForce);
}
saveArea((Surface) ee.getKey());
}
//claculate particle movement
it = particles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
PhysicsParticle p = (PhysicsParticle)ee.getValue();
p.move(time, gravity, particle_d);
}
//move nodes of b-net to particle positions
it = particles.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
Vertex v = (Vertex)ee.getKey();
PhysicsParticle p = (PhysicsParticle)ee.getValue();
v.set(p.nPos);
saveParticleParameter(v,p);
}
//update springs
it = springs.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
Edge e = (Edge)ee.getKey();
PhysicsSpring s = (PhysicsSpring)ee.getValue();
s.update(time, spring_d);
saveSpringParameter(e,s);
}
cNet.update();
}
//check if c-Net forms a solid.
//each edge is connected to 2 surfaces.
boolean isSolid() {
boolean solid = true;
Collection<Edge> cEdges = cNet.getEdges();
for (Edge nE : cEdges) {
Set<Surface> cSurfaces = nE.getSurfaces();
if (cSurfaces.size()<2) solid = false;
}
return solid;
}
//calculate volume of solid
double calcVolume() {
double v = 0.0;
Iterator it = surfaces.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ee = (Map.Entry)it.next();
Surface s = (Surface)ee.getKey();
PhysicsSurface pS = (PhysicsSurface)ee.getValue();
List<Vertex> vertices = s.getVertices();
Vertex p = vertices.get(0);
Vertex n = pS.averageNormal();
//n.normalize();
double test = p.dot(n);
v = v + pS.calcArea()* test;
}
v = Math.abs(v)/3;
return v;
}
}
--- NEW FILE: PhysicsPlane.java ---
package net.sourceforge.bprocessor.packages.physics;
import net.sourceforge.bprocessor.model.Vertex;
public class PhysicsPlane {
//properties of a plane
//3 points
Vertex[] pPoints = new Vertex[3];
//normal
Vertex nVec = new Vertex(0,0,0);
//origin
Vertex origin;
//directions
Vertex dirX;
Vertex dirY;
//distance
double d = 0;
//constructor from 3 points
PhysicsPlane (Vertex origin, Vertex point1, Vertex point2) {
//save plane points
this.origin = new Vertex(origin.getX(),origin.getY(), origin.getZ());
dirX = new Vertex(point1.getX(),point1.getY(), point1.getZ());
dirY = new Vertex(point2.getX(),point2.getY(), point2.getZ());
pPoints[0] = this.origin;
pPoints[1] = new Vertex(point1.getX(),point1.getY(), point1.getZ());
pPoints[2] = new Vertex(point2.getX(),point2.getY(), point2.getZ());
//get plane directions
dirX = dirX.minus(origin);
dirY = dirY.minus(origin);
//calculate normal
nVec = dirX.cross(dirY);
nVec.normalize();
d = nVec.dot(origin);
}
//constructor from normal and origin
PhysicsPlane (Vertex nVec, Vertex origin) {
this.nVec = nVec.copy();
this.nVec.normalize();
d = nVec.dot(origin);
}
//Normal Vector from point onto Plane
Vertex PointNormalToPlane(Vertex pnt) {
double t0;
Vertex x0;
Vertex lNorm;
Vertex PtoE;
t0 = (d-nVec.dot(pnt)) / (nVec.dot(nVec));
lNorm = new Vertex(nVec.getX(), nVec.getY(),nVec.getZ());
lNorm = lNorm.scale(t0);
x0 = new Vertex (pnt.getX(), pnt.getY(), pnt.getZ());
x0 = x0.add(lNorm);
PtoE = x0;
PtoE = PtoE.minus(pnt);
return PtoE;
}
Vertex PointProjectToPlane(Vertex pnt) {
double t0;
Vertex x0;
Vertex lNorm;
Vertex PtoE;
t0 = (d-nVec.dot(pnt)) / (nVec.dot(nVec));
lNorm = new Vertex(nVec.getX(), nVec.getY(),nVec.getZ());
lNorm = lNorm.scale(t0);
x0 = new Vertex (pnt.getX(), pnt.getY(), pnt.getZ());
x0 = x0.add(lNorm);
PtoE = x0;
return PtoE;
}
}
|