I'm trying to project 4D lines to 3D to 2D and clip them at z=p and w=p, but I'm not sure if it's rendering correctly - rendering

I've been trying to write a program that can render 4D lines, the specific function doing this gets the lines already rotated, and the function attempts to clip the lines at planes z = p and w = p if needed, and then draw the line to the screen.
I think that I am doing at least most of this properly, however I am unsure, and not having much experience viewing the fourth dimension I cannot tell what might be a visual bug, or what is actually how it should be rendered.
The function first loads a line into two variables, each is one of the two endpoints of the line. If both points are beyond clippl (the clipping plane variable) for z = clippl and w = clippl, it then applies perspective transformation to them, and subsequently renders a line on the screen correspondingly.
If certain logic is met for the points, the function goes through a process of clipping them, and then continues the same as it would outside the clipping planes.
The location of the camera is held in the variables Ox, Oy, Oz, Ow at the beginning of the full program.
I can't tell if I've done this properly, can anyone tell me if this works right as a 4D perspective projection from a first person camera?
EDIT: I've added points to the rendering list that are at the corners of the cube I'm rendering, and it seems to show that there is in fact some problem with the line clipping, as I am fairly certain that the points are rendering properly, and there is not always a line showing up at it. Could the problem have to do with the w = p clip?
Here's the function, the program uses p5.js:
function drawPLines(P){
var lA,lB;
for(var i=0;i<P.length;i++){
lA = [P[i][0],P[i][1],P[i][2],P[i][3]];
lB = [P[i][4],P[i][5],P[i][6],P[i][7]];
//X: ( x*VS+(width*0.5)+(ox*VS) )
//Y: ( y*VS+(height*0.5)+(oy*VS) )
//x: (XV[0]*P[i][0])+(YV[0]*P[i][1])+(ZV[0]*P[i][2])+(WV[0]*P[i][3])
//y: (XV[1]*P[i][0])+(YV[1]*P[i][1])+(ZV[1]*P[i][2])+(WV[1]*P[i][3])
var x0,y0,x1,y1;
//x0 = (XV[0]*lA[0])+(YV[0]*lA[1])+(ZV[0]*lA[2])+(WV[0]*lA[3]);
//y0 = (XV[1]*lA[0])+(YV[1]*lA[1])+(ZV[1]*lA[2])+(WV[1]*lA[3]);
//new rendering pipeline
//old rendering pipeline
if(lA[2]>clippl&&lB[2]>clippl&&lA[3]>clippl&&lB[3]>clippl){
x0 = XV[0]*lA[0];
y0 = YV[1]*lA[1];
x0 = (x0/lA[3])/(lA[2]/lA[3]);
y0 = (y0/lA[3])/(lA[2]/lA[3]);
//console.log(y);
x0 = ( x0*VS+(width*0.5)+(ox*VS) );
y0 = ( y0*VS+(height*0.5)+(oy*VS) );
//x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
//y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
x1 = XV[0]*lB[0];
y1 = YV[1]*lB[1];
x1 = (x1/lB[3])/(lB[2]/lB[3]);
y1 = (y1/lB[3])/(lB[2]/lB[3]);
//console.log(y);
x1 = ( x1*VS+(width*0.5)+(ox*VS) );
y1 = ( y1*VS+(height*0.5)+(oy*VS) );
stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
line(x0,y0,x1,y1);
}else if((lA[2]>clippl||lA[3]>clippl||lB[2]>clippl||lB[3]>clippl)){
var V = 0;
var zV = 0;
var wV = 0;
//var oV = 0;
if(lA[2]>clippl&&lA[3]>clippl){
V++;
}else if(lA[2]>clippl&&lA[3]<=clippl){
zV++;
}else if(lA[2]<=clippl&&lA[3]>clippl){
wV++;
}/*else{
oV++;
}*/
if(lB[2]>clippl&&lB[3]>clippl){
V++;
}else if(lB[2]>clippl&&lB[3]<=clippl){
zV++;
}else if(lB[2]<=clippl&&lB[3]>clippl){
wV++;
}/*else{
oV++;
}*/
if((V==1)||(wV==1&&(V==1||zV==1))||(zV==1&&(V==1||wV==1))){
var lin = lB;
var out = lA;
if(lA[2]<=clippl){
out = lB;
lin = lA;
}
if(lin[2]<=clippl){
lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[2]))/(lA[2]-lB[2]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[2]))/(lA[2]-lB[2]))+lB[1],clippl,((((lA[3]-lB[3])*clippl)-((lA[3]-lB[3])*lB[2]))/(lA[2]-lB[2]))+lB[3]];
}
if((lA[2]-lB[2])!==0){
lA = lin;
lB = out;
}
lin = lA;
out = lB;
if(lB[3]<=clippl){
out = lA;
lin = lB;
}
if(lin[3]<=clippl){
lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[3]))/(lA[3]-lB[3]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[3]))/(lA[3]-lB[3]))+lB[1],((((lA[2]-lB[2])*clippl)-((lA[2]-lB[2])*lB[3]))/(lA[3]-lB[3]))+lB[2],clippl];
//alert(lin);
//alert(out);
}
if((lA[3]-lB[3])!==0){
lA = lin;
lB = out;
}
if(lA[2]>clippl||lB[2]>clippl||lA[3]>clippl||lB[3]>clippl){
x0 = XV[0]*lA[0];
y0 = YV[1]*lA[1];
x0 = (x0/lA[3])/(lA[2]/lA[3]);
y0 = (y0/lA[3])/(lA[2]/lA[3]);
//console.log(y);
x0 = ( x0*VS+(width*0.5)+(ox*VS) );
y0 = ( y0*VS+(height*0.5)+(oy*VS) );
//x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
//y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
x1 = XV[0]*lB[0];
y1 = YV[1]*lB[1];
x1 = (x1/lB[3])/(lB[2]/lB[3]);
y1 = (y1/lB[3])/(lB[2]/lB[3]);
//console.log(y);
x1 = ( x1*VS+(width*0.5)+(ox*VS) );
y1 = ( y1*VS+(height*0.5)+(oy*VS) );
stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
line(x0,y0,x1,y1);
}
}
}
}
}
You can see the full program at https://editor.p5js.org/hpestock/sketches/Yfagz4Bz3

Related

How to fix "submatrix incorrectly defined" in Scilab?

I am trying to find three parameters (a, b, c) to fit my experimental data using ODE solver and optimization by least squares using Scilab in-built functions.
However, I keep having the message "submatrix incorrectly defined" at line "y_exp(:,1) = [0.135 ..."
When I try another series of data (t, yexp) such as the one used in the original template I get no error messages. The template I use was found here: https://wiki.scilab.org/Non%20linear%20optimization%20for%20parameter%20fitting%20example
function dy = myModel ( t , y , a , b, c )
// The right-hand side of the Ordinary Differential Equation.
dy(1) = -a*y(1) - b*y(1)*y(2)
dy(2) = a*y(1) - b*y(1)*y(2) - c*y(2)
endfunction
function f = myDifferences ( k )
// Returns the difference between the simulated differential
// equation and the experimental data.
global MYDATA
t = MYDATA.t
y_exp = MYDATA.y_exp
a = k(1)
b = k(2)
c = k(3)
y0 = y_exp(1,:)
t0 = 0
y_calc=ode(y0',t0,t,list(myModel,a,b,c))
diffmat = y_calc' - y_exp
// Make a column vector
f = diffmat(:)
MYDATA.funeval = MYDATA.funeval+ 1
endfunction
// Experimental data
t = [0,20,30,45,75,105,135,180,240]';
y_exp(:,1) =
[0.135,0.0924,0.067,0.0527,0.0363,0.02445,0.01668,0.012,0.009]';
y_exp(:,2) =
[0,0.00918,0.0132,0.01835,0.0261,0.03215,0.0366,0.0393,0.0401]';
// Store data for future use
global MYDATA;
MYDATA.t = t;
MYDATA.y_exp = y_exp;
MYDATA.funeval = 0;
function val = L_Squares ( k )
// Computes the sum of squares of the differences.
f = myDifferences ( k )
val = sum(f.^2)
endfunction
// Initial guess
a = 0;
b = 0;
c = 0;
x0 = [a;b;c];
[fopt ,xopt]=leastsq(myDifferences, x0)
Does anyone know how to approach this problem?
Just rewrite lines 28,29 as
y_exp = [0.135,0.0924,0.067,0.0527,0.0363,0.02445,0.01668,0.012,0.009
0,0.00918,0.0132,0.01835,0.0261,0.03215,0.0366,0.0393,0.0401]';
or insert a clear at line 1 (you may have defined y_exp before with a different size).

OpenCV Mat image data structure

I have an image that has been processed throw:
//UIImage to Mat
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];
//Grayscale
cv::Mat grayMat;
cv::cvtColor(originalMat, grayMat, CV_RGB2GRAY);
//Blur
cv::Mat gaussMat;
cv::GaussianBlur( grayMat , gaussMat, cv::Size(9, 9), 2, 2 );
//Threshold
cv::threshold(grayMat,tMat,100,255,cv::THRESH_BINARY);
than I want to analyze (calculate qty of white and black points) that belows to line. For instance: I have an image 100x120px and I want to check lines where x = 5 and y = from 0 to 119; and vice versa x = 0..99; y = 5;
so I expect that Mat will contains x - Mat.cols and y - Mat.rows but looks it saves data in another way. for example I've tried to change pixels color that belows to lines but didn't get 2 lines:
for( int x = 0; x < tMat.cols; x++ ){
tMat.at<cv::Vec4b>(5,x)[0] = 100;
}
for( int y = 0; y < tMat.rows; y++ ){
tMat.at<cv::Vec4b>(y,5)[0] = 100;
}
return [self UIImageFromCVMat:tMat];
result for white image:
why I did't get 2 lines? Is it possible to draw\check lines in Mat directly? what if I going to check line that calculates via y = kx + b?
You are accessing the pixel values in the wrong way. You are working with image that only has one channel, that's why you should access pixel values like this:
for (int x = 0; x < tMat.cols; x++){
tMat.at<unsigned char>(5, x) = 100;
}
for (int y = 0; y < tMat.rows; y++){
tMat.at<unsigned char>(y, 5) = 100;
}
The Mat element's type is defined by two properties - the number of channels and the underlying type of data. If you do not know the meaning of those terms, I strongly suggest that you read the documentation for methods cv::Mat::type(), cv::Mat::channels() and cv::Mat::depth().
Two more examples:
mat.at<float>(x, y) = 1.0f; // if mat type is CV_32FC1
mat.at<cv::Vec3b>(x, y) = Vec3b(1, 2, 3); // if mat type is CV_8UC3
Probably an issue with your Mat data types. The output of threshold is a single channel image that is 8-bit or 32-bit (http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold), so you probably should not be setting values with Mat.at<Vec4b>[0].
Here's a function to return the type of your matrix. Usage is in the commented out part. Copied from How to find out what type of a Mat object is with Mat::type() in OpenCV.
std::string type2str(int type){
//string ty = type2str( comparisonResult.type() );
//printf("Matrix: %s %dx%d \n", ty.c_str(), comparisonResult.cols, comparisonResult.rows );
string r;
uchar depth = type & CV_MAT_DEPTH_MASK;
uchar chans = 1 + (type >> CV_CN_SHIFT);
switch ( depth ) {
case CV_8U: r = "8U"; break;
case CV_8S: r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default: r = "User"; break;
}
r += "C";
r += (chans+'0');
return r;}

