Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
Solved

# interpolation

Posted on 2004-04-21
Medium Priority
453 Views
i need to do a interpolation on 2000 data points which i have capature using mousemove and it is stored in notepad. The problem i faced now is doing time normalization wif interpolation. For example, a user sign 3 times at different speed. First time is 4ms(fast speed), second is 6ms(standard speed) and third time is 9ms(slow speed). Using the second time as reference, i would like to make first time and third time to be the same amount of time where i have to do interpolation between the data points. How should i go about doing it?

0
Question by:slayer84
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 18
• 11
• 10

LVL 13

Expert Comment

ID: 10886894
I don't understand the question: What do you want to interpolate? xy coordinates inbetween know coordinates. xy coordinates as a function of time?

You have 2000 datapoints with mouse x,y coords and time for each point. I guess that the interpolation should take into account that a fast movement will most likely be straight compared to slower ones.

But can you explain a bit more in detail what you want to do exactly with your data. It would make helping easier.
0

Author Comment

ID: 10888139
well , i need to interpolate the data points 4ms(fast) which has 20 xy coordinates to 6ms (standard) which has 33 xy coordinates  and 9ms (slow) which has 44 xy coordinates to 6ms (standard). 1) How to interpolate the data points which has 20 pts of 4ms to 33pts of 6ms.
2) How to interpolate the data points which has 44 pts of 9ms to 33 pts of 6ms.
Thank you.
0

LVL 13

Expert Comment

ID: 10888292
From slow to standard should be the easier way: You need to interpolate points like
1   1  1   2  2  2   3
0--3--6--9--2--5--8--1--4--7--0

s------s-----s------s------s-----s

S-----s--S--s-----S-----s--S--s--   (s: standard, S: slow)

First attempt could be linear interpolation: This assumes straight lines between each points.
For the slow case you need to find either the 2/3 or 1/3 intersection between two points:

//point near to n+1
x(i) = .333 * x(n) + 0.666 * x(n+1);
y(i) = .333 * y(n) + 0.666 * y(n+1);
// point near n needs to exchnage 0.333 and 0.666.

To convert fast to standard you need to find every second middle point:

x(m) = .5 * x(n) + .5 * x(n+1);
y(m) = .5 * y(n) + .5 * y(n+1);

Values at 0, 12, 24 can be taken and values of 6 comes from middle of 4 and 8 ms, 18 from middle of 16 and 20 etc.
0

Author Comment

ID: 10888921
the solutions of this only applies to linear line right? i dun quite understand how u get the values of 0,12 and 24 ?
MAy i know how to apply this theory to visual C++ programming ?
0

LVL 13

Expert Comment

ID: 10889347
when you compare at which times you have data points you get:
0,4,8,12,16,20,24,28,...  fast
0,6,12,18,24,30,...  standard
0,9,18,27,36,... slow

Now to get for all traces points on a 6 ms intervall you need to do nothing for standard. For the fast approach you can use 0,12,24, ...
And the two value inbetween need to be averaged. (4+8)/2 = 6, (16+20)/2 = 18 and you have points for 0,6,12,18,24, .. for the fast set.

You can use other methods for interpolating the points: To get smooth curves use splines, bezier splines, etc. Only the formulas are much more complex and I can't tell you them out of my head. For linear interpolation the math can be done easily.

When going the approach with the more complex functions to interpolate you normally have variable going from 0 to 1 between to points. This has to be related to the time. And you have to look for either the 0.5 value (fast) or 0.33 and 0.66 (slow).
0

Author Comment

ID: 10890163
i understand what u trying to say ..but the time for fast at 0ms is (165,170),(165,169), (166,169),(169,167), at 1ms is (172,166), (179,165),(187,163),(199,162),(211,161),(226,160),(243,158), at 2ms is (258,155),(273,153),(287,150),(298,147),(307,144), (314,141)and at 3ms is (319,138),(321,137),(323,136) ...the time is in 1,2,3,4ms ....etc..which has 4 sets of xy coordinate at 0ms, 7 sets of xy coordinate at 1ms and 6 sets of xy at 2ms and 3 sets of coordinates at 3ms..and the time is not like what u have said 0,4,8,12,16,2,24,28 ...fast.....0,6,12,18,24,30....standard...and 0,9,18,27,36..slow....if is this case how to do linear interpolation? Can u help me with C++ programming source code for this ? Sooy for the trouble...
0

LVL 13

Expert Comment

ID: 10890334
So is there any regular interval at which those messages appear? At the moment I can't see how the different sets differ. In that case I can't help with code but perhaps I can help to clarify to describe what you want. Only afterwards one can try to get code.

What does the "4ms", "6ms" and "9ms" mean? What is the time resolution of your points sets? What I see here are different number of sets per time intervall. But can those be evenly distributed over the timespan?
0

Author Comment

ID: 10890635
4 , 6, 9 is the unit of time taken to draw a line at fast , medium and slow speed. Example if during the 4 unit of time it has the 20 sets of coordinates(shown above) , 6 unit of time it has 33 sets of coordinates , and 9 unit of time it has 44 sets of coordinates.In order to take the 6 unit as standard time, i have to do time normalization for the 4 unit and 9 unit to make it 6 unit. The time resolution is 50unit of time for 2000 pts. After that i have to do interpolation. I really got no time to waste. I was wondering if two days can do this ?
0

Author Comment

ID: 10895413
SteH, i really do not know how to do interpolation for my program. Can you help me with my program?
0

LVL 13

Expert Comment

ID: 10896988
Perhaps I got the problem now: You have a set of points which are equally spaced in time but for display you can only use a subset since drawing of a line takes too long. And the resulting image on the screen should approximate the curve of all the points as good as possible. Is that true?

In that case it is necessary to know what is expensive during line drawing. Since "non linear" interpolation would mean replacing a straight line with several shorter lines not all of them having the same direction. In other words a bezier spline would mean drawing of several shorter lines and a lot of calculations.

If there is no time for it you won't take an evenly spaced subsample of your points with 4,6 or 9 units spacing. But instead you can calculate how many lines can be drawn in that time and you need to find those end points for that number of lines that make the resulting figure match the original as close as possible. For the fast drawing you need 4 units and have 50 units of data: in that time you can draw 12.5 lines so you need 13 points to draw 12 lines. Points needed ar the first and last and 11 inbetween. Is this correct?
0

LVL 39

Expert Comment

ID: 10899944
>> a user sign 3 times at different speed.

What do you mean with that?

Did you capture MouseMove Events using three different timer intervals (4ms, 6 ms, 9 ms)?

And how can you get 2000 points with that?

Is it a user's signature that you are trying to catch?

You tell from 20, 33 and 44 points. What is the relationship from these numbers to the 2000 points?

Can you give us the code where you are collecting the points?

And try to explain what do you expect as result from that normalization? Maybe using an example of 20 - 30 points.

Regards, Alex
0

Author Comment

ID: 10905370
SteH,
i don't quite get wad u mean? i have to do linear interpolation since i onli experimenting drawing a line at different speed. i do not know  how to apply the alogorithm into programming?  i found some research on http://en.wikipedia.org/wiki/Linear_interpolation and i do not know how to apply the algorithm in visual C++ programming form.
0

Author Comment

ID: 10908155
Alex,
i am trying to capture the xy coordinates of the signature at fast , medium and slow speed.  Of the 2000
points, i am onli be able to get 4 unit of time of 20 sets of coordinates(fast),6 unit of time it has 33 sets of coordinates (medium), and 9 unit of time it has 44 sets of coordinates(slow).In order to take the 6 unit as standard time, i have to do time normalization for the 4 unit and 9 unit to make it 6 unit. The time resolution is 50unit of time for 2000 pts. After that i have to do interpolation. Supposed it has to be cubic spline interpolation,but now i only experimenting by drawing a line, to do linear interpolation as it is easier and after doing doing the interpolation i need to do FFT where i would compare the result and the result should be not much difference with doing the interpolation before FFT and interpolation after FFT. Below is the code for my capturing of xy coordinates.
voidCJustSignView::OnFileSave()
{

FILE*fp;

fp=fopen("G:\\data1.txt","w");

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{
fprintf(fp,"-------------------------------------------------------\n");
fprintf(fp,"|Index\t\t\t|X point\t|Y point\t|Time\n");
fprintf(fp,"-------------------------------------------------------\n");

for(int i=0;i<nMaxPoint;i++)
{
if(lXvalue[i] < 0 && lYvalue[i] < 0 && nTime[i] < 0)
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
}

fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|\n",i,lXvalue[i],lYvalue[i],nTime[i]);
}

}
fclose( fp );

