Files
Work/mdiwin/MESH.BAK
2024-08-07 09:16:27 -04:00

455 lines
13 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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();
}