Changing the angle depending on position changes

I'm writing a scenario to a game which allows to use custom scripts.
I want to change the camera angle using SetCameraHeading(float in_fAngle), where:
"0 is facing east, 90 is facing north, 180 is facing west, and 270 is facing south".
I made something like this:
//The map size is 150x300:
NWX = 0;
NWY = 300;
NEX = 150;
NEY = 300;
SWX = 0;
SWY = 0;
SEX = 150;
SEY = 0;
Player1NW = GetDistanceFromUnitToPoint("Survivor1", NWX, NWY);
Player1NE = GetDistanceFromUnitToPoint("Survivor1", NEX, NEY);
Player1SW = GetDistanceFromUnitToPoint("Survivor1", SWX, SWY);
Player1SE = GetDistanceFromUnitToPoint("Survivor1", SEX, SEY);
Player1NWDiff = Player1NWOld - Player1NW;
Player1NEDiff = Player1NEOld - Player1NE;
Player1SWDiff = Player1SWOld - Player1SW;
Player1SEDiff = Player1SEOld - Player1SE;
//Need to set camera heading here:
SetCameraHeading(Player1CurrentAngle, false);
Player1NWOld = Player1NW;
Player1NEOld = Player1NE;
Player1SWOld = Player1SW;
Player1SEOld = Player1SE;
The problem is I don't know how to change the angle depending on position changes (for example, when an unit is walking it changes to: Player1NWDiff = -0.02, Player1NEDiff = -0.02, Player1SWDiff = 0.04, Player1SEDiff = 0.03 etc.)
Does anybody know how should I calculate it to get a correct angle (0 to 360)?