if(fq==NULL)

MessageBox("Signature NOT saved.");

else
{
for(int i=0;i<nMaxPoint;i++)
{
fprintf(fq,"%ld\n",lYvalue[i]);

}

}

MessageBox("Signature saved.");

}

If u want any further clarifications of my program, hope u can leave your email and i send u my program to let u have a look. I got the code and the problem is that i do not know how to link my codes together.

0

LVL 13

Expert Comment

ID: 10915215
My question is, do you have the 2000 points and need to draw them? Or do you need to aquire those points?
In the first case: take the first and the last point. Calculate the angles between 2 points and sort them by the magnitude. Now take the 11 highest for the 4 unit case. In the other cases you need some more so you take more from that sorted list.

0

LVL 39

Expert Comment

ID: 10916314
>> i am trying to capture the xy coordinates of the signature at fast , medium and slow speed

I suppose that is a "yes" to my signature question: "Is it a user's signature that you are trying to catch?"

>> i am onli be able to get 4 unit of time of 20 sets of coordinates(fast), 6 unit of time it has 33 sets of coordinates (medium), ...
>> The time resolution is 50unit of time for 2000 pts.

I've still problems to unterstand that.  None of any combination i made gives 2000 points.

>> voidCJustSignView::OnFileSave()

That isn't the member that captures the points but stores the points to a file. I can see that you've a time value for any point. Is the value of nMaxPoint  == 2000 ? I need the member function where the points get collected and get assigned to lXValue[i], lYValue[i] and nTime[i]. And if it is an OnTimer handler i need the call to SetTimer also.

You may send me the zipped project to  info@sbsweb.info . However, i would suggest to answer my questions here in EE as well, so you may get a quicker answer.

Regards, Alex
0

Author Comment

ID: 10924386
//============================================================
// Custom Define START
//============================================================
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
#define ntmrDurValue      50    // 5 units of time
#define nMaxPoint            2000      // 2000 points allowed
//============================================================
// Custom Define END
//============================================================

void CDay10View::OnTimer(UINT nIDEvent)
{      if (bEnd==false)
{
nTimeCount++;
}
CView::OnTimer(nIDEvent);

}
0

Author Comment

ID: 10924387
//============================================================
// Custom Define START
//============================================================
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
#define ntmrDurValue      50    // 5 units of time
#define nMaxPoint            2000      // 2000 points allowed
//============================================================
// Custom Define END
//============================================================

void CDay10View::OnTimer(UINT nIDEvent)
{      if (bEnd==false)
{
nTimeCount++;
}
CView::OnTimer(nIDEvent);

}
0

LVL 13

Expert Comment

ID: 10936486
I still don't see how you get your data. And I don't understand what you want to interpolate.

An attempt in guessing: You get points at different speed for fast , standard and slow and now need to compare either with stored points of that signature. In that case I don't see how it would help to first get everything to standard timing to compare it afterwards to the very fast set. You need some fitting routine for the comparison. You will have some free parameters: the coordinates you are taking can have an offset in x and y and will have an angle to the stored curve. You need to find the best set of these parameters and test whether the resulting curves sufficiently match oneanother. This fit would be possible with a undefined number of points. Is this what you want to do?
0

LVL 39

Expert Comment

ID: 10936676
>> I need the member function where the points get collected and get assigned to lXValue[i], lYValue[i] and nTime[i].

That request isn't answered til now. We need the OnMouseMove(..)  function and the code where the MouseMove capturing is initialized.

Please give feedback if you've send your project to my e-mail address as i have to forward it to my current location.

Regards, Alex
0

Author Comment

ID: 10939542
Seth, your guessing is wad i am trying to say...bingo...correct..i do not know how to get started with it..see if u can help mi .. if u want to have a look at my program, feel free to let mi know...
0

Author Comment

ID: 10939560
Alex i have send my project to ya...did u receive it..i send it again..=)
0

LVL 13

Assisted Solution

SteH earned 60 total points
ID: 10939786
The idea for the fitting would be:
Calculate the distance of the points you aquired to the saved curve and checked whether the sum of the square of these distances is at its minimum below a threshold.

To start: Add 2 more variables to be able to shift rotation center to center of you data points. This will minimize the computing error during the rotation. And the overall thing is:

0) Set initial values to the three parameters and those 2 vars.
1) shift acquired points.
2) rotate
3) shift for offset.
4) calculate the distance of all points to the curve.
5) calculate sum of distance squared.
6) change values of fit parameters.
7) repeat 1-6 until sum is minimal.

check whether sum is below threshold.

These steps can be done with math programs as well but it takes some time to learn them. ON the other hand it will take a while to vary the 3 (5) parameters above to find a good minimum as well.

0

LVL 13

Accepted Solution

SteH earned 60 total points
ID: 10939803
A free math package which could be of help you can find at:
http://root.cern.ch/
But it takes some time to learn especially the minimisations.
0

LVL 39

Expert Comment

ID: 10940869
I got your project and will find time to look thru within the next 2 hours.

Regards, Alex
0

Author Comment

ID: 10945111
Steh , i have gone to look at the website.. what are u trying to ask me to look at? Can u specifify which part need the math to do it?
0

Author Comment

ID: 10945112
Steh , i have gone to look at the website.. what are u trying to ask me to look at? Can u specifify which part need the math to do it?
0

LVL 13

Expert Comment

ID: 10946810
Take the link download binaries and then choose your platform. It might take some month to learn how to use it. There are tutorials and howtos but you will need a bit more to get what you want. Mainly you will need the class TMinuit of that root package.

So what about trying to do it yourself in the way I sketched above.
0

Author Comment

ID: 10956685
Hi Alex, i have done the interpolation and extrapolation out. Now i have problem linking the program. So could u help me wif tat? i have send to your mail.
0

LVL 39

Expert Comment

ID: 10957453
Why do you have two projects in your workspace? The second project only has the document class. Is it by accident ?

At my environment (VC6, Win2K) only Day10Doc.dsp couldn't be linked. That is because line.cpp hasn't included to the project's workspace:

- Open line.cpp
- Right-click and select Insert... to day10doc.

Then, it should link. However, what do you intend to do with that project?

>> Hi Alex, i have done the interpolation and extrapolation out.

I had sent a post wednesday but it got lost somehow (maybe i closed my browser before the post was thru). In my comment  i told you that i would need some time to find out what happens and i posted day10view.h and day10view.cpp in order to give other experts a chance to help you.

My problem was, that at a first glance i couldn't see any closer relationship of the code in your view class and the interpolation question you asked here in EE. I could find out where the 2000 points come from, i saw that the points come from MouseMove Events - as suspected - but i couldn't find any traits where you got different value sets having been captured under different timing conditions. So, my initial question where the results sets that should get normalized come from is still unanswered.

I'll have a deeper look now in your prog and maybe i'll get some answers.

Regards, Alex

0

LVL 13

Expert Comment

ID: 10957484
Hi slayer84

Are you able to post the project to some web location. If not I will unsubscribe since only Alex will have much better chances to give you a solution.
0

LVL 39

Expert Comment

ID: 10957592
I'll post the view class files of the project. Maybe someone had time to look over that.

// Day10View.h : interface of the CDay10View class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_DAY10VIEW_H__EEBBEF4C_3F1A_40E3_B7EB_7B53CB2F9697__INCLUDED_)
#define AFX_DAY10VIEW_H__EEBBEF4C_3F1A_40E3_B7EB_7B53CB2F9697__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//============================================================
// Custom Define START
//============================================================
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
#define ntmrDurValue    10    // 5 units of time
#define nMaxPoint       2000    // 2000 points allowed
//============================================================
// Custom Define END
//============================================================

class CDay10View : public CView
{
protected: // create from serialization only
CDay10View();
DECLARE_DYNCREATE(CDay10View)
CPoint Anchor;
CPoint DrawTo;
CPoint OldPoint;
BOOL bDrawFlag;
// Attributes
public:
CDay10Doc* GetDocument();

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDay10View)
public:
virtual void OnDraw(CDC* pDC);  // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL

