I'm trying to draw a triangle on my screen, it works fine with calling winapi Polygon function (https://learn.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-polygon)
.data
xy POINT <350,50>,<350,70>,<370,70>
.code
...
INVOKE Polygon, hdc, offset xy, lengthof xy
while I check the document it says that POINT struct stores xy with LONG
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT, *PPOINT;
but i think it is not possible to directly initialize the data like this
.data
xy POINT <350.5,50.5>,<350.5,70.5>,<370.5,70.5>
SO is it possible to call this function in masm with real4 or real8?
Related
I am having a problem between sending a float trough the UART to be plotted in a graph on the Data Visualizer of Microchip.
I could plot int numbers without problem, but float ones are driving me crazy.
I made a sine wave with Laplace trnasform. After that put it on the 'z' plane with the bilineal z transform, then put the equation in the main routine of a dsPIC33FJ128GP802. It is working ok. In the terminal I can see the values and if I copy/paste those values on gnumeric and make a graph, it shows me my discrete sine wave.
The problem comes when I try to plot the float number 'yn' in the data visualizer of the MPLABX. There is something I am missing in the middle.
I am using MPLABX v5.45, XC16 v1.61 on Debian Bullseye. The communication with the microcontroller is transparent #9600-8N1.
Here is my main code:
int main(void)
{
InitClock(); // This is the PLL settings
Init_UART1();// This is the UART Init values for 9600-8-N-1
float states[6] = {0,0,0,0,0,0};
// states [xn-2 xn-1 xn yn yn-1 yn-2]
xn = 1.0; //the initial value
while (1)
{
yn = 1.9842*yn1-yn2+0.0013*xn1+0.0013*xn2; // equation for the sine wave
yn2 = yn1;
yn1 = yn;
xn2 = xn1;
xn1 = xn;
putc(0x03,stdout);
//Here I want to send the xn to plot in MDV
putc(0xFC,stdout);
}
}
The variables in the equation
yn = 1.9842*yn1-yn2+0.0013*xn1+0.0013*xn2;
are with #define like this
#define xn states[2]
#define xn1 states[1]
#define xn2 states[0]
#define yn states[3]
#define yn1 states[4]
#define yn2 states[5]
The WriteUART1(0x03); and the WriteUART1(0xFC); are for Data Visualizer to see the first byte and the last byte. It is like the example on the Microchip video.
The question is: How can I manage the float yn to be plot by the Microchip Data Visualizer.
Thanks in advance.
Ok, here is the answer.
A float number it is 32 bits long but you can't manage them bit by bit like int ones. So the way is to manage like a char.
You have to make a pointer to a char, assign the address of the float to the pointer (casting the address, because char pointer isn't the same as float pointer). Then just send 4 bytes incrementing the char pointer.
Here is the code:
while (1)
{
yn = 1.9842 * yn1 - yn2 + 0.0013 * xn1 + 0.0013 * xn2; // sine recursive equation
yn2 = yn1;
yn1 = yn;
xn2 = xn1;
xn1 = xn;
ptr = (char *) & yn; // This is the char pointer ptr saving the address of yn by casting it to char*, because &yn is float*
putc(0x03,stdout); // the start frame for MPLABX Data Visualizer
for (x = 0; x < sizeof(yn) ; x++) // with the for we go around the four bytes of the float
putc(*ptr++,stdout); // we send every byte to the UART
putc(0xFC,stdout); // the end frame for MPLABX Data Visualizer.
}
With this working, you have to config the data visualizer, your baudrate, and then select new streaming variable. You select a name, then Framing Mode you select One's complement, the start frame in this case 0x03 and the end frame 0xFC. Just name the variable and then type float32, press next, plot variable, finish and you have the variable in the MPLABX time plotter.
Here is the image of the plot
Hope, this helps someone.
Regards.-
I am trying to draw a koch curve (line) with basic trigonometric conversions.
I couldn't figure out what is the correct angle for newly generated peak point.
Here is my logic:
Given the start point of the line, angle of the line and the length for every segment, create this scheme.
After creating the schemem, treat every sub-lines starting point as new koch curves and repeat the steps.
I suspect the problem is at point 'pt' angle value.
/* Angle for turning downwards after the peak point */
float angle = 2*PI - PI/6;
void koch(Point2D start, float alpha, int d, int noi) {
Point2D p1 = new Point2D(start.x + d*cos(alpha), start.y + d*sin(alpha));
Point2D pt = new Point2D(start.x + d*sqrt(3)*cos(alpha+PI/6), start.y + d*sqrt(3)*sin(alpha+PI/6));
Point2D p2 = new Point2D(start.x + 2*d*cos(alpha), start.y + 2*d*sin(alpha));
Point2D p3 = new Point2D(start.x + 3*d*cos(alpha), start.y + 3*d*sin(alpha));
line(start.x, start.y, p1.x, p1.y);
line(p1.x, p1.y, pt.x, pt.y);
line(pt.x, pt.y, p2.x, p2.y);
line(p2.x, p2.y, p3.x, p3.y);
if(noi != 0) {
koch(start, alpha, d/3, noi-1);
koch(p1, alpha + PI/3, d/3, noi-1);
koch(pt, angle, d/3, noi-1); //Problem is here i suspect
koch(p2, alpha, d/3, noi-1);
}
return;
}
Calling this function with alpha being PI/6 and noi is 2 i get:
I want to get something like:
I was reluctant to answer as I do not code in Unity but as your question after few days still did not have any valid answer here is mine:
I do not see what I would expect in turtle graphics code. See:
Smooth Hilbert curves
and look for turtle_draw in the code. This is what I would expect:
initial string
turtle fractals are represented by a string holding turtle commands. Usual commands are:
f go forward by predetermined step
l turn left (CCW) by predetermined angle in your case 60 deg
r turn right (CW) by predetermined angle in your case 60 deg
For Koch snowflake you should start with triangle so "frrfrrf" the Koch curve starts with single line "f" instead.
iteration/recursion
for each level of iteration/recursion of the fractal you should replace each straight line command f by the triangular bump feature "flfrrflf" (make sure that last direction matches original f command). As the triangle tripled in size you should divide size of the f movement by 3 to stay at the same scale ...
render the string
simply process all the characters of the resulting string and render the lines. There are two approaches how to handle the rotations. Either remember direction angle and inc/dec it by rotation angle and compute the lines as polar coordinates increments (see the code below), or have direction in form of a 2D (or higher dimension) vector and apply rotation formula on it (see the link above).
Here small C++/VCL example of the Koch snowflake:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
Graphics::TBitmap *bmp=new Graphics::TBitmap;
int xs,xs2,ys,ys2,n=0;
AnsiString str;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)
{
int i;
char c;
float da=60.0*M_PI/180.0;
scr->MoveTo(x,y);
for (i=1;i<=s.Length();i++)
{
c=s[i];
if (c=='f')
{
x+=dl*cos(a);
y+=dl*sin(a);
scr->LineTo(x,y);
}
if (c=='l') a-=da;
if (c=='r') a+=da;
}
}
//---------------------------------------------------------------------------
AnsiString replace(AnsiString s0,char find,AnsiString replace)
{
int i;
char c;
AnsiString s="";
for (i=1;i<=s0.Length();i++)
{
c=s0[i];
if (c==find) s+=replace;
else s+=c;
}
return s;
}
//---------------------------------------------------------------------------
void draw()
{
str="frrfrrf"; // initial string
for (int i=0;i<n;i++) str=replace(str,'f',"flfrrflf"); // n times replacement
bmp->Canvas->Brush->Color=0x00000000; // just clear screen ...
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
bmp->Canvas->Pen ->Color=0x00FFFFFF; // and some info text
bmp->Canvas->Font ->Color=0x00FFFFFF;
bmp->Canvas->TextOutA(5,5,AnsiString().sprintf("n:%i",n));
float nn=pow(3,n),a;
a=xs; if (a>ys) a=ys; a=0.75*a/nn;
turtle(bmp->Canvas,xs2-(0.5*nn*a),ys2-(0.33*nn*a),0.0,a,str); // render fractal
Form1->Canvas->Draw(0,0,bmp); // swap buffers to avoid flickering
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete bmp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
bmp->Width=ClientWidth;
bmp->Height=ClientHeight;
xs=ClientWidth;
ys=ClientHeight;
xs2=xs>>1;
ys2=ys>>1;
draw();
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
{
if (WheelDelta<0) if (n<8) n++;
if (WheelDelta>0) if (n>0) n--;
Handled=true;
draw();
}
//---------------------------------------------------------------------------
Ignore the VCL stuff. The important thing here are:
void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)
which renders the string s on canvas scr (using VCL encapsulated GDI) where x,y is start position a is starting direction angle [rad] and dl is size of line.
AnsiString replace(AnsiString s0,char find,AnsiString replace)
which replace any find characters in s0 by replace pattern returned as a new string.
void draw()
which computes and render the fractal
Here few screenshots:
Now when I look at your code (just a quick look as I am too lazy to analyze your code in depth) you are generating points directly and without the incremental steps needed. Instead you are sort of hard-coding the triangular bump feature which will not work properly for next level of fractal recursion without clever indexing techniques. In your case it stop working properly even in the same level of recursion (on the next line because its oriented differently and you are not rotating but hard-coding the feature instead).
As far as I know basic Koch curve starts with a line, divides the length of step into three and puts a equilateral triangle in the middle:
There are different variations out there if you are interested in, but for basic Koch curve you can start with either two of p1, p2, p3, pt and start points that you drawn and calculate the rest respectively. In each iteration, you can go one level deeper.
I am trying to make my first steps with the C++ Eigen library. The Matrix functionality was very intuitive but I have some problems using the AlignedBox type from the Geometry module.
For an exercise I have to rotate an AlignedBox around a specific point and be able to translate it within a 2D plane using Eigen::Transform.
I have tried around for quite a while.
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
// create 1D AlignedBox
Eigen::MatrixXf sd1(1,1);
Eigen::MatrixXf sd2(1,1);
sd1 << 0;
sd2 << 3;
Eigen::AlignedBox1f box1(sd1, sd2);
// rotation of 45 deg
typedef Eigen::Rotation2D<float> R2D;
R2D r(M_PI/4.0);
// create transformation matrix with rotation of 45 deg
typedef Eigen::Transform< float, 2, Eigen::AffineCompact > SE2;
SE2 t;
t = r;
// how to apply transformation t to box1???
return 0;
}
I thought I have to multiply the AlignedBox with t.matrix() but since the Box is no matrix type and I did not find any useful build in function I have no idea how to apply the transformation. Any help would be appreciated
Note that result will be a 2D box. You can compute it by applying the affine transformation to the two 2D extremities, and updating the 2D box with the extend method, e.g.:
AlignedBox2f box2;
box2.extend(t * Vector2f(box1.min()(0), 0));
box2.extend(t * Vector2f(box1.max()(0), 0));
To apply another transformation to box2, you can use the same principle on the 4 corners of the box that you can get using the AlignedBox::corner method.
I have a question about wrapping a Halide::Image object around an already allocated C++ array that defines a 2-D double precision floating point image.
I've already looked at:
C++ array to Halide Image (and back)
This is close to what I want to do, but I'm confused by uint8_t type of the host member of buffer_t in halide and how you work with existing images that are not uint8_t.
I see that in the blur app which uses aot, the example allocates a Halide Image, and then copies elements into this halide image. I would like to do this, but without paying for the copy.
It's not an option for me to use load_image, I need to work with existing, already allocated memory defined by a double *.
Image<uint16_t> input(6408, 4802);
for (int y = 0; y < input.height(); y++) {
for (int x = 0; x < input.width(); x++) {
input(x, y) = rand() & 0xfff;
}
}
The uint8_t* type of the host field of buffer_t is just a pointer to any array of data. You are free to point it to a float or double array. It's basically a void* pointer that gets reinterpreted by the actual pipeline code. Its interpretation is determined by the combination of the Halide program that loads from it, and the elem_size field (which should be, e.g., sizeof(double) or sizeof(float) for floating point data of different kinds).
As MSDN said
BOOL ScreenToClient(
_In_ HWND hWnd,
LPPOINT lpPoint
);
the ScreenToClient's second para is a pointer to POINT,
and PINT said by MSDN is
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT, *PPOINT;
it has only x and y. It's NOT like MFC ScreenToClient function, the para is a rect, and rect has width and height.
I am confused how to use win32 ScreenToClient function.
You can use MapWindowPoints() to convert a RECT in a single operation:
RECT r = ...;
MapWindowPoints(NULL, hWnd, (LPPOINT)&r, 2);
MFC actually has two methods, they're overloaded. One accepts a POINT structure, just like the Win32 function, the other accepts a RECT structure, both work the same way: it maps each point from screen-to-client.
If you have a RECT that you want to get client coordinates of without using MFC then just do it manually, like so:
RECT rect = GetMyRect();
POINT rectTL;
rectTL.x = rect.left;
rectTL.y = rect.top;
ScreenToClient( hWnd, &rectTL );
POINT rectBR;
rectBR.x = rect.right
rectBR.y = rect.bottom;
ScreenToClient( hWnd, &rectBR );
rect.left = rectTL.x;
rect.top = rectTL.y;
rect.right = rectBR.x;
rect.bottom = rectBR.y;
Note that RECT is
typedef struct _RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;
and looks like two consecutive POINTs in memory. Therefore you can do what the MFC source code does, which is approx. the following (don't have the MFC source in front of me right now):
::ScreenToClient(hWnd, (POINT*)&rect->left);
::ScreenToClient(hWnd, (POINT*)&rect->right);
which is not the cleanest thing from a C point of view, but those structures are bound to remain binary compatible.