Turn on specific LED using NeoPixel module for Espruino? - espruino

I am trying to turn on a specific LED using the NeoPixel module. How it works is really easy: Parse it a 2D array of RGB colors. Here's an example:
require("neopixel").write(NodeMCU.B2, [[255, 0, 0], [0, 255, 0], [0, 0, 255]]);
That will turn on the first three LEDs with red, green, and blue. I want to have a function, where I can do something like:
function single(number, color) {
require("neopixel").write(NodeMCU.B2, number, color);
}
single(0, [255, 0, 0]);
single(1, [0, 255, 0]);
single(2, [0, 0, 255]);
Which would do the exact same as above. Now you might ask: Why would you want that? Well:
I want it to remember the last "configuration" of LEDs, so I can update it over time
If I want to turn off all my 100+ LEDs and just turn on the last few (or the ones in the middle), I wouldn't have to parse the write() function 100+ LEDs, where most of them are black
Is something like that possible, or would I have to do some magic in order to remember the last LED configuration?

Yes, totally - it's worth looking at the neopixel docs at http://www.espruino.com/WS2811 as they suggest you use an array to
store the current state.
Once you have that array - called arr here - you can use the .set method to set the 3 elements at the right position (3x the number, because RGB), and then can resend the whole array.
var arr = new Uint8ClampedArray(NUM_OF_LEDS*3);
function single(number, color) {
arr.set(color, number*3);
require("neopixel").write(NodeMCU.B2, arr);
}

Related

Flutter - How to change color of marker based on magnitude of an int?

I want to create markers at each GPS point with a color on a scale from white to red that corresponds to how slow or fast the GPS data indicates the speed is at that point. However, since Color.fromRGBO() requires const arguments, I'm having trouble getting the speed to change the color. How could I circumvent the Color class or find a better way to draw such a gradient than with Marker objects?
Welcome to StackOverflow Onur!
You can indeed use https://api.flutter.dev/flutter/dart-ui/Color/Color.fromARGB.html
const Color.fromARGB(
int a,
int r,
int g,
int b
)
with a=0, g=0 and b=0 and use your scale (you need to know the maximum value, lets call it r_max, to normalize the range). So whenever you have an intensity value, lets call it r_intensity, you'd simply compute
const r = 255 * (r_intensity / r_max)
to compute your color intensity. The result of r_intensity / r_max will always be in range [0, 1] multiplied by 255 to conform with
r is red, from 0 to 255.
from the docs.
Regarding the const issue: it sounds like you want to (heavily?) animate the color. Look at https://api.flutter.dev/flutter/animation/AnimationController-class.html and set the red color value to your Widgets state.
Other than that, it should work to either have
a method that returns the new red value (and does the aforementioned computation)
simply use var r = ... instead of const r = ... and pass it to Color
EDIT: looking at your image, the issue might stem from your int being null. Please make sure that your Color Widget is not wrapped into any Widget prefixed with const! This will likely be the case here and produces the result you are seeing. Tested it on my side to confirm.

How to use geoserver SLD style to serve single channel elevation raster ("gray" channel) as Mapbox Terrain-RGB tiles

