Turn gauge arc into gradient

How would you change an arc on a guage so it goes from green to yellow to red?

What do you mean, buddy? Can you be more specific? Do you want to reproduce something like the image below?
image

1 Like

Exactly like that! Except in reverse.

Do you have any code that you’ve started working on? We’re not going to provide a step by step guide, but we can help you when you hit problems you can’t figure out by yourself

import meter.*;
//import serial library (NEW)
import processing.serial.*;

//define a serial port (NEW)
Serial port;

Meter m,m2;//include variable (new meter names) here seperated by comma and last with semi-colon


void setup(){
  
  size(950,400);
  background(0,0,0);
  
 port = new Serial(this, "COM21",9600);//Create new port and add Baud rate (NEW)
 //port number is the serial port you are using when you connect your Arduino board (Tools/Port) and baud rate is in the Arduino Sketch we have used See Serial.begin(9600).
  //lets add a default meter
  //TEMPERATURE METER
  m = new Meter(this,25,50);// here 25,50 are x,y coords.
  
  m.setTitleFontSize(20);
  m.setTitleFontName("Ariel bold");
  m.setTitle("Temperature (°C)");
  //change meter scales
  
String[] scaleLabels = {"0","10","20","30","40","50","60","70","80"};
 
  m.setScaleLabels(scaleLabels);//numbers for dial
  m.setScaleFontSize(18);
  m.setScaleFontName("Times new roman bold");
  m.setScaleFontColor(color(200,30,70));
  // we can also display the values of meter underneath
 
  m.setDisplayDigitalMeterValue(true);
  // lets change the arc colour
  m.setArcColor(color(141,113,178));
  m.setArcThickness(15);
  
  m.setMaxScaleValue(80);
  m.setMinInputSignal(0);
  m.setMaxInputSignal(80);
  
  m.setNeedleThickness(3);
  //lets take some reference from first meter
  int mx = m.getMeterX();
  int my = m.getMeterY();
  int mw = m.getMeterWidth();
  
  
  //HUMIDITY METER
  m2 = new Meter(this,mx + mw+20, my);
  
    m2.setTitleFontSize(20);
  m2.setTitleFontName("Ariel bold");
  m2.setTitle("Humidity (%)");
  //change meter scales
  
String[] scaleLabels2 = {"0","10","20","30","40","50","60","70","80","90","100"};
 
  m2.setScaleLabels(scaleLabels2);//numbers for dial
  m2.setScaleFontSize(18);
  m2.setScaleFontName("Times new roman bold");
  m2.setScaleFontColor(color(200,30,70));
  // we can also display the values of meter underneath
 
  m2.setDisplayDigitalMeterValue(true);
  // lets change the arc colour
  m2.setArcColor(color(141,113,178));
  m2.setArcThickness(8);
  
  m2.setMaxScaleValue(100);
  m2.setMinInputSignal(0);
  m2.setMaxInputSignal(100);
  
  m2.setNeedleThickness(3);
  
}

void draw(){
  // lets give a title to our guages
  textSize(30);
  fill(132,131,131);  
  text("Temperature and Humidity",120,40);
  //below is (NEW)
  if(port.available() >0)
  {
    String val = port.readString();//read incoming string on serial port
    //Now to seperate temp and humidity values
    String[] list = split(val, ',');//splits value seperated by comma
    float temp = float(list[0]);
    float hum = float(list[1]); //**SHOWING ARRAYINDEXOUTOFBOUNDSEXCEPTION 1 ????**
    
    m.updateMeter(int(temp));//new
    m2.updateMeter(int(hum));//new
    
    println("Temperature: " +temp + " C " + "Humidity: " + hum +"%");
  }
 
}
1 Like

Thanks for the prompt response!

Could you also have a look at the out of bounds exception towards the bottom please?

Wow! I can’t find the thread but someone had this problem before! (I’ll edit it in once I find it). It comes down to the fact that the serial Port just skips output, randomly, for whatever reason. Our previous fix was to just test whether or not list actually contained a second element.

