《算法》第六章部分程序 part 1
▶ 书中第六章部分程序,包括在加上自己补充的代码,粒子碰撞系统及用到的粒子类
● 粒子系统
package package01; import java.awt.Color;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.Particle; public class class01
{
private static final double HZ = 0.5; // 每个时间步长内重画的次数
private MinPQ<Event> pq; // 优先队列
private double t = 0.0; // 计时器
private Particle[] particles; // 粒子数据列表 private static class Event implements Comparable<Event> // 碰撞事件类
{
private final double time; // 预计事件发生时间
private final Particle a, b; // 事件中的粒子
private final int countA, countB; // 粒子在加入事件中时的已碰撞的次数 public Event(double inputT, Particle inputA, Particle inputB) // 输入当前时间和两个粒子,计算碰撞事件
{
time = inputT;
a = inputA;
b = inputB;
countA = (a != null) ? a.count() : -1;
countB = (b != null) ? b.count() : -1;
} public int compareTo(Event that) // 比较两个事件哪个先发生
{
return Double.compare(this.time, that.time);
} public boolean isValid() // 判断事件是否有效
{
return (a == null || a.count() == countA) && (b == null || b.count() == countB);// 原代码简化版
//if (a != null && a.count() != countA || b != null && b.count() != countB) // 原代码,只要有粒子当前实际碰撞数与事件中记录的 count 不等,说明事件失效
// return false;
//return true;
}
} public class01(Particle[] inputParticle)
{
particles = inputParticle.clone(); // 输入列表的深拷贝
} private void predict(Particle a, double limit) // 更新优先队列中关于粒子 a 的事件
{
if (a == null)
return;
for (int i = 0; i < particles.length; i++) // 预测 a 与各粒子碰撞的时间,只要时间小于阈值就将其放入优先队列
{
double targetTime = t + a.timeToHit(particles[i]);
if (targetTime <= limit)
pq.insert(new Event(targetTime, a, particles[i]));
}
double targetTimeX = t + a.timeToHitVerticalWall(), targetTimeY = t + a.timeToHitHorizontalWall();
if (targetTimeX <= limit)
pq.insert(new Event(targetTimeX, a, null));
if (targetTimeY <= limit)
pq.insert(new Event(targetTimeY, null, a));
} private void redraw(double limit) // 重画所有粒子位置
{
StdDraw.clear();
for (int i = 0; i < particles.length; i++)
particles[i].draw();
StdDraw.show();
StdDraw.pause(20); // 暂停 20 ms
if (t < limit) // 还没到时限,加入重画事件
pq.insert(new Event(t + 1.0 / HZ, null, null));
} public void simulate(double limit) // 模拟器
{
pq = new MinPQ<Event>();
for (int i = 0; i < particles.length; i++) // 首次计算所有粒子之间的碰撞
predict(particles[i], limit);
for (pq.insert(new Event(0, null, null)); !pq.isEmpty();) // 多加入一个重画所有粒子位置的事件
{
Event e = pq.delMin(); // 取出发生时间最近的时间,判断是否有效
if (!e.isValid())
continue;
Particle a = e.a, b = e.b;
for (int i = 0; i < particles.length; i++) // 更新所有粒子位置
particles[i].move(e.time - t);
t = e.time; // 更新当前时间 if (a != null && b != null) // 粒子 - 粒子碰撞
a.bounceOff(b);
else if (a != null && b == null) // 粒子撞竖直墙壁
a.bounceOffVerticalWall();
else if (a == null && b != null)
b.bounceOffHorizontalWall(); // 粒子撞水平墙壁
else if (a == null && b == null)
redraw(limit); // 仅重画所有粒子位置
predict(a, limit); // 重新预测 a 与 b相关的事件
predict(b, limit);
}
} public static void main(String[] args)
{
StdDraw.setCanvasSize(600, 600); // 窗口大小
StdDraw.enableDoubleBuffering(); // double 缓冲区
Particle[] particles; // 粒子列表 if (args.length == 1) // 输入一个参数,生成相应个数的个粒子
{
int n = Integer.parseInt(args[0]);
particles = new Particle[n];
for (int i = 0; i < n; i++)
particles[i] = new Particle();
}
else // 否则按标准输入流依次输入每个粒子的信息
{
int n = StdIn.readInt();
particles = new Particle[n];
for (int i = 0; i < n; i++)
{
double rx = StdIn.readDouble();
double ry = StdIn.readDouble();
double vx = StdIn.readDouble();
double vy = StdIn.readDouble();
double radius = StdIn.readDouble();
double mass = StdIn.readDouble();
int r = StdIn.readInt();
int g = StdIn.readInt();
int b = StdIn.readInt();
Color color = new Color(r, g, b);
particles[i] = new Particle(rx, ry, vx, vy, radius, mass, color);
}
}
class01 system = new class01(particles); // 模拟和输出
system.simulate(10000); // 模拟事件 10s
}
}
● 粒子类
package package01; import java.awt.Color;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdRandom; public class class01
{
private static final double INFINITY = Double.POSITIVE_INFINITY; private double rx, ry;
private double vx, vy;
private int count; // 粒子已经碰撞的次数
private final double radius;
private final double mass;
private final Color color; public class01(double inputRx, double inputRy, double inputVx, double inputVy, double inputRadius, double inputMass, Color inputColor)
{
rx = inputRx;
ry = inputRy;
vx = inputVx;
vy = inputVy;
radius = inputRadius;
mass = inputMass;
color = inputColor;
} public class01()
{
rx = StdRandom.uniform(0.0, 1.0);
ry = StdRandom.uniform(0.0, 1.0);
vx = StdRandom.uniform(-0.005, 0.005);
vy = StdRandom.uniform(-0.005, 0.005);
radius = 0.02;
mass = 0.5;
color = Color.BLACK;
} public void move(double dt)
{
rx += vx * dt;
ry += vy * dt;
} public void draw() // 绘制粒子
{
StdDraw.setPenColor(color);
StdDraw.filledCircle(rx, ry, radius);
} public int count()
{
return count;
} public double timeToHit(class01 that)
{
if (this == that)
return INFINITY;
double dx = that.rx - rx, dy = that.ry - ry, dvx = that.vx - vx, dvy = that.vy - vy;
double dvdr = dx * dvx + dy * dvy;
if (dvdr > 0) // Δx 与 Δv 同号,不会撞
return INFINITY;
double dvdv = dvx * dvx + dvy * dvy;
if (dvdv == 0) // 速度完全相等,不会撞
return INFINITY;
double drdr = dx * dx + dy * dy;
double dist = radius + that.radius;
double d = (dvdr*dvdr) - dvdv * (drdr - dist * dist);
return (d > 0) ? -(dvdr + Math.sqrt(d)) / dvdv : INFINITY;
} public double timeToHitVerticalWall()
{
return (vx > 0) ? (1.0 - rx - radius) / vx : ((vx < 0) ? (radius - rx) / vx : INFINITY);
} public double timeToHitHorizontalWall()
{
return (vy > 0) ? (1.0 - ry - radius) / vy : ((vy < 0) ? (radius - ry) / vy : INFINITY);
} public void bounceOff(class01 that)
{
double dx = that.rx - rx, dy = that.ry - ry;
double dvx = that.vx - vx, dvy = that.vy - vy;
double dvdr = dx * dvx + dy * dvy;
double dist = radius + that.radius;
double magnitude = 2 * mass * that.mass * dvdr / ((mass + that.mass) * dist);
double fx = magnitude * dx / dist, fy = magnitude * dy / dist;
vx += fx / mass;
vy += fy / mass;
that.vx -= fx / that.mass;
that.vy -= fy / that.mass;
count++;
that.count++;
} public void bounceOffVerticalWall()
{
vx = -vx;
count++;
} public void bounceOffHorizontalWall()
{
vy = -vy;
count++;
} public double kineticEnergy()
{
return 0.5 * mass * (vx*vx + vy * vy);
}
}
《算法》第六章部分程序 part 1的更多相关文章
- 《算法》第六章部分程序 part 7
▶ 书中第六章部分程序,加上自己补充的代码,包括全局最小切分 Stoer-Wagner 算法,最小权值二分图匹配 ● 全局最小切分 Stoer-Wagner 算法 package package01; ...
- 《算法》第六章部分程序 part 6
▶ 书中第六章部分程序,包括在加上自己补充的代码,包括二分图最大匹配(最小顶点覆盖)的交替路径算法和 HopcroftKarp 算法 ● 二分图最大匹配(最小顶点覆盖)的交替路径算法 package ...
- 《算法》第六章部分程序 part 5
▶ 书中第六章部分程序,包括在加上自己补充的代码,网络最大流 Ford - Fulkerson 算法,以及用到的流量边类和剩余流量网络类 ● 网络最大流 Ford - Fulkerson 算法 pac ...
- 《算法》第六章部分程序 part 8
▶ 书中第六章部分程序,加上自己补充的代码,包括单纯形法求解线性规划问题 ● 单纯形法求解线性规划问题 // 表上作业法,I 为单位阵,y 为对偶变量,z 为目标函数值 // n m 1 // ┌── ...
- 《算法》第六章部分程序 part 4
▶ 书中第六章部分程序,包括在加上自己补充的代码,利用后缀树查找最长重复子串.查找最大重复子串并输出其上下文(Key word in context,KWIC).求两字符串的最长公共子串 ● 利用后缀 ...
- 《算法》第六章部分程序 part 3
▶ 书中第六章部分程序,包括在加上自己补充的代码,后缀树的两种实现 ● 后缀树实现一 package package01; import java.util.Arrays; import edu.pr ...
- 《算法》第六章部分程序 part 2
▶ 书中第六章部分程序,包括在加上自己补充的代码,B-树 ● B-树 package package01; import edu.princeton.cs.algs4.StdOut; public c ...
- 《算法》第一章部分程序 part 1
▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...
- 《算法》第二章部分程序 part 5
▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...
随机推荐
- sql server 安装时提示要重启
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager 打开“Session Manager”文件夹之后在右侧的区域中单 ...
- 黄聪:C#如何使用fiddlercoreCapture监控手机APP
1.去下载Fiddler:https://www.telerik.com/download/fiddler 2.安装Fiddler,按下图所示导出证书,导出后在桌面得到:FiddlerRoot.cer ...
- git撤销本地所有未提交的更改
1. git clean -df2. git reset --hard第一个命令只删除所有untracked的文件,如果文件已经被tracked, 修改过的文件不会被回退.而第二个命令把tracked ...
- 【mysql】ICP下mysql执行计划的一次解析
mysql版本 [root@xxxx]# mysql --version mysql Ver 15.1 Distrib 5.5.52-MariaDB, for Linux (x86_64) using ...
- java1.8 新特性(关于 match,find reduce )操作
match处理Integer集合 package lambda.stream; /** * @author 作者:cb * @version 创建时间:2019年1月4日 下午2:35:05 */ i ...
- 学习笔记之Supervised Learning with scikit-learn | DataCamp
Supervised Learning with scikit-learn | DataCamp https://www.datacamp.com/courses/supervised-learnin ...
- re模块小结
一.引子: 文件err.txt中有如下内容: 要求提取出所有的电话号码来. 方法一:文件操作法: f = open('eer.txt','r',encoding='utf-8') l = [] for ...
- [UE4]机器人射击逻辑行为树
1.寻找敌人 2.如果没有找到,等待2秒,跳转到1 3.如果找到了,走向敌人 4.走向敌人的过程中,如果看见敌人了,则射击 5.如果敌人没有了,则跳转到1
- 6行代码解决golang TCP粘包
转自:https://studygolang.com/articles/12483 什么是TCP粘包问题以及为什么会产生TCP粘包,本文不加讨论.本文使用golang的bufio.Scanner来实现 ...
- AnimDynamics简介
转自:http://www.cnblogs.com/corgi/p/5405452.html AnimDynamics简介 AnimDynamics是UE4.11 Preview 5测试版本发布的An ...