I have an elevation raster layer in my GeoServer with a single channel ("gray").
The "gray" values is elevations values (signed int16).
I have 2 clients:
The first one is using that elevation values as is.
The second one expect to get [Mapbox Terrain-RGB format][1]
I do not want to convert the "gray scale" format to Mapbox Terrain-RGB format and hold duplicate data in the GeoServer.
I was thinking to use the SLD style and elements to map the elevation value to the appropriate RGB value (with gradient interpolation between discrete values).
For example:
<ColorMap>
<ColorMapEntry color="#000000" quantity="-10000" />
<ColorMapEntry color="#FFFFFF" quantity="1667721.5" />
</ColorMap>
It turns out that the above example does not span the full range of colors but rather creates gray values only.
That is, it seems that it interpolate each color (red, green, blue) independent of each other.
Any idea how to make it interpolate values like that: #000000, #000001, #000002, ... , #0000FF, #000100, ..., #0001FF, ..., #FFFFFF?
Tx.
[1]: https://docs.mapbox.com/data/tilesets/reference/mapbox-terrain-rgb-v1/
I'm trying to do the same with no luck, and i think it can't be done... Check this example. It's a "gradient" [-10000, -5000, -1000, -500 ... 100000000000000000, 5000000000000000000, 1000000000000000000] with the Mapbox color codification. The color progression/interpolation is anything but linear, so i think it can't be emulated in an SLD.
If you have the elevation data in the format you desire then that is the easiest option: it just works. However, if you want a more customized solution, here's what I've done for a project using the Mapbox Terrain-RGB format:
I have a scale of colors from dark blue to light blue to white.
I want to be able to specify how many steps are used from light blue to white (default is 10).
This code uses GDAL Python bindings. The following code snippet was used for testing.
It just outputs the color mapping to a GeoTIFF file.
To get values between 0 and 1, simply use value *= 1/num_steps.
You can use that value in the lookup table to get an RGB value.
If you're only interested in outputting the colors, you can ignore everything involving gdal_translate. The colors will automatically be stored in a single-band GeoTIFF. If you do want to re-use those colors, note that this version ignores alpha values (if present). You can use gdal_translate to add those. That code snippet is also available at my gist here.
import numpy as np
import gdal
from osgeo import gdal, osr
def get_color_map(num_steps):
colors = np.zeros((num_steps, 3), dtype=np.uint8)
colors[:, 0] = np.linspace(0, 255, num_steps, dtype=np.uint8)
colors[:, 1] = colors[::-1, 0]
return colors
ds = gdal.Open('/Users/myusername/Desktop/raster.tif')
band = ds.GetRasterBand(1) # Assuming single band raster
arr = band.ReadAsArray()
arr = arr.astype(np.float32)
arr *= 1/num_steps # Ensure values are between 0 and 1 (or use arr -= arr.min() / (arr.max() - arr.min()) to normalize to 0 to 1)
colors = get_color_map(num_steps) # Create color lookup table
colors[0] = [0, 0, 0] # Set black for no data so it doesn't show up as gray in the final product.
# Create new GeoTIFF with colors included (transparent alpha channel if possible). If you don't care about including the colors in the GeoTIFF, skip this.
cols = ds.RasterXSize
rows = ds.RasterYSize
out_ds = gdal.GetDriverByName('GTiff').Create('/Users/myusername/Desktop/raster_color.tif', cols, rows, 4)
out_ds.SetGeoTransform(ds.GetGeoTransform())
out_ds.SetProjection(ds.GetProjection())
band = out_ds.GetRasterBand(1)
band.WriteArray(colors[arr]) # This can be removed if you don't care about including the colors in the GeoTIFF
band = out_ds.GetRasterBand(2)
band.WriteArray(colors[arr]) # This can be removed if you don't care about including the colors in the GeoTIFF
band = out_ds.GetRasterBand(3)
band.WriteArray(colors[arr]) # This can be removed if you don't care about including the colors in the GeoTIFF
band = out_ds.GetRasterBand(4)
alpha = np.zeros((rows, cols), dtype=np.uint8) # Create alpha channel to simulate transparency of no data pixels (assuming 0 is "no data" and non-zero is data). You can remove this if your elevation values are not 0.
alpha[arr == 0] = 255
band.WriteArray(alpha) # This can be removed if you don't care about including the colors in the GeoTIFF
out_ds.FlushCache()
This issue is also present in Rasterio when using a palette with multiple values. Here is an example.
However, if your raster has n-dimensions or is a masked array, the flip operation can be tricky. Here's a solution based on one of the answers in this stackoverflow question: How to vertically flip a 2D NumPy array?.

How to label ('vertically') points in graph

I would like to add labels to some points plotted using the command scatter. For the sake of simplicity, let's say I have only one point:
x = 10;
pointSize = 100;
fontSize = 20;
P = scatter(x, 0, pointSize, [0,0,0], 'filled');
text(x, 0, 'pointLabel',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom',...
'FontSize', fontSize);
The problem with the previous commands is that the text pointLabel overlaps with the point P depending on the values assigned to the properties pointsize and fontSize.
I have read the documentation of the text command, but the examples only show how to put a label horizontally aligned with a specific point in the diagram. If the alignment needs to be horizontal it is easy, but I could not find a general way to compute the y coordinate of the label pointLabel from the values of the other dimensions.
Clearly I can reach a good alignment by testing various combinations of values, but I am looking for a general solution.
Is there anyone who can help me?
This assumes you are using >=R2014b, though it can also be accomplished in older versions using set and get commands.
When a text object is created, its default units are data coordinates, but those can be changed. In your case, I'd go with points.
x = 10;
pointSize = 100;
fontSize = 20;
P = scatter(x, 0, pointSize, [0,0,0], 'filled');
t = text(x, 0, 'pointLabel',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom',...
'FontSize', fontSize);
% It's always a good idea to switch back to the default units, so remember them.
originalUnits = t.Units;
t.Units = 'points';
% Shift the text up by the sqrt(pi)/2 times the radius of the point
t.Position(2) = t.Position(2) + sqrt(pointSize)/2;
t.Units = originalUnits;
Check out Text Properties for more info. If you want to get really sophisticated, you can use the read-only property Extent and your known marker size and position to calculate when a label is overlapping one of your points. Since the default unit is in data space, no conversions are necessary.
If you're working with an older version of MATLAB, all of these options and properties are still available, you just have to work a little harder to use them. For instance, you can't direction set the position as above, but you would instead use get to assign it to a temporary variable, change it, and then use set to update. More lines of code, but ultimately the same effect.