I know you’ve must have spent a lot of time on this, but I actually believe someone’s made a very polished library that does what you want and more (yay?).

But if you’re just using this as a learning exercise, we can still tackle the original problem

EDIT:
Here’s the link: [SOLVED] ArrayIndexOutOfBoundsException: 1

The original problem was getting the arc to go from green to yellow to red. If we could solve that first that would be great. As you saw, list contains two elements so not sure what the error is about. It is reading from an Arduino with a DH22 attached.

Well, I don’t know if this will help you but I liked the challenge so I built a simple method to create gradient arcs. You can even choose to apply stroke or not. It’s not perfect, but I think it might be a good approach for someone better than me to work on it. I really don’t know if there’s any way to fill arcs (or any other geometric figures) with gradient. So I leave this sketch here and if anyone is interested in improving it, that would be great.

void setup() {
  size(500, 500);
}

void draw() {
  background(255);
  
  applyStroke(false);
  myArc(width/2, height/2, 30, 50, 0, PI/4, color(0, 0, 255), color(255, 0, 0));
  myArc(width/2, height/2, 70, 100, PI/4, PI, color(255, 0, 0), color(255, 255, 0));
  applyStroke(true);
  myArc(width/2, height/2, 110, 150, PI, PI+QUARTER_PI, color(255, 255, 0), color(0, 255, 255));
  myArc(width/2, height/2, 150, 200, PI+QUARTER_PI, TWO_PI, color(0, 255, 255), color(255, 0, 255));
}

void myArc(int x, int y, int innerRadius, int outerRadius, float startingAngle, float endAngle, color from, color to) {
  /*
   * This variable stores the "distance" between the starting angle and the final angle. 
   * This is important to use in strokeWeight and treat spaces between each line
   */
  float strokeOffset = endAngle - startingAngle;

  /*
   * This is an arbitrary number of lines to draw. 
   * The idea is to have one line for each angle (360 lines for 360 degrees). Yeah, this could be better...
   */
  int maxLines = 360;

  //This line of code resizes the strokeWeight of each line in order to smooth out the holes when the arc has a very large aplitude
  strokeWeight(map(strokeOffset, 0, TWO_PI, 2, 5));
  strokeCap(SQUARE);

  for (float i = 0; i < maxLines; i ++) {
    pushMatrix();
    translate(x, y);
    
    // distributing the angles for each line segment
    rotate(map(i, 0, maxLines, startingAngle, endAngle));
    
    // lerpColor() deals with the interpolation from one color to another
    stroke(lerpColor(from, to, map(i, 0, maxLines, 0, 1)));
    
    line(innerRadius, 0, outerRadius, 0);
    popMatrix();
  }
  if (stroke) {
    strokeWeight(2);
    stroke(0);

    pushMatrix();
    translate(x, y);
    rotate(startingAngle);
    line(innerRadius, 0, outerRadius, 0);
    rotate(strokeOffset);
    line(innerRadius, 0, outerRadius, 0);
    popMatrix();

    noFill();
    strokeCap(PROJECT);
    arc(x, y, outerRadius*2, outerRadius*2, startingAngle, endAngle);
    arc(x, y, innerRadius*2, innerRadius*2, startingAngle, endAngle);
  }
}

boolean stroke;
void applyStroke(boolean state) {
  stroke = state;
}

Here’s what my method can do:


good luck :wink:

2 Likes

It only contains 2 elements if the serial Port delivers 2 values.
Take a look at this thread:

Still throwing that error. Tried some of the suggestions above.

What’s the new code look like?

There are several approaches to this problem. Some include:

  1. draw many tiny arc segments to create a gradient (solution from @Ov3rM1nD above)
  2. create a closed PShape in the shape of an arc and fill with a gradient (e.g. a PShader)
  3. draw a full gradient image, then draw a single arc as a mask and apply to “cut-out” your gradient.

For examples and past discussion of the mask-based approach, see:

There is also a related library:

1 Like