我正在构建一个简单代码中的错误。代码从节点增长线。每个节点是两个点和连接两个点的线。每个节点可以增长一次,并且在增长函数中处理增长
节点类的增长函数的一部分具有旋转节点方向的条件(因此线条略微波动)并且由于某种原因所有节点以我编写代码的方式旋转。有人能指出我所犯的毫无疑问的简单错误吗?
代码:
Node[] ns;
int nodeCount;
void setup() {
size(1024, 1024, P3D);
background(255);
stroke(0);
frameRate(60);
fill(0);
nodeCount = int(10000);
ns = new Node[nodeCount];
for(int i = 0; i < nodeCount; i++){
ns[i] = new Node(i, 0, 0, 0, 0, 0, new PVector(0, 0), false, false, false);
}
for(int i = 0; i < 1; i++){
ns[i] = new Node(i, random(float(width)), random(float(height)), 5, 0, random(100), new PVector(10, 10).rotate(random(-PI/2, PI/2)), true, false, true);
}
}
void draw() {
background(255);
//print("frame ");
for ( Node n: ns ){
if ( n.Active ) {
//print(n.index, " ");
n.display();
if ( n.Growth ){
n.grow();
}
}
if( n.Init ){
n.init();
}
}
}
class Node {
int index;
float xi, yi, size, theta, noiseoff;
PVector dir;
Boolean Active, Growth, Init;
Node(int ind, float x, float y, float s, float t, float n, PVector d, Boolean A, Boolean G, Boolean I) {
index = ind;
xi = x;
yi = y;
size = s;
theta = t;
noiseoff = n;
dir = d;
Active = A;
Growth = G;
Init = I;
}
void display(){
strokeWeight(0);
ellipse(xi, yi, size, size);
ellipse(xi + dir.x, yi + dir.y, size, size);
strokeWeight(size);
line(xi, yi, xi + dir.x, yi + dir.y);
//xi = xi + dir.x;
//yi = yi + dir.y;
}
void grow(){
boolean done = false;
int i = index + 1;
PVector tempDir = new PVector(0, 0);
tempDir = dir;
while ( !done & i < nodeCount & Growth ) {
if ( ns[i].Active == false ) {
if( random(100) > 85 ){
noiseoff += 0.01;
theta = map(noise(noiseoff), 0, 1, -PI/12, PI/12);
tempDir.rotate(theta);
}
ns[i] = new Node(i, xi + tempDir.x, yi + tempDir.y, size, theta, noiseoff, tempDir, true, false, true);
Growth = false;
done = true;
if (i == nodeCount - 1 ) {
done = true;
}
}
i++;
if (i == nodeCount ) {
done = true;
}
}
i++;
}
void init(){
Growth = true;
Init = false;
}
}
另一个引入createNode()方法的版本,用于删除节点类中节点数组的循环(仍有错误):
Node[] ns;
int nodeCount;
void setup() {
size(1024, 1024, P3D);
background(255);
stroke(0);
frameRate(60);
fill(0);
nodeCount = int(10000);
ns = new Node[nodeCount];
// Initialize array with blank nodes
for(int i = 0; i < nodeCount; i++){
ns[i] = new Node(i, 0, 0, 0, 0, 0, new PVector(0, 0), false, false, false);
}
// Create Root node
createNode(random(float(width)), random(float(height)), 5, 0, random(100), new PVector(2.5, 2.5).rotate(random(-PI/2, PI/2)), true, false, true);
}
void draw() {
background(255);
for ( Node n: ns ){
if ( n.Active ) {
// Draw active nodes
n.display();
// Grow nodes which haven't grown before
if ( n.Growth ){
n.grow();
}
}
// Initialize nodes which were grown last time step (so that they can grown in the subsequent timestep)
if( n.Init ){
n.init();
}
}
}
// Wrapper function that looks for a free row in the node array to create a new node
void createNode(float x, float y, float s, float t, float n, PVector d, Boolean A, Boolean G, Boolean I){
float xi, yi, size, theta, noiseoff;
PVector dir;
Boolean Active, Growth, Init, done;
int i;
xi = x;
yi = y;
size = s;
theta = t;
noiseoff = n;
dir = d;
Active = A;
Growth = G;
Init = I;
i = 0;
done = false;
while ( !done ) {
if ( ns[i].Active == false ) {
ns[i] = new Node(i, xi + dir.x, yi + dir.y, size, theta, noiseoff, dir, true, false, true);
done = true;
if (i == nodeCount - 1 ) {
done = true;
}
}
i++;
if (i == nodeCount ) {
done = true;
}
}
}
// Node class
class Node {
int index;
float xi, yi, size, theta, noiseoff;
PVector dir;
Boolean Active, Growth, Init;
Node(int ind, float x, float y, float s, float t, float n, PVector d, Boolean A, Boolean G, Boolean I) {
index = ind;
xi = x;
yi = y;
size = s;
theta = t;
noiseoff = n;
dir = d;
Active = A;
Growth = G;
Init = I;
}
void display(){
// Draw node as two circles and a line
strokeWeight(0);
ellipse(xi, yi, size, size);
ellipse(xi + dir.x, yi + dir.y, size, size);
strokeWeight(size);
line(xi, yi, xi + dir.x, yi + dir.y);
}
// Grow method
void grow(){
int i = index + 1;
PVector tempDir = dir;
// Small chance of angle deviation
if( random(100) > 85 ){
noiseoff += 0.01;
theta = map(noise(noiseoff), 0, 1, -PI/12, PI/12);
tempDir.rotate(theta);
}
// Create new node appended onto the last
createNode(xi + tempDir.x, yi + tempDir.y, size, theta, noiseoff, tempDir, true, false, true);
// Set growth to false to prevent this node growning again
Growth = false;
}
// Initialize previously grown nodes for growth
void init(){
Growth = true;
Init = false;
}
}
答案 0 :(得分:1)
原来是我生成的一个临时矢量tempDir要旋转(因为.rotate()方法旋转矢量并更改它)稍微不正确。
改变
PVector tempDir = dir;
到
PVector tempDir = new PVector(dir.x, dir.y);
修正了我的错误,我猜不知道数据分配会不知所措?
答案 1 :(得分:0)
您的Node#grow()
函数循环遍历数组中的每个索引,将每个Node
替换为自身的旋转版本。
这没有多大意义,因为您已经遍历每个Node
并调用grow()
函数。因此,对于每个Node
,您循环遍历每个Node
并将其替换为旋转版本...为什么?
看起来你正在混合应该在每个Node
上运行的逻辑与在Node
上运行的逻辑。以下是一般的经验法则:您的Node
类应该只处理单个Node
,因此如果您正在访问ns
数组,那么可能会出现一些问题。
(除非您需要每个Node
与其他Node
进行互动,但这似乎并非如此。)
要解决您的问题,您必须将循环每个Node
的逻辑与修改单个Node
的逻辑分开。
如果您从一个Node
开始,可能会更容易。在您担心多个Node
实例之前,让单Node
工作。
编辑:您仍然在修改每个Node
内部包含Node
个实例的数组。这是你困惑的根源。我现在看到你修复了你的问题,但我敢打赌,你会继续遇到类似的问题。
这是我正在研究的例子。这在每个child
实例中使用Node
变量,而不是尝试将子项存储在存储父Node
实例的同一数组中。也许它会派上用场:< / p>
ArrayList<Node> nodes = new ArrayList<Node>();
void setup() {
size(500, 500);
for(int i = 0; i < 100; i++){
nodes.add(new Node());
}
}
void mousePressed() {
for ( Node node : nodes ) {
node.grow();
}
}
void draw() {
background(255);
for ( Node node : nodes ) {
node.display();
}
}
class Node {
float x;
float y;
float angle;
float length;
Node child;
Node() {
x = random(width);
y = random(height);
angle = random(360);
length = random(5, 10);
}
void display() {
float endX = x + cos(radians(angle)) * length;
float endY = y + sin(radians(angle)) * length;
line(x, y, endX, endY);
if (child != null) {
child.display();
}
}
void grow() {
if (child == null) {
float endX = x + cos(radians(angle)) * length;
float endY = y + sin(radians(angle)) * length;
child = new Node();
child.x = endX;
child.y = endY;
child.angle = random(angle-10, angle+10);
} else {
child.grow();
}
}
}