CGAffineTransform help, flipping a label

I basically have a pie chart where I have lines coming out of each segment of the pie chart. So in the case where the line comes out of the circle to the left, when I draw my text, it is reversed. "100%" would look like => "%001" (Note, the 1 and % sign are actually drawn in reverse to, like if a mirror. So the little overhang on top of the 1 points to the right, rather than the left.)
I tried reading through Apple's docs for the AffineTransform, but it doesn't make complete sense to me. I tried making this transformation matrix to start:
CGAffineTransform transform1 = CGAffineTransformMake(-1, 0, 0, 1, 0, 0);
This does flip the text around its x-axis so the text now looks correct on the left side of the circle. However, the text is now on the line, rather than at the end of the line like it originally was. So I thought I could translate it by moving the text in the x-axis direction by changing the tx value in the matrix. So instead of using the above matrix, I used this:
CGAffineTransform transform1 = CGAffineTransformMake(-1, 0, 0, 1, -strlen(t1AsChar), 0);
However, the text just stays where it's at. What am I doing wrong? Thanks.
strlen() doesn't give you the size of the rendered text box, it just gives you the length of the string itself (how many characters that string has). If you're using a UITextField you can use textField.frame.size.width instead.

Iphone OpengGL : Editing the MODELVIEW_MATRIX

I working on a spinning 3D cube (glFrustumf setup) and it multiplies the current matrix by the previous one so that the cube continues to spin. See below
/* save current rotation state */
GLfloat matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
/* re-center cube, apply new rotation */
glLoadIdentity();
glRotatef(self.angle, self.dy,self.dx,0);
glMultMatrixf(matrix);
The problem is I need to step back from this (as if I had a camera).
I tried to edit the matrix and that kind of works but picks up noise. The cube jumps around.
matrix[14] = -5.0;
matrix[13] = 0;
matrix[12] =0;
Is there a way to edit the current Modelview Matrix so that I can set the position of the cube with multiplying it by another matrix?
You should not mistreat OpenGL as a scene graph, nor a math library. That means: Don't read back the matrix, and multiply it arbitrarily back. Instead rebuild the whole matrix stack a new every time you do a render pass. I think I should point out, that in OpenGL-4 all the matrix functions have been removed. Instead you're expected to supply the matrices as uniforms.
EDIT due to comment by #Burf2000:
Your typical render handler will look something like this (pseudocode):
draw_object():
# bind VBO or plain VertexArrays (you might even use immediate mode, but that's deprecated)
# draw the stuff using glDrawArrays or better yet glDrawElements
render_subobject(object, parent_transform):
modelview = parent_tranform * object.transform
if OPENGL3_CORE:
glUniformMatrix4fv(object.shader.uniform_location[modelview], 1, 0, modelview)
else:
glLoadMatrixf(modelview)
draw_object(object)
for subobject in object.subobjects:
render_subobject(subobject, modelview)
render(deltaT, window, scene):
if use_physics:
PhysicsSimulateTimeStep(deltaT, scene.objects)
else:
for o in scene.objects:
o.animate(deltaT)
glClearColor(...)
glClearDepth(...)
glViewport(0, 0, window.width, window.height)
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)
# ...
# now _some_ objects' render pass - others may precede or follow, like for creating reflection cubemaps or water refractions.
glViewport(0, 0, window.width, window.height)
glEnable(GL_DEPTH_TEST)
glDepthMask(1)
glColorMask(1,1,1,1)
if not OPENGL3_CORE:
glMatrixMode(GL_PROJECTION)
glLoadMatrixf(scene.projection.matrix)
for object in scene.objects:
bind_shader(object.shader)
if OPENGL3_CORE:
glUniformMatrix4fv(scene.projection_uniform, 1, 0, scene.projection.matrix)
# other render passes
glViewport(window.HUD.x, window.HUD.y, window.HUD.width, window.HUD.height)
glStencil(window.HUD.x, window.HUD.y, window.HUD.width, window.HUD.height)
glEnable(GL_STENCIL_TEST)
glDisable(GL_DEPTH_TEST)
if not OPENGL3_CORE:
glMatrixMode(GL_PROJECTION)
glLoadMatrixf(scene.HUD.projection.matrix)
render_HUD(...)
and so on. I hope you get the general idea. OpenGL is neither a scene graph, nor a matrix manipulation library.