如何让处理使用数组的一部分

How to get Processing to use a part of an array

该软件用于加速度计芯片的实时分析。但是,它不会使用数组组件生成图形。当我用实际数字替换 void drawAxes 中的 dat[0/1/2] 部分时,会生成图形。

有什么方法可以让 dat[] 数组在这个系统中工作,或者我可以使用任何替代方法吗? dat[]*100 只是为了放大插入的值。

//Accelerometer graphing programme
//Author: Owain L. Evans, owainlevans@outlook.com
//Takes data from Arduino and produces a 3-Dimensional visualisation


import processing.serial.*;

Serial myPort; //Serial Port
String DataLine; //Input from serial port

float[] dat;

PVector a = new PVector(100, 50, 20);

void setup()
  {
  size(1024, 720, P3D);
  strokeWeight(3);

  dat = new float[3];

  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw() {
  if (myPort.available() > 0)
    {DataLine = myPort.readStringUntil('\n');
    }
  if (DataLine != null) {
  println(DataLine);
  float dat[] = float(split(DataLine, ","));  //parse comma-separated number string into numbers
  println(dat);
  println();
  }
  background(250);
  drawAxes(dat[0]*100, dat[1]*100, dat[2]*100);  //draw original coordinate system
  translate(width * 0.5, height * 0.5, 0);
  rotateX(map(mouseY,0,height,-PI,PI));
  rotateY(map(mouseX,0,width,-PI,PI));

  drawAxes(dat[0]*100, dat[1]*100, dat[2]*100);

  pushMatrix();
  translate(a.x, a.y, a.z);  //isolate coordinate system and draw translated A point
  popMatrix();
}

void drawAxes(float x, float y, float z) {
  //X - red
  stroke(192, 0, 0);  
  line( 0, 0, 0, x, 0, 0);
  //Y - green
  stroke(0, 192, 0);
  line(0, 0, 0, 0, y, 0);
  //Z - blue
  stroke(0, 0, 192);
  line(0, 0, 0, 0, 0, z);
}

很难说出数组发生了什么,但您可以向 drawAxes() 添加参数,这将消除与 dat 的紧密耦合,并使其可重新用于其他草图:

void drawAxes(float x, float y, float z) {
  //X - red
  stroke(192, 0, 0);  
  line( 0, 0, 0, x, 0, 0);
  //Y - green
  stroke(0, 192, 0);
  line(0, 0, 0, 0, y, 0);
  //Z - blue
  stroke(0, 0, 192);
  line(0, 0, 0, 0, 0, z);
}

(例如 drawAxes(dat[0] * 100, dat[1] * 100, dat[2] * 100);

更新 我明白你的意思:你想构建一个传入数据的图表和绘图。

问题是目前您只存储了一个不断更新的样本。

要绘制具有多个值的图表,您需要:

  1. 创建一个数组来存储多个样本
  2. 更新数组(在新值到达时移动旧值)
  3. 遍历数组并绘制每个值

第 1 步: 创建一个 [n-samples][3] 二维数组来存储传入数据。 为了争论起见,让我们存储 30 个样本的历史记录:

int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];

步骤 2: 更新样本(移动旧数据,添加新数据):

// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
  // shift oldest samples by 1: count backwards from oldest sample to 2nd sample
  for (int i = numSamples - 1; i > 0; i--) {
    // copy previous sample data: offsetting old data by 1
    samples[i][0] = samples[i-1][0];
    samples[i][1] = samples[i-1][1];
    samples[i][2] = samples[i-1][2];
  }
  // add newest entry as the first sample (replacing old data)
  samples[0][0] = x;
  samples[0][1] = y;
  samples[0][2] = z;
}

步骤 3 遍历数据并绘图:

// render samples on screen with the option to scale the data
void drawSamples(float scale) {
  for (int i = 0 ; i < numSamples; i++){
    drawAxes(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
  }
}

请记住,这在渲染方面并不是非常高效,但是对于 30 个样本应该没问题。最后,重要的是可视化风格的易读性。

如果你想做一个更简单的渲染可视化,你可以简单地渲染一条线:

void drawSamples(float scale) {
  beginShape();
  for (int i = 0 ; i < numSamples; i++){
    vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
  }
  endShape();
}

综合来看:

import processing.serial.*;

Serial myPort; //Serial Port
String dataLine; //Input from serial port

PVector a = new PVector(100, 50, 20);

int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];

// stores a single data sample from serial
float[] sample = new float[sampleDimensions]; 
// how much to scale data for visualisation
float sampleRenderScale = 100;

void setup() {
  size(1024, 720, P3D);
  strokeWeight(3);
  noFill();
  // try to open serial connection: display error otherwise (port missing, or busy (already open in Serial Monitor, etc.))
  try {
    String portName = Serial.list()[0];
    myPort = new Serial(this, portName, 9600);
  }catch(Exception e) {
    println("error openin serial port: " + Serial.list()[0]);
    e.printStackTrace();
  }

}

void draw() {
  if(myPort != null){
    if (myPort.available() > 0){
      dataLine = myPort.readStringUntil('\n');

      if (dataLine != null) {
        println(dataLine);
        sample = float(split(dataLine, ","));  //parse comma-separated number string into numbers
        println(sample);
        if(sample == null || sample.length < 3){
           println("parsed less than the expected 3 values:");
           return;
        }
        println();
        // add new sample to the list of recorded samples
        updateSamples(sample[0], sample[1], sample[2]);
      }
    }
  }


  background(250);

  drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale);  //draw original coordinate system

  translate(width * 0.5, height * 0.5, 0);
  rotateX(map(mouseY, 0, height, -PI, PI));
  rotateY(map(mouseX, 0, width, -PI, PI));

  drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale);
  // draw recorded samples
  drawSamples(sampleRenderScale);

  pushMatrix();
  translate(a.x, a.y, a.z);  //isolate coordinate system and draw translated A point
  popMatrix();
}

// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
  // shift oldest samples by 1: count backwards from oldest sample to 2nd sample
  for (int i = numSamples - 1; i > 0; i--) {
    // copy previous sample data: offsetting old data by 1
    samples[i][0] = samples[i-1][0];
    samples[i][1] = samples[i-1][1];
    samples[i][2] = samples[i-1][2];
  }
  // add newest entry as the first sample (replacing old data)
  samples[0][0] = x;
  samples[0][1] = y;
  samples[0][2] = z;
}

// render samples on screen with the option to scale the data
void drawSamples(float scale) {
  beginShape();
  for (int i = 0 ; i < numSamples; i++){
    vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
  }
  endShape();
}

void drawAxes(float x, float y, float z) {
  //X - red
  stroke(192, 0, 0); 
  line( 0, 0, 0, x, 0, 0); 
  //Y - green
  stroke(0, 192, 0); 
  line(0, 0, 0, 0, y, 0); 
  //Z - blue
  stroke(0, 0, 192); 
  line(0, 0, 0, 0, 0, z);
}

注意一些变化:

  • DataLine 重命名为 dataLine(根据 Java Naming Conventions
  • 通常将变量重命名为易于理解的内容are/do并格式化代码以便于阅读
  • 处理串行端口连接时出错。您已经对传入数据进行了错误处理,这很棒。

我们的想法是随着你的进步养成良好的习惯。

如果您有时间探索其他语言,我推荐 Python 和一些模块, 如果感兴趣,可能会启动 cluserting/classifying 传感器数据: