455 lines
13 KiB
Plaintext
455 lines
13 KiB
Plaintext
#include <stdio.h>
|
||
#include <math.h>
|
||
#include <mdiwin/main.hpp>
|
||
#include <mdiwin/mesh.hpp>
|
||
|
||
char GridMesh::szClassName[]="MESH93B";
|
||
char GridMesh::szMenuName[]={'\0'};
|
||
|
||
GridMesh::GridMesh(HWND hParent,int width,int height,GridShow visibility)
|
||
: mhParent(hParent), mStatus(InActive), mGridLines(GridLines), mStandardColor(RGB(0,0,0)),
|
||
mIsSuspended(FALSE), mhInstance(Main::processInstance())
|
||
{
|
||
mVersionInfo=szClassName;
|
||
mhDrawingPen=::CreatePen(PS_SOLID,1,mStandardColor);
|
||
registerClass();
|
||
::CreateWindowEx(WS_EX_TRANSPARENT,(LPSTR)szClassName,0,
|
||
WS_CHILD|WS_CLIPSIBLINGS,
|
||
CW_USEDEFAULT,CW_USEDEFAULT,
|
||
width,height,
|
||
mhParent,0x00,mhInstance,(LPSTR)(Window*)this);
|
||
if(GridMesh::Show==visibility)
|
||
{
|
||
Window::Show(SW_SHOW);
|
||
Update();
|
||
::InvalidateRect(GetHandle(),0,TRUE);
|
||
}
|
||
}
|
||
|
||
GridMesh::~GridMesh()
|
||
{
|
||
::DeleteObject(mhDrawingPen);
|
||
if(::IsWindow(GetHandle()))::DestroyWindow(GetHandle());
|
||
}
|
||
|
||
void GridMesh::registerClass(void)
|
||
{
|
||
WNDCLASS wndClass;
|
||
|
||
if(::GetClassInfo(mhInstance,szClassName,(WNDCLASS FAR *)&wndClass))return;
|
||
wndClass.style =CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
|
||
wndClass.lpfnWndProc =(WNDPROC)::WndProc;
|
||
wndClass.cbClsExtra =0;
|
||
wndClass.cbWndExtra =sizeof(GridMesh*);
|
||
wndClass.hInstance =mhInstance;
|
||
wndClass.hIcon =0;
|
||
wndClass.hCursor =::LoadCursor(NULL,IDC_ARROW);
|
||
wndClass.hbrBackground =(HBRUSH)::GetStockObject(NULL_BRUSH);;
|
||
wndClass.lpszMenuName =szMenuName;
|
||
wndClass.lpszClassName =szClassName;
|
||
::RegisterClass(&wndClass);
|
||
}
|
||
|
||
long GridMesh::WndProc(UINT message,WPARAM wParam,LPARAM lParam)
|
||
{
|
||
switch(message)
|
||
{
|
||
case WM_CREATE :
|
||
::SendMessage(GetHandle(),WM_NCACTIVATE,TRUE,0L);
|
||
newMesh();
|
||
return FALSE;
|
||
case WM_PAINT :
|
||
paint();
|
||
return FALSE;
|
||
case WM_LBUTTONUP :
|
||
mouseUp(LOWORD(lParam),HIWORD(lParam));
|
||
return FALSE;
|
||
case WM_LBUTTONDOWN :
|
||
mouseDown(LOWORD(lParam),HIWORD(lParam));
|
||
return FALSE;
|
||
case WM_MOUSEMOVE :
|
||
mouseMove(LOWORD(lParam),HIWORD(lParam));
|
||
return FALSE;
|
||
case WM_DESTROY :
|
||
return FALSE;
|
||
}
|
||
return ::DefWindowProc(GetHandle(),message,wParam,lParam);
|
||
}
|
||
|
||
void GridMesh::showWindow(int visible)
|
||
{
|
||
Window::Show(visible?SW_SHOW:SW_HIDE);
|
||
::InvalidateRect(GetHandle(),0,TRUE);
|
||
}
|
||
|
||
void GridMesh::newMesh(WORD gridLines)
|
||
{
|
||
createMesh(gridLines,(Vector<Segment>&)*this);
|
||
::InvalidateRect(mhParent,0,TRUE);
|
||
::InvalidateRect(GetHandle(),0,TRUE);
|
||
}
|
||
|
||
void GridMesh::createMesh(WORD gridLines,Vector<Segment> &someSegmentVector)
|
||
{
|
||
RECT clientRect;
|
||
WORD xLength;
|
||
WORD yLength;
|
||
Point tempFirstPoint;
|
||
Point tempSecondPoint;
|
||
WORD vectorSize(0);
|
||
Index vectorIndex(0);
|
||
|
||
if(gridLines>MaxGridLines)mGridLines=GridLines;
|
||
else mGridLines=gridLines;
|
||
::GetClientRect(GetHandle(),(RECT FAR *)&clientRect);
|
||
xLength=clientRect.right/(mGridLines+1);
|
||
yLength=clientRect.bottom/(mGridLines+1);
|
||
for(int x=0,xCount=0;xCount<=mGridLines;x+=xLength,xCount++)
|
||
for(int y=0,yCount=0;yCount<=mGridLines;y+=yLength,yCount++)vectorSize+=2;
|
||
someSegmentVector.size(vectorSize);
|
||
for(x=0,xCount=0;xCount<=mGridLines;x+=xLength,xCount++)
|
||
{
|
||
for(int y=0,yCount=0;yCount<=mGridLines;y+=yLength,yCount++)
|
||
{
|
||
tempFirstPoint.setPoint(x+xLength,y+yLength);
|
||
tempSecondPoint.setPoint(x+xLength,y);
|
||
someSegmentVector[vectorIndex]=Segment(tempFirstPoint,tempSecondPoint,(WORD)vectorIndex);
|
||
vectorIndex++;
|
||
tempSecondPoint.setPoint(x,y+yLength);
|
||
someSegmentVector[vectorIndex]=Segment(tempFirstPoint,tempSecondPoint,(WORD)vectorIndex);
|
||
vectorIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void GridMesh::paint(void)const
|
||
{
|
||
PAINTSTRUCT ps;
|
||
HDC hDC;
|
||
size_t size((int)Vector<Segment>::size());
|
||
|
||
hDC=::BeginPaint(GetHandle(),(PAINTSTRUCT FAR*)&ps);
|
||
for(int i=0;i<size;i++)
|
||
(Vector<Segment>::operator[](i)).drawSegment(hDC,mhDrawingPen);
|
||
::EndPaint(GetHandle(),(PAINTSTRUCT FAR *)&ps);
|
||
}
|
||
|
||
void GridMesh::mouseDown(int x,int y)
|
||
{
|
||
HDC hDC;
|
||
Point mousePoint;
|
||
size_t size;
|
||
|
||
if(mIsSuspended)return;
|
||
mCurrentIntersection.remove();
|
||
mousePoint.setPoint(x,y);
|
||
if(!closestIntersection(mCurrentIntersection,mousePoint))
|
||
{
|
||
mStatus=InActive;
|
||
::MessageBeep(-1);
|
||
return;
|
||
}
|
||
mStatus=Active;
|
||
hDC=::GetDC(GetHandle());
|
||
size=(int)mCurrentIntersection.size();
|
||
for(int i=0;i<size;i++)
|
||
mCurrentIntersection[i].drawSegment(hDC,mhDrawingPen);
|
||
for(i=0;i<size;i++)
|
||
mCurrentIntersection[i].drawSegment(hDC,mhDrawingPen);
|
||
::ReleaseDC(GetHandle(),hDC);
|
||
}
|
||
|
||
void GridMesh::mouseMove(int x,int y)
|
||
{
|
||
HDC hDC;
|
||
Point mousePoint;
|
||
size_t size;
|
||
int index;
|
||
|
||
if(InActive==mStatus)return;
|
||
hDC=::GetDC(GetHandle());
|
||
mousePoint.setPoint(x,y);
|
||
size=(int)mCurrentIntersection.size();
|
||
for(index=0;index<size;index++)
|
||
mCurrentIntersection[index].drawSegment(hDC,mhDrawingPen);
|
||
for(index=0;index<size;index++)
|
||
mCurrentIntersection[index].firstPoint(mousePoint);
|
||
for(index=0;index<size;index++)
|
||
mCurrentIntersection[index].drawSegment(hDC,mhDrawingPen);
|
||
::ReleaseDC(GetHandle(),hDC);
|
||
}
|
||
|
||
void GridMesh::mouseUp(int x,int y)
|
||
{
|
||
HDC hDC;
|
||
Point swapPoint;
|
||
Point mousePoint;
|
||
size_t size;
|
||
int index;
|
||
|
||
if(InActive==mStatus)return;
|
||
mStatus=InActive;
|
||
hDC=::GetDC(GetHandle());
|
||
mousePoint.setPoint(x,y);
|
||
size=(int)mCurrentIntersection.size();
|
||
for(index=0;index<size;index++)
|
||
Vector<Segment>::operator[](mCurrentIntersection[index].vectorIndex())=mCurrentIntersection[index];
|
||
size=(int)Vector<Segment>::size();
|
||
for(int i=0;i<size;i++)(Vector<Segment>::operator[](i)).drawSegment(hDC,mhDrawingPen);
|
||
::ReleaseDC(GetHandle(),hDC);
|
||
::InvalidateRect(GetHandle(),0,TRUE);
|
||
::UpdateWindow(GetHandle());
|
||
}
|
||
|
||
WORD GridMesh::closestIntersection(Block<Segment> &filterBlock,Point &mousePoint)
|
||
{
|
||
DWORD tempDistance;
|
||
DWORD leastDistance;
|
||
Segment tempSegment;
|
||
Segment minSegment;
|
||
size_t size((int)Vector<Segment>::size());
|
||
|
||
if(!size)return FALSE;
|
||
filterBlock.remove();
|
||
while(IntersectionSegments!=filterBlock.size())
|
||
{
|
||
for(int index=0;index<size;index++)
|
||
{
|
||
if(!index)
|
||
{
|
||
tempSegment=Vector<Segment>::operator[](index);
|
||
while(isInBlock(filterBlock,tempSegment))
|
||
tempSegment=Vector<Segment>::operator[](++index);
|
||
leastDistance=minDistance(tempSegment,mousePoint);
|
||
}
|
||
else
|
||
{
|
||
tempDistance=minDistance(Vector<Segment>::operator[](index),mousePoint);
|
||
if(tempDistance<leastDistance)
|
||
{
|
||
minSegment=Vector<Segment>::operator[](index);
|
||
if(!isInBlock(filterBlock,minSegment))
|
||
{
|
||
tempSegment=minSegment;
|
||
leastDistance=tempDistance;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
filterBlock.insert(&tempSegment);
|
||
}
|
||
return orderIntersection(filterBlock);
|
||
}
|
||
|
||
WORD GridMesh::orderIntersection(Block<Segment> &intersection)
|
||
{
|
||
Point tempPoint;
|
||
Point swapPoint;
|
||
size_t size((int)intersection.size());
|
||
int firstSection(0);
|
||
int secondSection(0);
|
||
int index;
|
||
|
||
if(IntersectionSegments!=size)return FALSE;
|
||
tempPoint=intersection[0].firstPoint();
|
||
firstSection=(tempPoint==intersection[1].firstPoint());
|
||
if(!firstSection)firstSection=(tempPoint==intersection[1].secondPoint());
|
||
if(!firstSection)
|
||
{
|
||
tempPoint=intersection[0].secondPoint();
|
||
secondSection=tempPoint==intersection[1].firstPoint();
|
||
if(!secondSection)secondSection=tempPoint==intersection[1].secondPoint();
|
||
}
|
||
if(!firstSection && !secondSection)return FALSE;
|
||
for(index=1;index<size;index++)
|
||
{
|
||
if(!(tempPoint==intersection[index].firstPoint())&&
|
||
!(tempPoint==intersection[index].secondPoint()))return FALSE;
|
||
}
|
||
if(secondSection)
|
||
{
|
||
swapPoint=intersection[0].firstPoint();
|
||
intersection[0].firstPoint(intersection[0].secondPoint());
|
||
intersection[0].secondPoint(swapPoint);
|
||
}
|
||
for(index=1;index<size;index++)
|
||
{
|
||
if(!(tempPoint==intersection[index].firstPoint()))
|
||
{
|
||
intersection[index].secondPoint(intersection[index].firstPoint());
|
||
intersection[index].firstPoint(tempPoint);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
WORD GridMesh::isInBlock(Block<Segment> &source,Segment &someSegment)
|
||
{
|
||
size_t size((int)source.size());
|
||
|
||
for(int i=0;i<size;i++)if(source[i]==someSegment)return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
DWORD GridMesh::minDistance(const Segment &someSegment,const Point &somePoint)
|
||
{
|
||
LONG yTemp;
|
||
LONG xTemp;
|
||
LONG midy;
|
||
LONG midx;
|
||
LONG distancePointOne;
|
||
LONG distancePointTwo;
|
||
LONG distancePointThree;
|
||
|
||
yTemp=((LONG)someSegment.yFirst()-(LONG)somePoint.y)*((LONG)someSegment.yFirst()-(LONG)somePoint.y);
|
||
xTemp=((LONG)someSegment.xFirst()-(LONG)somePoint.x)*((LONG)someSegment.xFirst()-(LONG)somePoint.x);
|
||
distancePointOne=::sqrt(yTemp+xTemp);
|
||
yTemp=((LONG)someSegment.ySecond()-(LONG)somePoint.y)*((LONG)someSegment.ySecond()-(LONG)somePoint.y);
|
||
xTemp=((LONG)someSegment.xSecond()-(LONG)somePoint.x)*((LONG)someSegment.xSecond()-(LONG)somePoint.x);
|
||
distancePointTwo=::sqrt(yTemp+xTemp);
|
||
midx=((LONG)someSegment.xFirst()+(LONG)someSegment.xSecond())/2;
|
||
midy=((LONG)someSegment.yFirst()+(LONG)someSegment.ySecond())/2;
|
||
yTemp=((LONG)midy-(LONG)somePoint.y)*((LONG)midy-(LONG)somePoint.y);
|
||
xTemp=((LONG)midx-(LONG)somePoint.x)*((LONG)midx-(LONG)somePoint.x);
|
||
distancePointThree=::sqrt(yTemp+xTemp);
|
||
if(distancePointThree<=distancePointTwo&&distancePointTwo<=distancePointOne)
|
||
return distancePointThree;
|
||
if(distancePointTwo<=distancePointThree&&distancePointThree<=distancePointOne)
|
||
return distancePointTwo;
|
||
return distancePointOne;
|
||
}
|
||
|
||
WORD GridMesh::saveMesh(String &pathFileName)
|
||
{
|
||
FILE *fp;
|
||
Point tempPoint;
|
||
size_t size((int)Vector<Segment>::size());
|
||
|
||
if(!size)return FALSE;
|
||
if(0==(fp=::fopen((LPSTR)pathFileName,"wb")))return FALSE;
|
||
::fwrite((void*)(LPSTR)mVersionInfo,::strlen(mVersionInfo),1,fp);
|
||
::fwrite((void*)&size,sizeof(size),1,fp);
|
||
::fwrite((void*)&mGridLines,sizeof(mGridLines),1,fp);
|
||
for(int i=0;i<size;i++)
|
||
{
|
||
tempPoint=Vector<Segment>::operator[](i).firstPoint();
|
||
::fwrite((void *)&tempPoint,sizeof(Point),1,fp);
|
||
tempPoint=Vector<Segment>::operator[](i).secondPoint();
|
||
::fwrite((void*)&tempPoint,sizeof(Point),1,fp);
|
||
}
|
||
::fclose(fp);
|
||
return TRUE;
|
||
}
|
||
|
||
WORD GridMesh::loadMesh(String &pathFileName)
|
||
{
|
||
FILE *fp;
|
||
Point firstPoint;
|
||
Point secondPoint;
|
||
String versionString;
|
||
int vectorIndex(0);
|
||
size_t size;
|
||
|
||
if(0==(fp=::fopen((LPSTR)pathFileName,"rb")))return upgradeStatus(FALSE);
|
||
versionString.reserve(String::MaxString);
|
||
::fread((void*)(LPSTR)versionString,::strlen(mVersionInfo),1,fp);
|
||
if(versionString!=mVersionInfo)
|
||
{
|
||
::fclose(fp);
|
||
return upgradeStatus(FALSE);
|
||
}
|
||
::fread((void*)&size,sizeof(size),1,fp);
|
||
::fread((void*)&mGridLines,sizeof(mGridLines),1,fp);
|
||
Vector<Segment>::size(size);
|
||
for(int i=0;i<size;i++)
|
||
{
|
||
::fread((void*)&firstPoint,sizeof(Point),1,fp);
|
||
::fread((void*)&secondPoint,sizeof(Point),1,fp);
|
||
Vector<Segment>::operator[](vectorIndex)=Segment(firstPoint,secondPoint,vectorIndex);
|
||
vectorIndex++;
|
||
}
|
||
::fclose(fp);
|
||
return upgradeStatus(TRUE);
|
||
}
|
||
|
||
WORD GridMesh::upgradeStatus(WORD retCode)const
|
||
{
|
||
if(!::IsWindowVisible(GetHandle()))Window::Show(SW_SHOW);
|
||
::InvalidateRect(mhParent,0,TRUE);
|
||
::InvalidateRect(GetHandle(),0,TRUE);
|
||
return retCode;
|
||
}
|
||
|
||
WORD GridMesh::retrieveMesh(Vector<Point> &sourcePoints,Vector<Point> &destPoints)
|
||
{
|
||
Vector<Segment> sourceSegments;
|
||
createMesh(mGridLines,sourceSegments);
|
||
retrieveMesh(sourcePoints,sourceSegments);
|
||
retrieveMesh(destPoints,(Vector<Segment>&)*this);
|
||
if(sourcePoints.size()!=destPoints.size())return FALSE;
|
||
return (WORD)sourcePoints.size();
|
||
}
|
||
|
||
WORD GridMesh::retrieveMesh(Vector<Point> &meshPoints,Vector<Segment> &someSegmentVector)const
|
||
{
|
||
Segment tempSegment;
|
||
int vectorIndex;
|
||
int pointIndex(0);
|
||
size_t vectorSize((int)someSegmentVector.size());
|
||
int haveFirstColumn(FALSE);
|
||
Vector<Point> dummyPoint;
|
||
|
||
meshPoints.size(0);
|
||
meshPoints.size((mGridLines+2)*(mGridLines+2));
|
||
for(vectorIndex=0;vectorIndex<vectorSize;vectorIndex+=2)
|
||
{
|
||
if(!(vectorIndex%(mGridLines+1)))
|
||
{
|
||
if(!vectorIndex&&!haveFirstColumn)meshPoints[pointIndex++]=Point(0,0);
|
||
else if(haveFirstColumn)
|
||
{
|
||
if(someSegmentVector[vectorIndex].firstPoint().yPoint()<
|
||
someSegmentVector[vectorIndex].secondPoint().yPoint())
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].firstPoint();
|
||
else
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].secondPoint();
|
||
}
|
||
}
|
||
else if(vectorIndex<=(mGridLines*2)&&!haveFirstColumn)
|
||
{
|
||
tempSegment=someSegmentVector[vectorIndex-1];
|
||
if(tempSegment.firstPoint()==someSegmentVector[vectorIndex].firstPoint()||
|
||
tempSegment.firstPoint()==someSegmentVector[vectorIndex].secondPoint())
|
||
meshPoints[pointIndex++]=tempSegment.secondPoint();
|
||
else
|
||
meshPoints[pointIndex++]=tempSegment.firstPoint();
|
||
if(vectorIndex==mGridLines*2)
|
||
{
|
||
if(someSegmentVector[vectorIndex].firstPoint().yPoint()<
|
||
someSegmentVector[vectorIndex].secondPoint().yPoint())
|
||
meshPoints[pointIndex++]=Point(0,someSegmentVector[vectorIndex].secondPoint().yPoint());
|
||
else
|
||
meshPoints[pointIndex++]=Point(0,someSegmentVector[vectorIndex].firstPoint().yPoint());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(!haveFirstColumn){haveFirstColumn=TRUE;vectorIndex=-2;continue;}
|
||
if(someSegmentVector[vectorIndex].firstPoint().yPoint()<
|
||
someSegmentVector[vectorIndex].secondPoint().yPoint())
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].firstPoint();
|
||
else
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].secondPoint();
|
||
if(!((vectorIndex+2)%(mGridLines+1)))
|
||
{
|
||
if(someSegmentVector[vectorIndex].firstPoint().yPoint()<
|
||
someSegmentVector[vectorIndex].secondPoint().yPoint())
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].secondPoint();
|
||
else
|
||
meshPoints[pointIndex++]=someSegmentVector[vectorIndex].firstPoint();
|
||
}
|
||
}
|
||
}
|
||
return (WORD)meshPoints.size();
|
||
}
|
||
|