QPainter graduation(this);
pen.setWidth(2);
pen.setColor(Qt::white);
graduation.setPen(pen);
graduation.setRenderHint(QPainter::HighQualityAntialiasing);
graduation.translate(center.x(), center.y());
double newRadius = (width() - 50) / 2;
//qreal angleStep = 270 / m_stepsize;
for (int i = 0; i <= m_stepsize; i++)
{
graduation.save();
graduation.rotate(i * angleStep + 135);
graduation.drawLine(newRadius - 8, 0, newRadius, 0);
graduation.drawText(newRadius - 30, 0, "100");
graduation.restore();
}
I used code above to draw numbers on clock. Here is what i get
But i want to draw numbers to look like the image below. It must not be upside down.
Can anyone help me. I understand about rotate function that's is the reason its happen to the numbers, but i can not figure it out how to fix it.
You can calculate the position manually and draw the text unrotated:
for (int i = 0; i <= m_stepsize; i++)
{
graduation.save();
graduation.rotate(i * angleStep + 135);
graduation.drawLine(newRadius - 8, 0, newRadius, 0);
graduation.restore();
double xpos=(newRadius - 30)*cos((i * angleStep + 135.)/360.*2.*3.14159);
double ypos=(newRadius - 30)*sin((i * angleStep + 135.)/360.*2.*3.14159);
graduation.drawText(xpos, ypos, "100");
}
Related
I'm trying to move an arrow, which could be rotated, in a straight line. I'm having some difficulty coming up with the correct formula to use. I know it should probably involve sine and cosine, but I've tried various configurations and haven't been able to get something that works.
Here's a picture of my scene with the arrow and bow
rotateNumber is an integer like -1 (for 1 left rotation), 0 (no rotation), 1 (1 right rotation), etc.
rotateAngle is 10 degrees by default.
Here's the code to move the arrow:
if (arrowMoving) {
var rAngle = rotateAngle * rotateNumber;
var angleInRad = rAngle * (Math.PI/180);
var stepSize = 1/20;
arrowX += stepSize * Math.cos(angleInRad);
arrowY += stepSize * Math.sin(angleInRad);
DrawArrowTranslate(arrowX, arrowY);
requestAnimFrame(render);
} else {
DrawArrow();
arrowX = 0;
arrowY = 0;
}
Here's the code to draw and translate the arrow:
function DrawArrowTranslate(tx, ty) {
modelViewStack.push(modelViewMatrix);
/*
var s = scale4(0.3, -0.7, 1);
var t = translate(0, -4, 0);
*/
var s = scale4(0.3, -0.7, 1);
var t = translate(0, -5, 0);
var t2 = translate(0 + tx, 1 + ty, 0)
// rotate takes angle in degrees
var rAngle = rotateAngle;
var r = rotate(rAngle, 0, 0, 1);
var m = mult(t, r);
var m = mult(m, t2);
modelViewMatrix = mat4();
modelViewMatrix = mult(modelViewMatrix, m);
modelViewMatrix = mult(modelViewMatrix, s);
/*
// update bounding box
arrowBoundingBox.translate(0, -5);
arrowBoundingBox.rotate(rAngle);
arrowBoundingBox.translate(0, 1);
arrowBoundingBox.scale(0.3, -0.7);
*/
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_STRIP, 1833, 4);
gl.drawArrays( gl.LINE_STRIP, 1837, 4);
modelViewMatrix = modelViewStack.pop();
}
Your code looks quite correct, but you should eliminate the use of the rotateNumber. You can just use positive and negative angles for rotation instead, eliminating what I imagine is the cause of error here.
Sin and Cos can certainly handle angles of any magnitude positive, negative, or zero.
Good luck!
I figured out the problem. I was translating after rotating when I needed to translate before rotating as the rotation was messing up the translation.
I am trying to get my arduino code for gemma, with neopixels, which has 5310 bytes of memory smaller so I can get more things into the program.
Currently I am trying to remove floats / reduce the size of the code snippet below:
void gradient(Color c1, Color c2, float time) {
for (float i = 0; i < time; i += 0.001) {
Color result(0, 0, 0);
result.Red = c1.Red * (1 - (i / time)) + c2.Red * (i / time);
result.Green = c1.Green * (1 - (i / time)) + c2.Green * (i / time);
result.Blue = c1.Blue * (1 - (i / time)) + c2.Blue * (i / time);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(1);
}
}
I managed to reduce it by 30 bytes to:
void gradient(Color c1, Color c2, float time) {
float stepsize = 0.01; // Stepsize in seconds
float lambda;
int maxiter = (int) (time/ stepsize);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
lambda = (float) i / maxiter;
result.Red = c1.Red * (1 - lambda) + c2.Red * (lambda);
result.Green = c1.Green * (1 - lambda) + c2.Green * (lambda);
result.Blue = c1.Blue * (1 - lambda) + c2.Blue * (lambda);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(stepsize * 1000); // delay in milliseconds
}
}
But am trying still to make it smaller.
For those wondering the Color object is just an object with 3 ints called Red, Green and Blue. An example usage of this code would be:
gradient(Color(255, 0, 0), Color(0, 255, 0), 2);
Which would be a gradient from Red to Green over 2 seconds.
Thanks in advance!
If you can pull "delay()" out of all your code, it seems to avoid including a 100 byte size library? idk tbh, but here is my suggested modification, which in my testing saves 100 bytes of memory:
void gradient(Color c1, Color c2, float time) {
float stepsize = 0.01; // Stepsize in seconds
float lambda;
int maxiter = (int) (time/ stepsize);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
lambda = (float) i / maxiter;
result.Red = c1.Red * (1 - lambda) + c2.Red * (lambda);
result.Green = c1.Green * (1 - lambda) + c2.Green * (lambda);
result.Blue = c1.Blue * (1 - lambda) + c2.Blue * (lambda);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
//delay(stepsize * 1000); // delay in milliseconds
long lastTime=millis();
long delayTime = stepsize * 1000;
while(millis()-lastTime<delayTime){}
}
}
-First off, your color object should take 3 unsigned chars (0-255) there is no reason to put ints in there. (byte type in arduino)
-Second, I am not sure how you are implementing time, but generally in arduino you are working in milliseconds. Furthermore, without seeing your other implementation, I am guessing that time is a segment of time and based on your delay, I am going to guess that you could send time as a short (up multiply x1000 if necessary) (This would hold up to 32 seconds, in milliseconds)
void gradient(Color c1, Color c2, short time) {
short maxiter = (short) (time/ 10);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
result.Red = (c1.Red * (maxiter-i) + c2.Red * i)/maxiter;
result.Green = (c1.Green* (maxiter-i) + c2.Green* i)/maxiter;
result.Blue = (c1.Blue* (maxiter-i) + c2.Blue* i)/maxiter;
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(10); // delay in milliseconds
}
}
I have a function (shown below) that I need some advice on. The function returns the slope of a line which is fit (via the least squares method) to n data points. To give you a context, my project is a barometric pressure based altimeter which uses this function to determine velocity based on the n most recent altitude-time pairs. These altitude-time pairs are stored in 2 global arrays(times[] and alts[]).
My problem is not that this method doesn't work. It usually does. But sometimes I will run the altimeter and this function will return the value 'inf' interspersed with a bunch of other wrong values (I have also seen 'NaN' but that is more rare). There are a few areas of suspicion I have at this point but I would like a fresh perspective. Here is some further contextual information that may or may not be of use:
I am using interrupts for a quadrature encoder
The times[] array is of type unsigned long
The alts[] array is of type float
n is a const int, in this case n = 9
On the ATMEGA328 a double is the same as a float.. Arduino-double
float velF() { // uses the last n data points, fits a line to them,
// and uses the slope of that line as the velocity at that moment
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (int i = 0; i < n; i++) {
sumTY += (float)times[i] * alts[i] / 1000;
sumT += (float)times[i] / 1000;
sumY += alts[i];
sumT2 += (float)times[i] * times[i] / 1000000;
}
return (n*sumTY - sumT*sumY) / (n*sumT2 - sumT*sumT);
}
Any help or advice would be greatly appreciated!
Code is certainly performing division by zero.
For a variety of reasons, n*sumT2 - sumT*sumT will be zero. #John Bollinger In most of these cases, the top (dividend) of the division will also be zero and a return value of zero would be acceptable.
float velF(void) {
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (size_t i = 0; i < n; i++) {
// insure values are reasoable
assert(alts[i] >= ALT_MIN && alts[i] <= ALT_MAX);
assert(times[i] >= TIME_MIN && times[i] <= TIME_MAX);
sumTY += (float)times[i] * alts[i] / 1000;
sumT += (float)times[i] / 1000;
sumY += alts[i];
sumT2 += (float)times[i] * times[i] / 1000000;
}
float d = n*sumT2 - sumT*sumT;
if (d == 0) return 0;
return (n*sumTY - sumT*sumY) / d;
}
Side note: could factor out the division for improved accuracy and speed. Suggest performing the last calculation as double.
float velF(void) {
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (size_t i = 0; i < n; i++) {
float tf = (float) times[i];
sumTY += tf * alts[i];
sumT += tf;
sumY += alts[i];
sumT2 += tf * tf;
}
double nd = n;
double sumTd = sumT;
double d = nd*sumT2 - sumTd*sumTd;
if (d == 0) return 0;
return (nd*sumTY - sumTd*sumY)*1000 / d;
}
For my Arduino project I have a Neopixel RGB Strip with 72 LED's.
I can successfully change the colour of any of the LED's (at the moment I'm only setting the first one 0 for testing purposes) so I know my wiring isn't the problem here, it's my coding.
What I would like to do is be able to select a color and then another color and have the first color fade to the next color and so forth (much like the LIFX bulbs behave when using the iPhone application).
This is what I have at the moment:
I am logging output of all the variables to give you an indication of what's going on. I'm not 100% sure on where I'm going wrong or whether there's a much easier way to do what I'm after (I'm open to suggestions).
The function takes a parameter called command, which is a string separated by commas:
e.g. 255, 0, 0 (RED) or 0, 255, 0 (GREEN).
/*******************************************************************************
* Function Name : tinkerSetColour
* Description : Sets the strip with the appropriate colour
* Input : Pin and value
* Output : None.
* Return : 1 on success and a negative number on failure
*******************************************************************************/
int Rstart = 0, Gstart = 0, Bstart = 0;
int Rnew = 0, Gnew = 0, Bnew = 0;
int tinkerSetColour(String command)
{
sprintf(rgbString, "Rstart %i, Gstart %i, Bstart %i", Rstart, Gstart, Bstart);
Spark.publish("rgb", rgbString);
sprintf(rgbString, "Rnew %i, Gnew %i, Bnew %i", Rnew, Gnew, Bnew);
Spark.publish("rgb", rgbString);
// Clear strip.
strip.show();
int commaIndex = command.indexOf(',');
int secondCommaIndex = command.indexOf(',', commaIndex+1);
int lastCommaIndex = command.lastIndexOf(',');
int red = command.substring(0, commaIndex).toInt();
int grn = command.substring(commaIndex+1, secondCommaIndex).toInt();
int blu = command.substring(lastCommaIndex+1).toInt();
int Rend = red, Gend = grn, Bend = blu;
sprintf(rgbString, "Rend %i, Gend %i, Bend %i", Rend, Gend, Bend);
Spark.publish("rgb", rgbString);
// Larger values of 'n' will give a smoother/slower transition.
int n = 200;
for (int i = 0; i < n; i++)
{
Rnew = Rstart + (Rend - Rstart) * i / n;
Gnew = Gstart + (Gend - Gstart) * i / n;
Bnew = Bstart + (Bend - Bstart) * i / n;
// Set pixel color here.
strip.setPixelColor(0, strip.Color(Rnew, Gnew, Bnew));
}
sprintf(rgbString, "Rnew %i, Gnew %i, Bnew %i", Rnew, Gnew, Bnew);
Spark.publish("rgb", rgbString);
Rstart = red, Gstart = grn, Bstart = blu;
sprintf(rgbString, "Rstart %i, Gstart %i, Bstart %i", Rstart, Gstart, Bstart);
Spark.publish("rgb", rgbString);
return 1;
}
The problem is the colors are not fading between themselves.
Apologies if any of this is confusing. I can provide more information if necessary.
Here's the output selecting RED to begin with:
Rstart 0, Gstart 0, Bstart 0
Rnew 0, Gnew 0, Bnew 0
Rend 255, Gend 0, Bend 0
Rnew 253, Gnew 0, Bnew 0
Here's the output selecting GREEN directly afterwards:
Rstart 255, Gstart 0, Bstart 0
Rnew 253, Gnew 0, Bnew 0
Rend 0, Gend 255, Bend 0
Rnew 2, Gnew 253, Bnew 0
And then the output selecting BLUE after that:
Rstart 0, Gstart 255, Bstart 0
Rnew 2, Gnew 253, Bnew 0
Rend 0, Gend 23, Bend 255
Rnew 0, Gnew 25, Bnew 253
I've been working on the same problem for a couple days. I'm fairly new to arduino and coding so my code might be a bit simple, but for right now this seems to work.
I'm using the FastLED library.
#include "FastLED.h"
#define NUM_LEDS 15
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
int fade = 2; //minutes
byte cred; //current red
byte cgreen;
byte cblue;
byte targetred; //red after fade
byte targetgreen;
byte targetblue;
byte oldred; //red before fade
byte oldgreen;
byte oldblue;
byte deltared; //difference before and after fade
byte deltagreen;
byte deltablue;
unsigned long start;
unsigned long current;
unsigned long whole;
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
cred = 0; cblue = 0; cgreen = 0;
oldred = 0; oldblue = 0; oldgreen = 0;
update();
start = millis();
}
void loop() {
targetred = 20;
targetgreen = 220;
targetblue = 130;
deltared = targetred - oldred; deltagreen = targetgreen - oldgreen; deltablue = targetblue - oldblue;
whole = fade * 60000 + start; //fade time in milliseconds
if (cred <= targetred && millis() <= whole){
current = millis();
cred = current * deltared / whole;
cred = cred + oldred;}
if (cgreen <= targetgreen && millis() <= whole){
current = millis();
cgreen = current * deltagreen / whole;
cgreen = cgreen + oldgreen;}
if (cblue <= targetblue && millis() <= whole){
current = millis();
cblue = current * deltablue / whole;
cblue = cblue + oldblue;}
update();
}
void update(){
for (int i = 0; i <= NUM_LEDS; i++){
leds[i] = CRGB (cred, cgreen, cblue);
FastLED.show();
}};
This version doesn't actually fade to another colour afterwards, but you would just assign oldred = cred etc, then update your targetcolours. another thing is that this code is tuned to fade up due to the if cred <= target red. I originally was using != but sometimes ccolour would shoot past ctarget and keep going. I need to figure out how to set better tolerances. I am trying to avoid using delay so it will be easier later to receive outside input without lag.
Anyway, it's good to look at the same problem from different approaches, and this is another. Good luck with your fades!
I think your code is not so bad, you just need delays. Because your forloop will be too quick for you to notice the fading.
From a project I'm working on, here is a c++/pseudocode example for fading a led between to rgb colors.
It can be modified to work with your library pretty easily. The Serial.print() are for a debug purpose and can be removed once it works. Notice at the end of each loop iteration the waitMS(). you can also replace it with the Arduino delay() function.
void fade(uint16_t duration, Color startColor, Color endColor) {
int16_t redDiff = endColor.getR() - startColor.getR();
int16_t greenDiff = endColor.getG() - startColor.getG();
int16_t blueDiff = endColor.getB() - startColor.getB();
int16_t delay = 20;
int16_t steps = duration / delay;
int16_t redValue, greenValue, blueValue;
for (int16_t i = 0 ; i < steps - 1 ; ++i) {
redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);
Serial.print(redValue);
Serial.print("\t");
Serial.print(greenValue);
Serial.print("\t");
Serial.print(blueValue);
Serial.println("\t");
led.shine(redValue, greenValue, blueValue);
waitMs(delay);
}
led.shine(endColor);
}
Hope this helps :)
EDIT:
Here is links to the code of Color and Led:
Led Class
Color Class
In my processing application I want to translate a shape and scale it.
The coordinate, scale, and translate-values are saved in objects.
In each cycle I use the same translate-value per object and a bigger scale-value.
The problem is the 'scale' is somehow cumulated with the 'translate'- the scale does not happen in the middle of the object...
How can I setup the objects so the scaling happens at their center?
for (int i = 1; i < formen.size(); i++) {
Form f = formen.get(i);
pushMatrix();
f.sx = f.sx * 2;
f.sy = f.sy * 2;
scale(f.sx, f.sy);
translate(f.tx, f.ty);
noStroke();
createShape();
beginShape();
vertex(f.ax, f.ay);
bezierVertex(f.ax + f.kabx, f.ay, f.bx, f.by - f.kaby, f.bx, f.by);
bezierVertex(f.bx, f.by + f.kbcy, f.cx + f.kbcx, f.cy, f.cx, f.cy);
bezierVertex(f.cx - f.kcdx, f.cy, f.dx, f.dy + f.kcdy, f.dx, f.dy);
bezierVertex(f.dx, f.dy - f.kday, f.ax - f.kdax, f.ay, f.ax, f.ay);
endShape();
popMatrix();
delay(5);
}