// Implementation
public:
void MakeAllFlagsFalse();
int sig_length;
int sig_width;
void On_enlarge(float Scale);
void OnNormal_Screen();
int no_of_count();
int getYpos(int which_point);
int getXpos(int which_point);
void four1(long data[],unsigned long nn,int isign);
void FFT();
long lCentrePointY;
long lCentrePointX;
long AreaBox;
int nSegmentNo;
bool bFirstPoint;
int m_iPrevY;
int m_iPrevX;
CPoint m_ptTo;
CPoint m_ptFrom;

int pDC;
CPoint point;
int m_ptPrevPosY;
int m_ptPrevPosX;

bool bCurrentButtonDownStatus;

int nLength;
long lXvalue[nMaxPoint];
long lYvalue[nMaxPoint];
int nTime[nMaxPoint];
int nSegmentNumber[nMaxPoint];

int nLengthNom;
long lXvalueNom[nMaxPoint];
long lYvalueNom[nMaxPoint];
int nTimeNom[nMaxPoint];
int nSegmentNumberNom[nMaxPoint];

long IndexStartElement;
int nLengthRef;
long lXvalueRef[nMaxPoint];
long lYvalueRef[nMaxPoint];
int nTimeRef[nMaxPoint];
int nSegmentNumberRef[nMaxPoint];
int nIdexStartElement;
int nCount;
int nTimeCount;
bool bEnd;
bool bStart;
void ShowPointValue();
void OnTimer(UINT nIDEvent);

virtual ~CDay10View();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CDay10View)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRetrieve();
afx_msg void OnCentrePos();
afx_msg void OnCentrePoint();
afx_msg void OnHalf();
afx_msg void OnQuarter();
afx_msg void OnDouble();
afx_msg void OnEnd();
afx_msg void OnStart();
afx_msg void OnNormalBox();
afx_msg void OnNormalArea();
afx_msg void OnNormalNormalize();
afx_msg void OnNormalScreen();
afx_msg void OnSignatureCheck();
afx_msg void OnSignatureFft();
afx_msg void OnFileSave();
afx_msg void OnToolsDrawfreehand();
afx_msg void OnUpdateToolsDrawfreehand(CCmdUI* pCmdUI);
afx_msg void OnNormalTime();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CPoint m_ptPrevPos;
};

#ifndef _DEBUG  // debug version in Day10View.cpp
inline CDay10Doc* CDay10View::GetDocument()
{ return (CDay10Doc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_DAY10VIEW_H__EEBBEF4C_3F1A_40E3_B7EB_7B53CB2F9697__INCLUDED_)

// Day10View.cpp : implementation of the CDay10View class
//

#include "stdafx.h"
#include "Day10.h"
#include "MainFrm.h"
#include "Line.h"
#include "Pts.h"
#include "Day10Doc.h"
#include "Day10View.h"
#include "Math.h"
#include "iostream.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDay10View

IMPLEMENT_DYNCREATE(CDay10View, CView)

BEGIN_MESSAGE_MAP(CDay10View, CView)
//{{AFX_MSG_MAP(CDay10View)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_RETRIEVE, OnRetrieve)
ON_COMMAND(ID_CentrePos, OnCentrePos)
ON_COMMAND(ID_CentrePoint, OnCentrePoint)
ON_COMMAND(ID_HALF, OnHalf)
ON_COMMAND(ID_QUARTER, OnQuarter)
ON_COMMAND(ID_DOUBLE, OnDouble)
ON_COMMAND(ID_END, OnEnd)
ON_COMMAND(ID_START, OnStart)
ON_COMMAND(ID_NORMAL_BOX, OnNormalBox)
ON_COMMAND(ID_NORMAL_AREA, OnNormalArea)
ON_COMMAND(ID_NORMAL_NORMALIZE, OnNormalNormalize)
ON_COMMAND(ID_NORMAL_SCREEN, OnNormalScreen)
ON_COMMAND(ID_SIGNATURE_CHECK, OnSignatureCheck)
ON_COMMAND(ID_SIGNATURE_FFT, OnSignatureFft)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
ON_COMMAND(ID_TOOLS_DRAWFREEHAND, OnToolsDrawfreehand)
ON_UPDATE_COMMAND_UI(ID_TOOLS_DRAWFREEHAND, OnUpdateToolsDrawfreehand)
ON_COMMAND(ID_NORMAL_TIME, OnNormalTime)
ON_WM_TIMER()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDay10View construction/destruction

CDay10View::CDay10View()
{
// TODO: add construction code here
MakeAllFlagsFalse();
/* bStart=false;
bEnd=false;
nCount=0;
bFirstPoint=true;
nSegmentNo=0;

int i;
for (i=0; i<nMaxPoint;i++)
{
lXvalue[i]=0;
lYvalue[i]=0;
nSegmentNumber[i]=0;
} */
}

CDay10View::~CDay10View()
{
}

BOOL CDay10View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs

return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CDay10View drawing

void CDay10View::OnDraw(CDC* pDC)
{
CDay10Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here

HMETAFILE MetaFileHandle = pDoc->pMetaFileDC->Close();
pDC->PlayMetaFile(MetaFileHandle);
CMetaFileDC* ReplacementMetaFile = new CMetaFileDC();
ReplacementMetaFile->Create();
ReplacementMetaFile->PlayMetaFile(MetaFileHandle);
DeleteMetaFile(MetaFileHandle);
delete pDoc->pMetaFileDC;
pDoc->pMetaFileDC = ReplacementMetaFile;
//my code start here
/*
//get the number of lines in the document
int liCount = pDoc->GetLineCount();

//are there any lines in the document?
if(liCount)
{
int liPos;
CLine *lptLine;

//loop through the lines in the document
for (liPos = 0; liPos < liCount; liPos++)
{
//get the from and to point for each line
lptLine = pDoc->GetLine(liPos);
//draw the line
lptLine->Draw(pDC);
}
}
//my code ends here  */
}

/////////////////////////////////////////////////////////////////////////////
// CDay10View printing

BOOL CDay10View::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}

void CDay10View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CDay10View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CDay10View diagnostics

#ifdef _DEBUG
void CDay10View::AssertValid() const
{
CView::AssertValid();
}

void CDay10View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}