Removing the spacing between tiles in tilesheet

So I have an image which contains a tile-sheet, where each tile is approx 16 pixels wide, and high. But there spaced out with a transparent spacer between each tile.
Like so:
But this is ugly, and makes displaying the sprites in the program annoying, not to mention it wastes valuable image space. Is there any easy (Besides me manually using Photoshop to move each individual tile) way to make it look like this?
I looked through Photoshop macros, as-well as other programs and I diden't seem to find anything that would directly do this.
Google also suggests I go to home-depo and get tile caulk remover.
Try this snippet. As you said, it assumes tiles are always going to be 16 pixels. Top left one is in the correct position and a single pixel gap. The script assumes the document will opened with the layer containing your tiles set as the active layer.
#target photoshop
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
var gap = 1;
var tileSize = 16;
var doc = app.activeDocument.duplicate();
var sourceLyr = doc.activeLayer;
var xTilePosition = 0;
var yTilePosition = 0;
for (var x = 0; x < sourceLyr.bounds[2]; x = x+ tileSize + 1 ) {
for (var y = 0; y < sourceLyr.bounds[3]; y = y + tileSize + 1) {
if (x > 0 || y > 0) {
app.activeDocument = doc;
doc.activeLayer = sourceLyr;
selRegion = Array(Array(x, y),
Array(x + tileSize, y),
Array(x + tileSize, y + tileSize),
Array(x, y + tileSize),
Array(x, y))
doc.selection.select(selRegion);
var dx = x - (xTilePosition * tileSize);
var dy = y - (yTilePosition * tileSize);
doc.selection.translate(0 - dx, 0 - dy);
}
yTilePosition ++;
}
xTilePosition++;
yTilePosition = 0;
}

using DateTime and Stopwatch to calculate velocity with kinect sdk

