Related
I have an intArray of ints corresponding to pixel RGB values and am trying to write them to an image that I then add to a canvas displayed in a view.
I have followed the JavaFX docs guideline for using a pixelWriter and I know my syntax for adding a canvas to the view is correct cause I have done the same elsewhere I my app and tested putting a different canvas here correctly.
I've tried the context way:
View class:
vbox(20.0, Pos.BOTTOM_CENTER) {
if (controller.t > 100) { //same results with or without this
label("IR camera view title")
children.add(controller.rPiSensors.canvasIR)
}
}
Model class:
val canvasIR = Canvas(lIR_WIDTH_RES.toDouble(), lIR_HEIGHT_RES.toDouble())
val gc: GraphicsContext = canvasIR.graphicsContext2D
var lIRPixelWriter = gc.pixelWriter
for (y in 0 until 32) {
for (x in 0 until 24) {
lIRPixelWriter.setPixels(0,0,lIR_WIDTH_RES,lIR_HEIGHT_RES, PixelFormat.getIntArgbInstance(), lIRHeatMapPixelInts, 0 , lIR_WIDTH_RES)
}
}
I've also tried the WritableImage way as mentioned in this SO post Creating a Javafx image from a int array:
View class:
vbox(20.0, Pos.BOTTOM_CENTER) {
if (controller.t > 100) { //same results with or without this
label("IR camera view title")
//tested this too controller.rPiSensors.imageView.show()
children.add(controller.rPiSensors.imageView)
}
}
Model class:
var lIRHeatMapPixelInts = IntArray(768) //24*32
//write to this in calculateIRPixelHelper below
var lIRHeatImage = WritableImage(lIR_WIDTH_RES, lIR_HEIGHT_RES)
var lIRPixelWriter = lIRHeatImage.pixelWriter
val imageView = ImageView(lIRHeatImage)
for (y in 0 until 32) {
for (x in 0 until 24) {
lIRPixelWriter.setPixels(0,0,lIR_WIDTH_RES,lIR_HEIGHT_RES, PixelFormat.getIntArgbInstance(), lIRHeatMapPixelInts, 0 , lIR_WIDTH_RES)
}
}
function to get IR RGBInt from float value of temperature (shown to be correct on RasPi that acquires data, and I have compared my received data vs snet RasPi data)
fun calculateIRPixelHelper(x : Int, y : Int, v : Float) {
//float color[NUM_COLORS][3] = { {0;0;0}; {0;0;1}; {0;1;0}; {1,1,0},{1,0,0}, {1,0,1}, {1,1,1} }
val color : Array<FloatArray> = arrayOf(floatArrayOf(0.0f,0.0f,0.0f), floatArrayOf(0.0f,0.0f,1.0f), floatArrayOf(0.0f,1.0f,0.0f), floatArrayOf(1.0f,1.0f,0.0f), floatArrayOf(1.0f,0.0f,0.0f), floatArrayOf(1.0f,0.0f,1.0f), floatArrayOf(1.0f,1.0f,1.0f))
var outputV = v
val idx1 : Int
val idx2 : Int
var fractBetween = 0.0f
val vmin = 5.0f
val vmax = 50.0f
val vrange = vmax-vmin
outputV -= vmin
outputV /= vrange
val ir : Int
val ig : Int
val ib : Int
val pixelRGBInt : Int
if (outputV <= 0) {
idx1= 0
idx2= 0
} else if (outputV >= 1) {
idx1 = (NUM_COLORS-1)
idx2 = (NUM_COLORS-1)
} else {
outputV *= (NUM_COLORS-1)
idx1 = truncate(outputV).toInt()
idx2 = idx1+1
fractBetween = outputV - idx1
}
ir = ((((color[idx2][0] - color[idx1][0]) * fractBetween) + color[idx1][0]) * 255.0).toInt()
ig = ((((color[idx2][1] - color[idx1][1]) * fractBetween) + color[idx1][1]) * 255.0).toInt()
ib = ((((color[idx2][2] - color[idx1][2]) * fractBetween) + color[idx1] [2]) * 255.0).toInt()
pixelRGBInt = (ir shl 16) or (ig shl 8) or ib
for(py in 0 until IMAGE_SCALE) {
for(px in 0 until IMAGE_SCALE) {
lIRHeatMapPixelInts[x + px + IMAGE_SCALE*(y + py)] = pixelRGBInt
}
}
}
Here are the float values of the temperature
the pixel ints, which are all 0 beyond the first ~50
And part of the list of values saved in the canvas
For the first method, there are 133K dirty bits written in the canvas and when I use the debugger it seems that PixelWriter.setPixels is writing over bits on almost every call but slowly progressing in increasing values (the trend is like this:
write val pos = 12, 30, 62, 12, 30, 62, 78, 99, 10 ...
I can copy down the exact numbers if this is suspected to be the issue)
In both cases I thought the issue was in updating the canvas once it's populated but I have eliminated this theory by only adding the canvas once a flag is set in the models--still nothing appears besides the title of the canvas.
I have spent about a full workday on trying to display this, any help would be GREATLY appreciated :)
Alpha bits were set to zero, must set them in the pixelRGBint high bits to non-zero for a non transparent pixel!
I am using an algorithm to create a 6 digit pin from a string of letters(I already have it). I also need to make different iterations of this 6 digit pin that would all lead back to the origin pin which can be used to generate the string of letters.
input "FEFOEISUDFRORI"
output 523923
some algorithm...
first iteration: 123203
then to authenticate
iteration: 1 ; pin: 123203
output: 'FEFOEISUDFRORI' // same as original string
Any idea how to do this?
The easiest way to solve this mathematical problem is probably with a rotation. Essentially performing an addition then a modulus, rotation will result in a one-to-one function with a range equal to it's domain.
The example I've shown will rotate the entire 6 digit number or the individual digits of the number.
function rRot(x, rot, max) {
if (rot < 0) return lRot(x,-rot,max);
rot = rot % max;
return (x + rot) % max;
}
function lRot(x, rot, max) {
if (rot < 0) return rRot(x,-rot,max);
rot = rot % max;
return rRot(x,max-rot,max);
}
function rotDigits(x, r) {
var pwr = 1, y = 0;
while (x > 0) {
var digit = x % 10;
y += rRot(digit, r, 10) * pwr;
x = Math.floor(x / 10);
pwr *= 10;
}
return y;
}
var samples = [675821, 126421, 678321, 100001, 580127, 999999];
(function () {
console.log("Rotate individual digits");
samples.forEach(v => {
var r = rotDigits(v, 7);
var vr = rotDigits(r, 10-7);
console.log(v.toString() + " => " + r.toString() + " => " + vr.toString());
});
console.log("Rotate whole number");
samples.forEach(v => {
var r = rRot(v, 65537, 1000000);
var vr = lRot(r, 65537, 1000000);
console.log(v.toString() + " => " + r.toString() + " => " + vr.toString());
});
})()
Updates
Updated fiddle to simplify what is going on:
added four buttons to move the stick, each button increments the value by 30 in the direction
plotted x and y axis
red line is the stick, with bottom end coordinates at (ax,ay) and top end coordinates at (bx,by)
green line is (presumably) previous position of the stick, with bottom end coordinates at (ax, ay) and top end coordinates at (bx0, by0)
So, after having my ninja moments. I'm still nowhere near understanding the sorcery behind unknownFunctionA and unknownFunctionB
For the sake of everyone (all two of you) here is what I've sort of learnt so far
function unknownFunctionB(e) {
var t = e.b.x - e.a.x
, n = e.b.y - e.a.y
, a = t * t + n * n;
if (a > 0) {
if (a == e.lengthSq)
return;
var o = Math.sqrt(a)
, i = (o - e.length) / o
, s = .5;
e.b.x -= t * i * .5 * s,
e.b.y -= n * i * .5 * s
}
}
In the unknownFunctionB above, variable o is length of the red sitck.
Still don't understand
What is variable i and how is (bx,by) calculated? essentially:
bx = bx - (bx - ax) * 0.5 * 0.5
by = by - (by - ay) * 0.5 * 0.5
In unknownFunctionA what are those magic numbers 1.825 and 0.825?
Below is irrelevant
I'm trying to deconstruct marker drag animation used on smartypins
I've managed to get the relevant code for marker move animation but I'm struggling to learn how it all works, especially 2 functions (that I've named unknownFunctionA and unknownFunctionB)
Heres the StickModel class used on smartypins website, unminified to best of my knowledge
function unknownFunctionA(e) {
var t = 1.825
, n = .825
, a = t * e.x - n * e.x0
, o = t * e.y - n * e.y0 - 5;
e.x0 = e.x,
e.y0 = e.y,
e.x = a,
e.y = o;
}
function unknownFunctionB(e) {
var t = e.b.x - e.a.x
, n = e.b.y - e.a.y
, a = t * t + n * n;
if (a > 0) {
if (a == e.lengthSq)
return;
var o = Math.sqrt(a)
, i = (o - e.length) / o
, s = .5;
e.b.x -= t * i * .5 * s,
e.b.y -= n * i * .5 * s
}
}
function StickModel() {
this._props = function(e) {
return {
length: e,
lengthSq: e * e,
a: {
x: 0,
y: 0
},
b: {
x: 0,
y: 0 - e,
x0: 0,
y0: 0 - e
},
angle: 0
}
}
(60)
}
var radianToDegrees = 180 / Math.PI;
StickModel.prototype = {
pos: {
x: 0,
y: 0
},
angle: function() {
return this._props.angle
},
reset: function(e, t) {
var n = e - this._props.a.x
, a = t - this._props.a.y;
this._props.a.x += n,
this._props.a.y += a,
this._props.b.x += n,
this._props.b.y += a,
this._props.b.x0 += n,
this._props.b.y0 += a
},
move: function(e, t) {
this._props.a.x = e,
this._props.a.y = t
},
update: function() {
unknownFunctionA(this._props.b),
unknownFunctionB(this._props),
this.pos.x = this._props.a.x,
this.pos.y = this._props.a.y;
var e = this._props.b.x - this._props.a.x
, t = this._props.b.y - this._props.a.y
, o = Math.atan2(t, e);
this._props.angle = o * radianToDegrees;
}
}
StickModel.prototype.constructor = StickModel;
Fiddle link with sample implementation on canvas: http://jsfiddle.net/vff1w82w/3/
Again, Everything works as expected, I'm just really curious to learn the following:
What could be the ideal names for unknownFunctionA and unknownFunctionB and an explanation of their functionality
What are those magic numbers in unknownFunctionA (1.825 and .825) and .5 in unknownFunctionB.
Variable o in unknownFunctionB appears to be hypotenuse. If that's the case, then what exactly is i = (o - e.length) / o in other words, i = (hypotenuse - stickLength) / hypotenuse?
First thing I'd recommend is renaming all those variables and methods until they start making sense. I also removed unused code.
oscillator
adds wobble to the Stick model by creating new position values for the Stick that follows the mouse
Exaggerates its movement by multiplying its new position by 1.825 and also subtracting the position of an "echo" of its previous position multiplied by 0.825. Sort of looking for a middle point between them. Helium makes the stick sit upright.
overshooter minus undershooter must equal 1 or you will have orientation problems with your stick. overshooter values above 2.1 tend to make it never settle.
seekerUpdate
updates the seeker according to mouse positions.
The distance_to_cover variable measures the length of the total movement. You were right: hypothenuse (variable o).
The ratio variable calculates the ratio of the distance that can be covered subtracting the size of the stick. The ratio is then used to limit the adjustment of the update on the seeker in both directions (x and y). That's how much of the update should be applied to prevent overshooting the target.
easing slows down the correct updates.
There are lots of interesting info related to vectors on the book The nature of code.
function oscillator(seeker) {
var overshooter = 1.825;
var undershooter = .825;
var helium = -5;
var new_seeker_x = overshooter * seeker.x - undershooter * seeker.echo_x;
var new_seeker_y = overshooter * seeker.y - undershooter * seeker.echo_y + helium;
seeker.echo_x = seeker.x;
seeker.echo_y = seeker.y;
seeker.x = new_seeker_x;
seeker.y = new_seeker_y;
}
function seekerUpdate(stick) {
var dX = stick.seeker.x - stick.mouse_pos.x;
var dY = stick.seeker.y - stick.mouse_pos.y;
var distance_to_cover = Math.sqrt(dX * dX + dY * dY);
var ratio = (distance_to_cover - stick.length) / distance_to_cover;
var easing = .25;
stick.seeker.x -= dX * ratio * easing;
stick.seeker.y -= dY * ratio * easing;
}
function StickModel() {
this._props = function(length) {
return {
length: length,
lengthSq: length * length,
mouse_pos: {
x: 0,
y: 0
},
seeker: {
x: 0,
y: 0 - length,
echo_x: 0,
echo_y: 0 - length
}
}
}(60)
}
StickModel.prototype = {
move: function(x, y) {
this._props.mouse_pos.x = x;
this._props.mouse_pos.y = y;
},
update: function() {
oscillator(this._props.seeker);
seekerUpdate(this._props);
}
};
StickModel.prototype.constructor = StickModel;
// Canvas to draw stick model coordinates
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
canvas.width = window.outerWidth;
canvas.height = window.outerHeight;
var canvasCenterX = Math.floor(canvas.width / 2);
var canvasCenterY = Math.floor(canvas.height / 2);
context.translate(canvasCenterX, canvasCenterY);
var stickModel = new StickModel();
draw();
setInterval(function() {
stickModel.update();
draw();
}, 16);
$(window).mousemove(function(e) {
var mouseX = (e.pageX - canvasCenterX);
var mouseY = (e.pageY - canvasCenterY);
stickModel.move(mouseX, mouseY);
stickModel.update();
draw();
});
function draw() {
context.clearRect(-canvas.width, -canvas.height, canvas.width * 2, canvas.height * 2);
// red line from (ax, ay) to (bx, by)
context.beginPath();
context.strokeStyle = "#ff0000";
context.moveTo(stickModel._props.mouse_pos.x, stickModel._props.mouse_pos.y);
context.lineTo(stickModel._props.seeker.x, stickModel._props.seeker.y);
context.fillText('mouse_pos x:' + stickModel._props.mouse_pos.x + ' y: ' + stickModel._props.mouse_pos.y, stickModel._props.mouse_pos.x, stickModel._props.mouse_pos.y);
context.fillText('seeker x:' + stickModel._props.seeker.x + ' y: ' + stickModel._props.seeker.y, stickModel._props.seeker.x - 30, stickModel._props.seeker.y);
context.lineWidth = 1;
context.stroke();
context.closePath();
// green line from (ax, ay) to (bx0, by0)
context.beginPath();
context.strokeStyle = "#00ff00";
context.moveTo(stickModel._props.mouse_pos.x, stickModel._props.mouse_pos.y);
context.lineTo(stickModel._props.seeker.echo_x, stickModel._props.seeker.echo_y);
context.fillText('echo x:' + stickModel._props.seeker.echo_x + ' y: ' + stickModel._props.seeker.echo_y, stickModel._props.seeker.echo_x, stickModel._props.seeker.echo_y - 20);
context.lineWidth = 1;
context.stroke();
context.closePath();
// blue line from (bx0, by0) to (bx, by)
context.beginPath();
context.strokeStyle = "#0000ff";
context.moveTo(stickModel._props.seeker.echo_x, stickModel._props.seeker.echo_y);
context.lineTo(stickModel._props.seeker.x, stickModel._props.seeker.y);
context.stroke();
context.closePath();
}
body {
margin: 0px;
padding: 0px;
}
canvas {
display: block;
}
p {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<p>Move your mouse to see the stick (colored red) follow</p>
<canvas id="myCanvas"></canvas>
I am trying to scale a skeleton to match to the sizes of another skeleton.
My algoritm do the following:
Find the distance between two joints of the origin skeleton and the destiny skeleton using phytagorean teorem
divide this two distances to find a multiply factor.
Multiply each joint by this factor.
Here is my actual code:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny)
{
Joint newJoint = new Joint();
double distanciaOrigem = 0;
double distanciaDestino = 0;
double fator = 1;
SkeletonPoint pos = new SkeletonPoint();
foreach (BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanciaOrigem = FisioKinectCalcs.Distance3DBetweenJoint(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanciaDestino = FisioKinectCalcs.Distance3DBetweenJoint(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if (distanciaOrigem > 0 && distanciaDestino > 0)
{
fator = (distanciaDestino / distanciaOrigem);
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
// applying the new values to the joint
pos = new SkeletonPoint()
{
X = (float)(newJoint.Position.X * fator),
Y = (float)(newJoint.Position.Y * fator),
Z = (float)(newJoint.Position.Z * fator)
};
newJoint.Position = pos;
skToBeScaled.Joints[bo.EndJoint] = newJoint;
}
}
return skToBeScaled;
}
Every seems to work fine except for the hands and foots
Look at this images
I have my own skeleton over me, and my skeleton scaled to the sizes of another person, but the hands and foots still crazy. (but code looks right)
Any suggestion?
It's hard to say without running the code, but it somewhat "looks good".
What I would validate though, is your
if (distanciaOrigem > 0 && distanciaDestino > 0)
If distanciaOrigem is very close to 0, but even just epsilon away from 0, it won't be picked up by the if, and then
fator = (distanciaDestino / distanciaOrigem);
Will result in a very large number!
I would suggest to smooth the factor so it generally fits the proper scale. Try this code:
private static Dictionary<JointType, double> jointFactors = null;
static CalibrationUtils()
{
InitJointFactors();
}
public static class EnumUtil
{
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
private static void InitJointFactors()
{
var jointTypes = EnumUtil.GetValues<JointType>();
jointFactors = new Dictionary<JointType, double>();
foreach(JointType type in jointTypes)
{
jointFactors.Add(type, 0);
}
}
private static double SmoothenFactor(JointType jointType, double factor, int weight)
{
double currentValue = jointFactors[jointType];
double newValue = 0;
if(currentValue != 0)
newValue = (weight * currentValue + factor) / (weight + 1);
else
newValue = factor;
jointFactors[jointType] = newValue;
return newValue;
}
When it comes to factor usage just use the SmoothenFactor method first:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny, double additionalFactor = 1)
{
Joint newJoint = new Joint();
double distanceToScale = 0;
double distanceDestiny = 0;
double factor = 1;
int weight = 500;
SkeletonPoint pos = new SkeletonPoint();
Skeleton newSkeleton = null;
KinectHelper.CopySkeleton(skToBeScaled, ref newSkeleton);
SkeletonPoint hipCenterPosition = newSkeleton.Joints[JointType.HipCenter].Position;
foreach(BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanceToScale = Distance3DBetweenJoints(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanceDestiny = Distance3DBetweenJoints(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if(distanceToScale > 0 && distanceDestiny > 0)
{
factor = (distanceDestiny / distanceToScale) * additionalFactor;
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
factor = SmoothenFactor(newJoint.JointType, factor, weight);
pos = new SkeletonPoint()
{
X = (float)((newJoint.Position.X - hipCenterPosition.X) * factor + hipCenterPosition.X),
Y = (float)((newJoint.Position.Y - hipCenterPosition.Y) * factor + hipCenterPosition.Y),
Z = (float)((newJoint.Position.Z - hipCenterPosition.Z) * factor + hipCenterPosition.Z)
};
newJoint.Position = pos;
newSkeleton.Joints[bo.EndJoint] = newJoint;
}
}
return newSkeleton;
}
I also modified your ScaleToMatch method as you see. There was a need to move joints in relation to HipCenter position. Also new positions are saved to a new Skeleton instance so they are not used in further vector calculations.
Experiment with the weight but since our bones length is constant you can use big numbers like 100 and more to be sure that wrong Kinect readings do not disturb the correct scale.
Here's an example of how it helped with scaling HandRight joint position:
The weight was set to 500. The resulting factor is supposed to be around 2 (because the base skeleton was purposely downscaled by a factor of 2).
I hope it helps!
I am creating a Sudoku Puzzle in asp and I'm having trouble with some classes. When I create a function to display all the numbers in the text box, I get this error: Object reference not set to an instance of an object. I know that it means that my object is null, but here is my code. The line that I am getting the error on is the line that says: stbNumber.setNumber(currentSolution[3 * i + m, 3 * k + n]);
private SudokuTextBox stb;
private Puzzle puzzle;
private Box box;
private Number stbNumber;
public void displayAll(object sender,EventArgs e)
{
puzzle = new Puzzle();
for (int i = 0; i < 3; i++)
{
for (int k = 0; k < 3; k++)
{
box = new Box();
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
stbNumber = new Number();
stb = new SudokuTextBox();
stbNumber.setNumber(currentSolution[3 * i + m, 3 * k + n]);
stb.setTextBoxValue(stbNumber);
stb.setVisibility(true);
box.setItem(stb, m, n);
}// end forth for
}//end third for
puzzle.setItem(box, i, k);
}//end second for
}//end first for
generateBoxes();
}
I have initialized stbNumber at the very top of my code, and I have made sure that currentSolution is not null or empty. I'm therefore unsure as to what I am doing wrong. I also should mention that I have this exact code elsewhere to generate new puzzles and it works just fine, but this section of code specifically gets called when I click a button.
you essentially have 3 possibilities:
stbNumber.setNumber(currentSolution[3 * i + m, 3 * k + n]);
stbNumber could be null
currentSolution could be null
the element you are trying to index could be null--just because currentSolution is not null does not mean the item is at that index is not null--so new one up or take appropriate action
since you new up an instance of stbNumber, it is unlikely to be the culprit (but it could be)
you say you are checking currentSolution is null, I don't see the code for that and from the code you did post it is most likely the culprit here. what you COULD do is add a check for null before you access it, and if your test fails writing an error message somewhere:
stbNumber = new Number();
stb = new SudokuTextBox();
if ( currentSolution != null )
{
// if the item does not exist, new it up
if ( currentSolution[3 * i + m, 3 * k + n] == null ) currentSolution[3 * i + m, 3 * k + n] = new someObject()
stbNumber.setNumber(currentSolution[3 * i + m, 3 * k + n]);
stb.setTextBoxValue(stbNumber);
}
else
{
WriteSomeErrorMessage("currentSolution is null");
}