CDay10Doc* CDay10View::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDay10Doc)));
return (CDay10Doc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDay10View message handlers

void CDay10View::OnLButtonDown(UINT nFlags, CPoint point)
{
//  AfxMessageBox("Mouse Button DOWN");
/*  bFirstPoint=true;
bCurrentButtonDownStatus=true;
nSegmentNo++;    */
Anchor.x = point.x;
Anchor.y = point.y;
//code end here
CView::OnLButtonDown(nFlags, point);
}

void CDay10View::OnLButtonUp(UINT nFlags, CPoint point)
{
//  AfxMessageBox("Mouse Button UP");
CDay10Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

DrawTo.x = point.x;
DrawTo.y = point.y;

CClientDC* pDC = new CClientDC(this);
bCurrentButtonDownStatus=false;
CView::OnLButtonUp(nFlags, point);
}

void CDay10View::OnMouseMove(UINT nFlags, CPoint point)
{
// check to see if the left mouse button is down
/*   if (!bEnd)
{
if (nCount!=nMaxPoint)
{
if ((nFlags & MK_LBUTTON) == MK_LBUTTON)
{
//have we capture the mouse?
if (GetCapture() == this)
{
//              AfxMessageBox("here");
//get the device context
CClientDC dc(this);

//add the line to the document

if ((bCurrentButtonDownStatus)&&(!bFirstPoint))
{

//draw the current stretch of line
pLine->Draw(&dc);
}

if (bCurrentButtonDownStatus&&bFirstPoint)
bFirstPoint=false;

/*          CString m_ptx;
m_ptx.Format("%d",m_ptPrevPos.x);
CString m_pty;
m_pty.Format("%d",m_ptPrevPos.y);
AfxMessageBox("X= "+m_ptx);
AfxMessageBox("Y= "+m_pty);
//save the current point as the previous point
m_ptPrevPos = point;
}

CView::OnMouseMove(nFlags, point);
//          PostMessage(WM_MOUSEMOVE);
lXvalue[nCount]=m_ptPrevPos.x;    //   this two lines record the value of
lYvalue[nCount]=m_ptPrevPos.y;    //   x & y axis..
nTime[nCount]=nTimeCount;
nSegmentNumber[nCount]=nSegmentNo;
nCount++;
}
}
else
{
if (!bEnd)
{
if (GetCapture() == this)
//if so, release it so other applications can have it
ReleaseCapture();

//code end here

nLength=nCount;
ShowPointValue();
bEnd=true;
bStart=false;
AfxMessageBox("Time Up!");
//      OnEnd();
}
}
}  */

CClientDC* pDC = new CClientDC(this);
if ((nFlags && MK_LBUTTON) && bDrawFlag)
{

if (bStart==false && bEnd==true)
bEnd=false;
nCount++;

pDC->MoveTo(Anchor.x, Anchor.y);
pDC->LineTo(point.x, point.y);

Anchor.x = point.x;
Anchor.y = point.y;

// record the point
lXvalue[nCount]=Anchor.x;    //   this two lines record the value of
lYvalue[nCount]=Anchor.y;    //   x & y axis..
nTime[nCount]=nTimeCount;

// assume one and only one segment (this need to be removed, when segmentation routine is ready
nSegmentNumber[nCount]=1;
}

delete pDC;
}

void CDay10View::OnRButtonDown(UINT nFlags, CPoint point)
{

CString m_ptx;
m_ptx.Format("%d",m_ptPrevPos.x);
CString m_pty;
m_pty.Format("%d",m_ptPrevPos.y);
AfxMessageBox("X= "+m_ptx);
AfxMessageBox("Y= "+m_pty);

KillTimer(1);
AfxMessageBox("Time up!");

CView::OnRButtonDown(nFlags, point);
}

void CDay10View::OnTimer(UINT nIDEvent)
{
/*  if (nIDEvent==1)
{
if (bEnd==false)
{
if (nCount!=nMaxPoint)
{
PostMessage(WM_MOUSEMOVE);
lXvalue[nCount]=m_ptPrevPos.x;    //   this two lines record the value of
lYvalue[nCount]=m_ptPrevPos.y;    //   x & y axis..
bButtonDownStatus[nCount]=bCurrentButtonDownStatus;
nCount++;

}
else
{
KillTimer(1);
if (GetCapture() == this)
//if so, release it so other applications can have it
ReleaseCapture();

//code end here

nLength=nCount;
ShowPointValue();
bEnd=true;
bStart=false;
AfxMessageBox("Time Up!");
//          OnEnd();
}
}
else
{
KillTimer(1);
}
}
bEnd=true;
nLength=nCount;
ShowPointValue();
bStart=false;
KillTimer(1);
AfxMessageBox("Time Up!");  */

if (bEnd==false)
{
nTimeCount++;
}
else
nLength=nCount;

CView::OnTimer(nIDEvent);

}

void CDay10View::ShowPointValue()
{
int i;
for (i=0;i<nLength;i++)
{
CString m_ptX;
m_ptX.Format("%d",lXvalue[i]);        // lXvalue[i] & lYvalue[i] are an array
CString m_ptY;
m_ptY.Format("%d",lYvalue[i]);
CString strXY;
strXY="( "+m_ptX+" , "+m_ptY+")";

}

}

void CDay10View::OnRetrieve()                 // able to show back the point in the box
{
int i;
CClientDC dc(this);
dc.MoveTo(lXvalue[0], lYvalue[0]);
m_ptPrevPos.x=lXvalue[0];
m_ptPrevPos.y=lYvalue[0];
for (i=1;i<nLength;i++)
{
CString m_ptX;
m_ptX.Format("%d",lXvalue[i]);        // lXvalue[i] & lYvalue[i] are an array
CString m_ptY;
m_ptY.Format("%d",lYvalue[i]);
CString strStatus;

//      if (bButtonDownStatus[i])
//          strStatus="Down";
//      else
//          strStatus="Up";
//      CString strXY;
//       strXY="( "+m_ptX+" , "+m_ptY+") Status = "+ strStatus;
//      AfxMessageBox("Next point = "+strXY);

if (nSegmentNumber[i]==nSegmentNumber[i-1])
dc.LineTo(lXvalue[i], lYvalue[i]);
else
dc.MoveTo(lXvalue[i], lYvalue[i]);

m_ptPrevPos.x = lXvalue[i];              // draw back the line
m_ptPrevPos.y = lYvalue[i];
}

//  }
}

void CDay10View::OnCentrePos()
{
int i;
int a;                    //find min x value
a = lXvalue[0];
for (i=0;i<nLength;i++)
{
if (a > lXvalue[i])
{
a = lXvalue[i];
}
}
CString value;
CString comtext1;

value.Format("%d",a);
CString text1=("Min X=");        //declare of text to appear
CString text2=(value);

comtext1=_T(text1+text2);        // combine the two text
MessageBox(comtext1);            // show both text combine

int b;                 //find max x value
CString comtext2;
b = lXvalue[0];
for (i=0;i<nLength;i++)
{
if (b < lXvalue[i])
{
b = lXvalue[i];
}
}

value.Format("%d",b);
CString text3=("Max X=");       //declare of text to appear
CString text4=(value);

comtext2=_T(text3+text4);        // combine the two text
MessageBox(comtext2);            // show both text combine

int c;                  //find min y value
CString comtext3;
c = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (c > lYvalue[i])
{
c = lYvalue[i];
}
}

value.Format("%d",c);
CString text5=("Min Y=");       //declare of text to appear
CString text6=(value);

comtext3=_T(text5+text6);        // combine the two text
MessageBox(comtext3);            // show both text combine

int d;               //find max y value
CString comtext4;
d = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (d < lYvalue[i])
{
d = lYvalue[i];
}
}

value.Format("%d",d);
CString text7=("Max Y=");        //declare of text to appear
CString text8=(value);

comtext4=_T(text7+text8);         // combine the two text
MessageBox(comtext4);             // show both text combine

}

void CDay10View::OnCentrePoint()
{
int i;
long MinX;
long MaxX;
long MinY;
long MaxY;
MinX = lXvalue[0];
MaxX = lXvalue[0];
MinY = lYvalue[0];
MaxY = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (MinX > lXvalue[i])
{
MinX = lXvalue[i];
}

if (MaxX < lXvalue[i])
{
MaxX = lXvalue[i];
}

if (MinY > lYvalue[i])
{
MinY = lYvalue[i];
}

if (MaxY < lYvalue[i])
{
MaxY = lYvalue[i];
}

}

// CClientDC dc(this);
// dc.MoveTo(MinX, MaxY);
// dc.LineTo(MaxX, MinY);

// dc.MoveTo(MinX, MinY);
// dc.LineTo(MaxX, MaxY);

lCentrePointX = MinX+((MaxX-MinX)/2);

CString tmp;
tmp.Format("%d",lCentrePointX);
//MessageBox("Centre X= "+tmp);

lCentrePointY = MinY+((MaxY-MinY)/2);

tmp.Format("%d",lCentrePointY);
//MessageBox("Centre Y= "+tmp);
}

void CDay10View::OnHalf()
{
OnCentrePoint();

float Scale;
Scale=0.5;

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];
CString I, X, Y;
X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox("Original X,Y = "+X+" , "+Y);

lXvalue[i]=lOriginalXvalue[i]+((lCentrePointX-lOriginalXvalue[i])*(1-Scale));
lYvalue[i]=lOriginalYvalue[i]+((lCentrePointY-lOriginalYvalue[i])*(1-Scale));

I.Format("%d",i);

X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox(I +" New X,Y = "+X+" , "+Y);

}

OnRetrieve();

MessageBox("Scaling completed");

for (i=0;i<nLength;i++)
{
lXvalue[i]=lOriginalXvalue[i];
lYvalue[i]=lOriginalYvalue[i];
}
}

void CDay10View::OnQuarter()
{

OnCentrePoint();

float Scale;
Scale=0.25;

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];
CString I, X, Y;
X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox("Original X,Y = "+X+" , "+Y);

lXvalue[i]=lOriginalXvalue[i]+((lCentrePointX-lOriginalXvalue[i])*(1-Scale));
lYvalue[i]=lOriginalYvalue[i]+((lCentrePointY-lOriginalYvalue[i])*(1-Scale));

I.Format("%d",i);

X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox(I +" New X,Y = "+X+" , "+Y);

}

OnRetrieve();

MessageBox("Scaling completed");

for (i=0;i<nLength;i++)
{
lXvalue[i]=lOriginalXvalue[i];
lYvalue[i]=lOriginalYvalue[i];
}
}