i'm stuck for days to calculate the velocity of a mouvement so i'll try to more explain my problem.
i have to applicate an approache which allows to detect fall with kinect SDK and VS c#.
this approche takes as input 3 dimensions of a 3Box, built from the coordinates of skeleton joints.
these dimensions are:
W = |xMin - xMax|;
H = |yMin - yMax|;
D = |zMin - zMax|;
with xMin, xMax, yMin, yMax, zMin, zMax the minimum and the maximum of coordinates in all the tracked joints.
At this point, this is not the problem.. i already calculated all these values:
List<Joint> JointList = new List<Joint>();
List<double> JCx = new List<double>();
List<double> JCy = new List<double>();
List<double> JCz = new List<double>();
// define the min and max of coordinates as the filed of view of kinect
private double xMin = 2.2;
private double xMax = -2.2;
private int framecounter = 0;
private double yMin = 1.6;
private double yMax = -1.6;
private double zMin = 4;
private double zMax = 0;
Skeleton first = GetFirstSkeleton(allFramesReadyEventArgs);
if (first == null) // if no skeleton
{
txtP.Text = "No One";
return;
}
else
{
txtP.Text = "Yes";
skeletonDetected = true;
/// define all joints
Joint Head = first.Joints[JointType.Head];
JointList.Add(Head);
Joint SC = first.Joints[JointType.ShoulderCenter];
JointList.Add(SC);
Joint SL = first.Joints[JointType.ShoulderLeft];
JointList.Add(SL);
Joint SR = first.Joints[JointType.ShoulderRight];
JointList.Add(SR);
Joint EL = first.Joints[JointType.ElbowLeft];
JointList.Add(EL);
Joint ER = first.Joints[JointType.ElbowRight];
JointList.Add(ER);
Joint WL = first.Joints[JointType.WristLeft];
JointList.Add(WL);
Joint WR = first.Joints[JointType.WristRight];
JointList.Add(WR);
Joint HandL = first.Joints[JointType.HandLeft];
JointList.Add(HandL);
Joint HandR = first.Joints[JointType.HandRight];
JointList.Add(HandR);
Joint Spine = first.Joints[JointType.Spine];
JointList.Add(Spine);
Joint HipC = first.Joints[JointType.HipCenter];
JointList.Add(HipC);
Joint HipL = first.Joints[JointType.HipLeft];
JointList.Add(HipL);
Joint HipR = first.Joints[JointType.HipRight];
JointList.Add(HipR);
Joint KL = first.Joints[JointType.KneeLeft];
JointList.Add(KL);
Joint KR = first.Joints[JointType.KneeRight];
JointList.Add(KR);
Joint AnkL = first.Joints[JointType.AnkleLeft];
JointList.Add(AnkL);
Joint AnkR = first.Joints[JointType.AnkleRight];
JointList.Add(AnkR);
Joint FL = first.Joints[JointType.FootLeft];
JointList.Add(FL);
Joint FR = first.Joints[JointType.FootRight];
JointList.Add(FR);
// calculate x, y and z coordinates for each joint and
// put it into 3 different lists
foreach (Joint j in JointList)
{
if (j.TrackingState == JointTrackingState.Tracked)
jx = j.Position.X;
JCx.Add(jx);
jy = j.Position.Y;
JCy.Add(jy);
jz = j.Position.Z;
JCz.Add(jz);
foreach (double f in JCx)
{
if (f < xMin)
xMin = f;
else if (f > xMax)
xMax = f;
}
foreach (double f in JCy)
{
if (f < yMin)
yMin = f;
else if (f > yMax)
yMax = f;
}
foreach (double f in JCz)
{
if (f < zMin)
zMin = f;
else if (f > zMax)
zMax = f;
}
}
txtminx.Text = xMin.ToString();
txtmaxx.Text = xMax.ToString();
txtminy.Text = yMin.ToString();
txtmaxy.Text = yMax.ToString();
txtminz.Text = zMin.ToString();
txtmaxz.Text = zMax.ToString();
//calculate the 3 dimensions of the Box and the diagonal WD
double W = System.Math.Abs(xMin - xMax);
double H = System.Math.Abs(yMin - yMax);
double D = System.Math.Abs(zMin - zMax);
double WD = System.Math.Sqrt(Math.Pow(W0, 2) + Math.Pow(D0, 2));
The problem is when i have to calculate the velocity of the box dimensions vH and vWD .
vH = (Hi - H0) /(Ti- T0);
vWD = (WDi- WD0) /(Ti-T0);
i tried to use DateTime.UtcNow and Stopwatch to calculate the time spend
DateTime T0 = DateTime.UtcNow;
Stopwatch _stopwatch = Stopwatch.StartNew();
DateTime Ti = DateTime.UtcNow;
but i don't know how to get H value in a first time and in a second also i'm not sure if this methode will give me real result.
Can anyone help me ?
Thanks in advance
I did something similar in an application.
I started a StopWatch when the application started:
System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
int msNow;
int msPast;
int dif;
TimeSpan currentTime;
TimeSpan lastTime = new TimeSpan(0);
public GaitAnalyzer()
{
stopWatch.Start();
}
Then you just have to do something like this:
currentTime = stopWatch.Elapsed;
msNow = currentTime.Seconds * 1000 + currentTime.Milliseconds;
if(lastTime.Ticks != 0)
{
msPast = lastTime.Seconds * 1000 + lastTime.Milliseconds;
dif = msNow - msPast;
}
lastTime = currentTime;