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

455 lines
13 KiB
C++
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)Window::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)
{
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)
{
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();
}