void CDay10View::OnDouble()
{
OnCentrePoint();

float Scale;
Scale=2;

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];
CString I, X, Y;
X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox("Original X,Y = "+X+" , "+Y);

lXvalue[i]=lOriginalXvalue[i]+((lCentrePointX-lOriginalXvalue[i])*(1-Scale));
lYvalue[i]=lOriginalYvalue[i]+((lCentrePointY-lOriginalYvalue[i])*(1-Scale));

I.Format("%d",i);

X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox(I +" New X,Y = "+X+" , "+Y);

}

OnRetrieve();

MessageBox("Scaling completed");

for (i=0;i<nLength;i++)
{
lXvalue[i]=lOriginalXvalue[i];
lYvalue[i]=lOriginalYvalue[i];
}
}

void CDay10View::OnStart()
{
//grab it if the mouse leaves the window area
/*    SetCapture();
//  m_ptPrevPos = point;
bStart=true;
bEnd=false;
//  AfxMessageBox("OnStart");
SetTimer(1,ntmrDurValue,NULL); */

nCount=-1;
nTimeCount=0;
//  nCountNext=0;
bStart=false;
bEnd=true;
//  MessageBox("Start to Sign");

SetTimer(1,ntmrDurValue,NULL);

}

void CDay10View::OnEnd()
{
//have we captured the mouse?

AfxMessageBox("OnEnd");

//  afx_msg void OnCancelMode( );
}

void CDay10View::OnNormalBox()
{
int i;
long MinX;
long MaxX;
long MinY;
long MaxY;
MinX = lXvalue[0];
MaxX = lXvalue[0];
MinY = lYvalue[0];
MaxY = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (MinX > lXvalue[i])
{
MinX = lXvalue[i];
}

if (MaxX < lXvalue[i])
{
MaxX = lXvalue[i];
}

if (MinY > lYvalue[i])
{
MinY = lYvalue[i];
}

if (MaxY < lYvalue[i])
{
MaxY = lYvalue[i];
}

}

CClientDC dc(this);
dc.MoveTo(MinX, MaxY);
dc.LineTo(MaxX, MaxY);

dc.MoveTo(MaxX, MaxY);
dc.LineTo(MaxX, MinY);

dc.MoveTo(MaxX, MinY);
dc.LineTo(MinX, MinY);

dc.MoveTo(MinX, MinY);
dc.LineTo(MinX, MaxY);

lCentrePointX = MinX+((MaxX-MinX)/2);

CString tmp;
tmp.Format("%d",lCentrePointX);
//MessageBox("Centre X= "+tmp);

lCentrePointY = MinY+((MaxY-MinY)/2);

tmp.Format("%d",lCentrePointY);
//MessageBox("Centre Y= "+tmp);
}

void CDay10View::OnNormalArea()
{
long MinX;
long MaxX;
long MinY;
long MaxY;
long Length;
int i;

MinX = lXvalue[0];
MaxX = lXvalue[0];
MinY = lYvalue[0];
MaxY = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (MinX > lXvalue[i])
{
MinX = lXvalue[i];
}

if (MaxX < lXvalue[i])
{
MaxX = lXvalue[i];
}

if (MinY > lYvalue[i])
{
MinY = lYvalue[i];
}

if (MaxY < lYvalue[i])
{
MaxY = lYvalue[i];
}

}

CClientDC dc(this);
dc.MoveTo(MinX, MaxY);
dc.LineTo(MaxX, MaxY);

dc.MoveTo(MaxX, MaxY);
dc.LineTo(MaxX, MinY);

dc.MoveTo(MaxX, MinY);
dc.LineTo(MinX, MinY);

dc.MoveTo(MinX, MinY);
dc.LineTo(MinX, MaxY);

lCentrePointX = MinX+((MaxX-MinX)/2);

CString tmp;
tmp.Format("%d",lCentrePointX);
//MessageBox("Centre X= "+tmp);

lCentrePointY = MinY+((MaxY-MinY)/2);

tmp.Format("%d",lCentrePointY);
//MessageBox("Centre Y= "+tmp);

Length= MaxY-MinY;

//Set l & w of signature
sig_length = Length;

// CString tmp;
tmp.Format("%d",AreaBox);
MessageBox("Area of Box= "+tmp);

}

void CDay10View::OnNormalNormalize()
{
long PreviousArea;
OnNormalArea();
PreviousArea=1000000;
//AreaBox=(MaxX-MinX)*(MaxY-MinY);

while(AreaBox<PreviousArea)
{
PreviousArea=AreaBox;
OnCentrePoint();

long lOriginalCentrePointX=lCentrePointX;
long lOriginalCentrePointY=lCentrePointY;

float Angle;
Angle=5;

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];

}

OnCentrePoint();

for (i=0;i<nLength;i++)
{
lXvalue[i]=lXvalue[i]-(lCentrePointX-lOriginalCentrePointX);
lYvalue[i]=lYvalue[i]-(lCentrePointY-lOriginalCentrePointY);
}
OnRetrieve();

OnNormalArea();

}

while(AreaBox>PreviousArea)
{
//AreaBox=(MaxX-MinX)*(MaxY-MinY);

PreviousArea=AreaBox;
OnCentrePoint();

long lOriginalCentrePointX=lCentrePointX;
long lOriginalCentrePointY=lCentrePointY;

float Angle;
Angle=-5;

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];

}

OnCentrePoint();

for (i=0;i<nLength;i++)
{
lXvalue[i]=lXvalue[i]-(lCentrePointX-lOriginalCentrePointX);
lYvalue[i]=lYvalue[i]-(lCentrePointY-lOriginalCentrePointY);
}
OnRetrieve();

OnNormalArea();

}
MessageBox("Normalization Completed");
}

void CDay10View::OnNormalScreen()
{
OnNormalNormalize();
// move signature to centre of screen (510,322)
// then scale the signature to 30% of screen

long Scale;
Scale=(1021*645)*(80/100);

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

long PointX=510-lCentrePointX;
long PointY=321-lCentrePointY;

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];

lXvalue[i]=lOriginalXvalue[i]+PointX;
lYvalue[i]=lOriginalYvalue[i]+PointY;

}

OnRetrieve();
OnNormalBox();

MessageBox("Screening completed");

}

void CDay10View::FFT()
{
long nn;

nn=no_of_count();
four1(lXvalue,nn,1);
four1(lYvalue,nn,1);

}

void CDay10View::four1(long data[], unsigned long nn, int isign)
{
OnNormalTime();
//Temp for lXvalue
long lXvalue[nMaxPoint] = {0};

for(int b=0;b<nn;b++)

{

lXvalue[b]  = data[b];      //data array from intial 0 to maximum no of counts nn
}

unsigned long n,m,mmax,j,istep,i;
double wtemp,wr,wpr,wpi,wi,theta;
float tempr,tempi;
CString imp,imp2;

n=nn<<1;
j=1;
for(i=1;i<n;i+=2)
{
if(j>i)
{
SWAP(data[j],data[i]);
SWAP(data[j+1],data[i+1]);
}
m=n>>1;
while(m>=2 && j>m)
{
j-=m;
m>>=1;
}
j+=m;
}

mmax=2;
while(n>mmax)                   /*outer loop executed log2 nn times*/
{
istep=mmax<<1;
theta=isign*(6.28318530717959/mmax);        /* -j, 2pi, k/n */
wtemp=sin(0.5*theta);                       /* 0.5 might be k *
*could sin(theta)be equals to*
*e -j 2pi k/n ? */
wpr=-2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;
for(m=1;m<mmax;m+=2)
{
for(i=m;i<=n;i+=istep)
{
j=i+mmax;
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i]+=tempr;
data[i+1]+=tempi;
}
wr=(wtemp=wr)*wpr-wi*wpi+wr;
wi=wi*wpr+wtemp*wpi+wi;
}
mmax=istep;
}
//=================================================================
/*  CString FFTResult;
CString OriXValue;

for(i=0;i<nn;i++)
{
for(int l=0;l<10;l++)
{
int data1=lXvalue[i];
int data2=lYvalue[i];

imp.Format("%d",data[i]);
FFTResult += "\t"+imp;//FFT Result
imp.Format("%d",lXvalue[i]);
OriXValue += "\t"+imp;//Original value
i++;
}
imp.Format("%d",i);
imp2.Format("%d",i-10);
FFTResult += "\n\rXVal ="+OriXValue+"\n\r"+imp2+"->"+imp;
MessageBox("FFT="+FFTResult);
FFTResult = "";
OriXValue = "";
}
*/
}

int CDay10View::getXpos(int which_point)
{
return lXvalue[which_point];
}

int CDay10View::getYpos(int which_point)
{
return lYvalue[which_point];
}

int CDay10View::no_of_count()
{
long nn=0;
int i;

for(i=0;i<nMaxPoint;i++)
{
if(lXvalue[i]==0 && lYvalue[i]==0 && nTime[i]==0)
break;
nn=nn+1;
}

CString tmp;
tmp.Format("%d",nn);
MessageBox("No of point used ="+tmp);
return nn;
}

void CDay10View::OnSignatureCheck()
{

long xvalue,yvalue;

OnNormalNormalize();
FFT();

int i=0;
CString num1,num2,num3,num4;
float check1,check2,check3,check4;

FILE*fp;
FILE*fq;

fp=fopen("G:\\data_x.txt","r");
fq=fopen("G:\\data_y.txt","r");

MessageBox("Safe1");

if(fp==NULL)
{
MessageBox("ERROR.Need to save signature first");
}

else
{

MessageBox("Safe2");

while(!feof(fp))
{

fscanf(fp,"%ld",&xvalue);
fscanf(fq,"%ld",&yvalue);

num1.Format("%d",xvalue);
num2.Format("%d",lXvalue[i]);

MessageBox(" 1 -> "+num1+"    2 -> "+num2 );

num3.Format("%d",yvalue);
num4.Format("%d",lYvalue[i]);

MessageBox(" 3 -> "+num3+"    4 -> "+num4 );

if(lXvalue[i]==0 || xvalue==0 || lYvalue[i]==0 || yvalue==0 )
{
break;
}

else

{
check1 = xvalue/lXvalue[i];
check2 = lXvalue[i]/xvalue;

check3 = yvalue/lYvalue[i];
check4 = lYvalue[i]/yvalue;

if(check1 > 0.6 || check2 < 1.2 || check3 > 0.6 || check4 < 1.2 )
{

}

else

{
MessageBox("Wrong Signature");

}
}
i++;
}
}

}

void CDay10View::OnSignatureFft()
{
OnFileSave;
float Scale;

CString tmp,imp,amp,bmp;

OnNormalScreen();
OnNormalArea();

if(sig_length>sig_width)
{
Scale = 450.0 / sig_length;
}
else
{
Scale = 750.0 / sig_width;
}
On_enlarge(Scale);

int nn=no_of_count();

for(int i=0;i<nn;i++)
{
tmp.Format("%ld",lXvalue[i]);
imp.Format("%ld",lYvalue[i]);

MessageBox("X="+tmp);
MessageBox("Y="+imp);

}

four1(lXvalue,nn,1);
for(i=0;i<nn;i++)
{
tmp.Format("%ld",lXvalue[i]);
MessageBox("FFT(X)="+tmp);
}

four1(lYvalue,nn,1);
for(i=0;i<nn;i++)
{
tmp.Format("%ld",lYvalue[i]);
MessageBox("FFT(Y)="+tmp);
}

}

void CDay10View::OnFileSave()
{

/*  OnSignatureFft();       //normalize the signature w/respect to x-axis
//do the FFT function

FILE*fp;
FILE*fq;

fp=fopen("G:\\data_x.txt","w");

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{
for(int i=0;i<nMaxPoint;i++)
{
fprintf(fp,"%ld\n",lXvalue[i]);
//fprintf(fp,"%ld\n",lYvalue[i]);

}

//MessageBox("Signature saved.");

}
fclose( fp );

fq=fopen("G:\\data_y.txt","w");

if(fq==NULL)

MessageBox("Signature NOT saved.");

else
{
for(int i=0;i<nMaxPoint;i++)
{
fprintf(fq,"%ld\n",lYvalue[i]);

}

//MessageBox("Signature saved.");

}
fclose( fp );

MessageBox("Signature saved.");  */

FILE*fp;
//FILE*fq;

fp=fopen("G:\\data.txt","w");

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{

//START:PLEASE DEBUG (LOOK BELOW - "FOR EXAMPLE")
//etc. nMaxPoint = {0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3,...}
fprintf(fp, "Reference signature\n");

int interXValue[2000];
int interYValue[2000];
int lastTime, counter, valCounter;

lastTime = -1;
counter = 0;
valCounter = 0;

while(lXvalue[counter] > 0)
{
if (lastTime != nTime[counter]) {
lastTime = nTime[counter];
interXValue[valCounter] = lXvalue[counter];
interYValue[valCounter++] = lYvalue[counter];

}
counter++;
}

for(int s=0; s< valCounter-1; s++)
{
float interPolateXVal, interPolateYVal;
interPolateXVal = (interXValue[s] + ((interXValue[s+1] - interXValue[s]) /* * (0.167-(1/valCounter))*/));
interPolateYVal = (interYValue[s] + ((interYValue[s+1] - interYValue[s]) /* * (0.167-(1/valCounter))*/));

fprintf(fp, "%d, %f, %f\n", s, interPolateXVal, interPolateYVal);
}
//END

fprintf(fp,"--------------------------------------------------------------------------------\n");
fprintf(fp,"|Index\t\t\t|X point\t|Y point\t|Time\t|Segment Number|\n");
fprintf(fp,"--------------------------------------------------------------------------------\n");

for(int i=0;i<nMaxPoint;i++)
{
if(lXvalue[i] < 0 && lYvalue[i] < 0  && nTime[i] < 0 && nSegmentNumber[i])
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
nSegmentNumber[i] = 0;
}

fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|%ld\t\t|\n",i,lXvalue[i],lYvalue[i],nTime[i],nSegmentNumber[i]);
}

}
fclose( fp );

/*fq=fopen("G:\\data_y.txt","w");

if(fq==NULL)

MessageBox("Signature NOT saved.");

else
{
for(int i=0;i<nMaxPoint;i++)
{
fprintf(fq,"%ld\n",lYvalue[i]);

}

//MessageBox("Signature saved.");

}
fclose( fp );*/

MessageBox("Signature saved.");

}

/*
--- FOR EXAMPLE

float CDay10View::interploate(int y1, int y2, int timeMax, int scale)
{
return (y1 + ((y2-y1)*((1/scale)-(1/timeMax))));
}
*/

void CDay10View::OnNormal_Screen()
{
OnNormalNormalize();

long MinX;
long MaxX;
long MinY;
long MaxY;
long Length;
int i;

MinX = lXvalue[0];
MaxX = lXvalue[0];
MinY = lYvalue[0];
MaxY = lYvalue[0];
for (i=0;i<nLength;i++)
{
if (MinX > lXvalue[i])
{
MinX = lXvalue[i];
}

if (MaxX < lXvalue[i])
{
MaxX = lXvalue[i];
}

if (MinY > lYvalue[i])
{
MinY = lYvalue[i];
}

if (MaxY < lYvalue[i])
{
MaxY = lYvalue[i];
}

}

CClientDC dc(this);
dc.MoveTo(MinX, MaxY);
dc.LineTo(MaxX, MaxY);

dc.MoveTo(MaxX, MaxY);
dc.LineTo(MaxX, MinY);

dc.MoveTo(MaxX, MinY);
dc.LineTo(MinX, MinY);

dc.MoveTo(MinX, MinY);
dc.LineTo(MinX, MaxY);

lCentrePointX = MinX+((MaxX-MinX)/2);

lCentrePointY = MinY+((MaxY-MinY)/2);

Length= MaxY-MinY;

OnRetrieve();
OnNormalBox();

{
if(Length!=819)
{
if(Length<819)
{
OnDouble();
}
else
{
OnQuarter();
}
}
}
{
{
{
OnDouble();
}
else
{
OnQuarter();
}
}
}
}

void CDay10View::On_enlarge(float Scale)
{
OnCentrePoint();

long lOriginalXvalue[nMaxPoint];
long lOriginalYvalue[nMaxPoint];

for (int i=0;i<nLength;i++)
{
lOriginalXvalue[i]=lXvalue[i];
lOriginalYvalue[i]=lYvalue[i];
CString I, X, Y;
X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox("Original X,Y = "+X+" , "+Y);

lXvalue[i]=lOriginalXvalue[i]+((lCentrePointX-lOriginalXvalue[i])*(1.0-Scale));
lYvalue[i]=lOriginalYvalue[i]+((lCentrePointY-lOriginalYvalue[i])*(1.0-Scale));

I.Format("%d",i);

X.Format("%d",lXvalue[i]);
Y.Format("%d",lYvalue[i]);
//      MessageBox(I +" New X,Y = "+X+" , "+Y);

}

OnRetrieve();

MessageBox("Scaling completed");

for (i=0;i<nLength;i++)
{
lXvalue[i]=lOriginalXvalue[i];
lYvalue[i]=lOriginalYvalue[i];
}
}

void CDay10View::MakeAllFlagsFalse()
{
bDrawFlag = FALSE;
}

void CDay10View::OnToolsDrawfreehand()
{
MakeAllFlagsFalse();
bDrawFlag = TRUE;

}

void CDay10View::OnUpdateToolsDrawfreehand(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(bDrawFlag);

}

void CDay10View::OnNormalTime()
{

// get the Reference data
FILE*fp;
FILE*fq;

fp=fopen("G:\\data.txt","r");

// i.e. get nLengthRef, lXvalueRef, lYvalueRef, nTimeRef, nSegmentNumberRef

// Get nSegmentCount of the Reference Signature and the specimen signature
int nSegmentCountRef;
int nSegmentCount;

nSegmentCountRef=nSegmentNumberRef[nLengthRef-1];
nSegmentCount=nSegmentNumber[nLength-1];

// assumed the two segment counts are the same; else, we need to throw away the extra

int nTimeCountRef=0;
int nTimeCount=0;

int nRefPointerPosition=0;
int nPointerPosition=0;

int nInitialRefPointerPosition=0;
int nInitialPointerPosition=0;

int nPointerPositionNom=0;

for (int i=1 ; i<(nSegmentCountRef+1); i++)
{
// register the initial PointerPosition
nInitialRefPointerPosition=nRefPointerPosition;
nInitialPointerPosition=nPointerPosition;

nTimeCountRef=0;
nTimeCount=0;

// get nTimeCount
while (nSegmentCountRef/*[nRefPointerPosition]*/==i)
{
nRefPointerPosition++;
}
nTimeCountRef=nTimeRef[nRefPointerPosition]-nTimeRef[nInitialRefPointerPosition]+1;

while (nSegmentCount/*[nPointerPosition]*/==i)
{
nPointerPosition++;
}
nTimeCount=nTime[nPointerPosition]-nTime[nInitialPointerPosition]+1;

// Proceed to do the interpolation now for i segment
// first the two end condition
lXvalueNom[nPointerPositionNom]=lXvalue[nInitialPointerPosition];
lYvalueNom[nPointerPositionNom]=lYvalue[nInitialPointerPosition];
lXvalueNom[nPointerPositionNom+nTimeCountRef]=lXvalue[nPointerPosition];  // we assumed that the last nTime of the segment has only one element
lYvalueNom[nPointerPositionNom+nTimeCountRef]=lYvalue[nPointerPosition];

for (int j=nPointerPositionNom+1; j<(nPointerPositionNom+nTimeCountRef); j++)
{
float fTimeNoPosition;
int nIdexStartTimeNo;
int nIdexStart;
int nIdexCount=0;

fTimeNoPosition=(j-nPointerPositionNom)/(nTimeCountRef-1)*(nTimeCount);
nIdexStartTimeNo=INT(fTimeNoPosition);  // convert from real to int type

for (int k=nInitialPointerPosition; k<nPointerPosition; k++)
{
if (nTime[k]<nIdexStartTimeNo)
{
nIdexStart=k;
k=nPointerPosition;
}
}

for (int m=nIdexStart; m<nPointerPosition; m++)
{
if (nTime[m]<(nIdexStartTimeNo+1))
{
m=nPointerPosition;
}
else
nIdexCount++;
}

// Assumed linear between two captured points. In future, it can do a curve fitting.
// we only take care of one decimal accuracy
float fIdexFraction;
fIdexFraction=fTimeNoPosition-nIdexStartTimeNo;

float fIdexPosition;
float fLastFraction;

fLastFraction=(nIdexCount-1)/nIdexCount;
fIdexPosition=fIdexFraction*nIdexCount;

if (fIdexPosition<=fLastFraction)
{
// then it is an interpolation

// find the first position of the Idex
int nIdexStartElement=0;
for (int n=1; n<nIdexCount; n++)
{
if (fIdexFraction<(n/nIdexCount))
{
nIdexStartElement++;
}
else
n=nIdexCount;   // break it to end
}

// compute now
float fInterpolationFraction;

fInterpolationFraction=(fIdexFraction-(nIdexStartElement/nIdexCount))/(1/nIdexCount);
lXvalueNom[j]=lXvalue[nIdexStart+nIdexStartElement]+(lXvalue[nIdexStart+nIdexStartElement+1]-lXvalue[nIdexStart+nIdexStartElement])*fInterpolationFraction;
lYvalueNom[j]=lYvalue[nIdexStart+nIdexStartElement]+(lYvalue[nIdexStart+nIdexStartElement+1]-lYvalue[nIdexStart+nIdexStartElement])*fInterpolationFraction;
}
else
{
// then it is an extrapolation of the last fraction
float fExtrapolationFraction;
fExtrapolationFraction=(fIdexFraction-((nIdexCount-1)/nIdexCount))/(1/nIdexCount);
lXvalueNom[j]=lXvalue[nIdexStart+nIdexStartElement]+(lXvalue[nIdexStart+nIdexStartElement]-lXvalue[nIdexStart+nIdexStartElement-1])*fExtrapolationFraction;
lYvalueNom[j]=lYvalue[nIdexStart+nIdexStartElement]+(lYvalue[nIdexStart+nIdexStartElement]-lYvalue[nIdexStart+nIdexStartElement-1])*fExtrapolationFraction;

}

}

// update the Nom array pointer
nPointerPositionNom=nPointerPositionNom+nTimeCountRef+1;

}

}

0

LVL 39

Expert Comment

ID: 10961366
Ok, could find some issues:

1. The program collects points in OnMouseMove. The mouse isn't captured but that doesn't matter as long as the cursur doesn't move outside the view
window. For each point a 'line' (prevoius point and current point) gets stored to the documents's line array.

2. A timer is set with a current timeout value of 10 ms. That constant seemed to be changed to other timer values obviously to control speed of mouse
capturing using a timer. In the OnTimer function  the last saved mouse position (point) gets stored to the lxvalue resp. lyvalue array we've seen above.
Also a time counter gets stored that counts that ot incremented in the OnTimer function thus counts the number of times OnTimer was called.

All point values finally get stored to a file and there are some functions to evaluate, recalculate and draw the points.

There is one big mistake in OnTimer by calling

PostMessage(WM_MOUSEMOVE);

Evidently it was an attempt to increase the number of mosue move events. However, as the message doesn't supply any parameters beside of the message itself, the 'point' argument of OnMouseMove defaults to (0, 0) what makes no sense.

The fundamental problem with the design described before is, that it would need much more mouse events within a given time period as normally get fired. I tried to move the mouse as fast as i could and didn't get more than 50 - 60 mouse moves a second, mostly less. So, the OnTimer function often catches the same mouse point. By increasing the timer value the number of duplicates decreases, however the final result is even worse as the few duplicates got a greater statistical weight as if any mouse move point gets duplicated or tripled. In my opinion, the best 'curve' would come up if the timer would be omitted and all points got collected in the OnMouseMove function. But i might be wrong if a mouse is used that sends more events like a gamer mouse or a  graph tablet.

In any case, it is wrong to collect the points in OnTimer. It's better to collect them in OnMouseMove and if you would like create some additional points depending on the speed of mouse events you have to associate a time value - e. g. 60000* minutes + 1000 * seconds + milliseconds of the current system time - to the collected point. You can get the system time by calling GetSystemTime(..). Having time and points you may make an interpolation using cubic splines that would give you - say one point per millisecond. You have to calculate splines separatly for x and y and finally bring the values together. For cubic splines there should be a lot of implementations to get freely.

Regards, Alex

0

Author Comment

ID: 10965329
Aex, the second project i have done is the interpolation and extrapolation. I have improve on my porgram. NOw i have a problem doing the reference signature. This reference signature acts as a template to save the signature where it shows nLength,lxvalue,lyvalue,nTime,nSegment number(is always one because now i assume it to be a linear line only) ,but tis reference signature onli extracts the first of every lxvalue and lyvalue. NOw my results came out like tis:

Index       lxvalue            lyvalue            nTime                  nSegmentNumber
0               238              244                  0                           1
1               240              243                  0                           1
2               242              242                  0                           1
3               248              239                  1                           1
4               255              236                  1                           1
5               266              233                  1                           1
6               278              230                  2                           1
7               294              225                  2                           1
8               310              220                  2                           1
9               326              216                  3                           1
10             340              211                  3                           1
11             352              207                  3                           1
12             360              203                  4                           1
13             366              199                  4                           1
14             369              196                  4                           1
15             371              194                  4                           1
16             372              193                  5                           1
17             373              191                  5                           1

Then actually the reference signature should show like tis:

(         )     nLength   // length of the array

Index       lxvalue             lyvalue            nTime                  nSegment Number
0             238                    244               0                               1
1             248                    239               1                               1
2             278                    230               2                               1
3             326                    216               3                               1
4             360                    203               4                               1
5             372                    193               5                               1

HOw do i go doing it to extraact every first set of value?

the code for first one is like tis:
void CDay10View::OnFileSave()
{

FILE*fp;
//FILE*fq;

fp=fopen("C:\\data.txt","w");

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{
fprintf(fp,"-------------------------------------------------------------------------------------\n");
fprintf(fp,"|Index\t\t\t|X point\t|Y point\t|Time\t|Segment Number|\n");
fprintf(fp,"-------------------------------------------------------------------------------------\n");

for(int i=0;i<nMaxPoint;i++)
{
if(lXvalue[i] < 0 && lYvalue[i] < 0 && nTime[i] < 0 && nSegmentNumber[i])
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
nSegmentNumber[i] = 0;

}

fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|%ld\t\t|\n",i,lXvalue[i],lYvalue[i],nTime[i],nSegmentNumber[i]);
}

}
fclose( fp );
MessageBox("Signature saved.");

}

0

LVL 39

Expert Comment

ID: 10966279
To print only the first values to a timer value use this:

void CDay10View::OnFileSave()
{

FILE*fp;
//FILE*fq;

fp=fopen("C:\\data.txt","w");

int nTimeLast  = -1;
int nCountSet  = 0;

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{
fprintf(fp,"-------------------------------------------------------------------------------------\n");
fprintf(fp,"|Index\t\t\t|X point\t|Y point\t|Time\t|Segment Number|\n");
fprintf(fp,"-------------------------------------------------------------------------------------\n");

for(int i=0;i<nMaxPoint;i++)
{
if(lXvalue[i] < 0 && lYvalue[i] < 0 && nTime[i] < 0 && nSegmentNumber[i])
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
nSegmentNumber[i] = 0;

}

// check if timer changed
if (nTime[i] != nTimeLast)
{
// increase set counter
++nCountSet;
fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|%ld\t\t|\n",nCountSet,lXvalue[i],lYvalue[i],nTime[i],nSegmentNumber[i]);
nTimeLast = nTime[i];
}
}

}
fclose( fp );
MessageBox("Signature saved.");

}

However, may be you should better use the average of all values of a set:

void CDay10View::OnFileSave()
{

FILE*fp;
//FILE*fq;

fp=fopen("C:\\data.txt","w");

int nTimeLast  = -1;

int nSumXVal   = 0;
int nSumYVal   = 0;
int nCountVal  = 0;
int nCountSet  = 0;

if(fp==NULL)

MessageBox("Signature NOT saved.");

else
{
fprintf(fp,"-------------------------------------------------------------------------------------\n");
fprintf(fp,"|Index\t\t\t|X point\t|Y point\t|Time\t|Segment Number|\n");
fprintf(fp,"-------------------------------------------------------------------------------------\n");

for(int i=0;i<nMaxPoint;i++)
{
if(lXvalue[i] < 0 && lYvalue[i] < 0 && nTime[i] < 0 && nSegmentNumber[i])
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
nSegmentNumber[i] = 0;

}

if (nTime[i] != nTimeLast && nCountVal > 0)
{
// increase set counter
++nCountSet;
nSumXVal /= nCountVal;
nSumYVal /= nCountVal;

fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|%ld\t\t|\n",nCountSet,nSumXVal,nSumYVal,nTime[i-1],nSegmentNumber[i-1]);

// reset values
nTimeLast = nTime[i];
nCountVal = 0;
nSumXVal  = 0;
nSumYVal  = 0;
}
// collect values for average
++nCountVal;
nSumXVal += lXvalue[i];
nSumYVal += lYvalue[i];
}
// print last average
++nCountSet;
nSumXVal /= nCountVal;
nSumYVal /= nCountVal;

fprintf(fp,"|\t%d\t\t|%ld\t\t|%ld\t\t|%d\t|%ld\t\t|\n",nCountSet,nSumXVal,nSumYVal,nTime[i-1],nSegmentNumber[i-1]);
}
fclose( fp );
MessageBox("Signature saved.");

}

I got your mail and will find time sunday evening (CEST) or monday morning to look thru.

Regards, Alex
0

Author Comment

ID: 10967015
Thanks a lot Alex.  Hope to hear the gd news form ya.

0

LVL 39

Expert Comment

ID: 10973574
Could you send me your project again.

I lost your last mail because of my spam filter.
yahoo.com isn't my favourite provider ;-)

Regards, Alex
0

Author Comment

ID: 10973997
Alex i have send my project already. please kindly help mi look into it and link the project as soon as possible.Thanks for the trouble.
0

LVL 39

Assisted Solution

itsmeandnobodyelse earned 1440 total points
ID: 10982043
I could compile and link the program and finally i found out how to store points. The problem was these statements in CDay10View::OnFileSave()

if(lXvalueRef[i] < 0 && lYvalueRef[i] < 0 && nTimeRef[i] < 0 && nSegmentNumberRef[i])
{
lXvalue[i] = 0;
lYvalue[i] = 0;
nTime[i]   = 0;
nSegmentNumber[i] = 0;

}

As all these arrays hadn't been initialized the condition was true and all the values that had been recorded before were now zero! But now i have some questions on that:

Where do you intend to get the reference values from?

I saw an open of c:\dat1.txt that had been commented. Do you expect to get the reference values from that? And if so, how do they happen to become negative?

The file data1.txt could be written by using OnFileSaveAs instead of OnFileSave. However, you don't store average values there as you do with OnFileSave(). So, i assume you are intending to get the reference values by storing with OnFileSave and renaming the file from data.txt to data1.txt. Is that correct?

You write, you have problems with 'normalization' and i found a lot of functions like OnNormalBox, OnNormalArea, OnNormalNormalize,  OnNormalScreen, OnNormalTime, where i couldn't find out what's the purpose. Unfortunately, my knowledge regarding signatures and comparing them is very thin, although i could make some suggestions - which may be far off the last state of Science. Ok, let's try:

You have two sets of coordinates associated with a timer value and a segment number (that should be incremented if the user made a new left mouse click). Both sets will have most likely no points in common.

First, find out minimum and maximum of each set (x and y separated) and subtract minimum from any point and from both maximum values. Then, calculate the relation between both maxima and normalize each point using that normaliazation factor, also x and y separatedly. Finally, we could make linear interpolation by calculating  the pair (a, b) where y = ax +b for any line between two points of any set. From that line set we now extract 2000 equidistant points regarding the x-value and calculate the y-values using the lines set. Note, i didn't use the timer value as in my opinion it has no weight in all. Whether the user draws slowly or fast makes no significant difference on the shape of the signature.

At this moment you could draw both images using the new points. As a measure how good both signatures fit you may take the sum of the absolute y-value differences or the difference between both integrals. I've heard with Fast Fourier Transformation you could also compare images. However, i can't remember on that part of my college lessons in math, so you would have to help me on that.

If you agree on that kind of normalization, i would do the C++ calculation for you, while you had to draw lines and make the dialog and menu part. If not, you should give me the mathematical basics of the calculations you want to perform and i would do the C++ part later.

Regards, Alex
0

Author Comment

ID: 11088808
sorry for the late reply Alex ..my computer break down..well u have helped mi a lot ..i will continue my project from here..thanks a lot for your help.
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Finishing the grid â€“ keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. â€¦
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informatâ€¦
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonstâ€¦
###### Suggested Courses
Course of the Month9 days, 3 hours left to enroll