//--------------------------------------------------------------------------- #include #pragma hdrstop #include "MainForm.h" #include "ChildForm.h" #include "ToolWin.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" //--------------------------------------------------------------------------- complex one(1.,0.); complex zero(0.,0.); // Wythoff coefficients double wythoffChoices[11][3] = { {1,0,0}, // primal {.75,.25,0}, {.5,.5,0}, {.25,.75,0}, {.0,1,0}, {0,.75,.25}, {0,.5,.5}, {0,.25,.75}, {0,0,1}, // dual {.5,0,.5}, // runcinated {1,1,1}, // omnitruncated }; __fastcall TfrmChild::TfrmChild(TComponent* Owner) : TForm(Owner), mg(NULL), driverSelection(-1), currentWythoff(3) { if(ClientWidth > ClientHeight) ClientWidth = ClientHeight; if(ClientHeight > ClientWidth) ClientHeight = ClientWidth; currentIsometry = Isometry(one, zero, 1); setCurrentOperation(0); prevX = 0; prevY = 0; motionModel = DRAG_PURETRANSLATE_CLAMPED; mouseDownLeft = false; mouseDownRight = false; mouseDownMiddle = false; frmTools->SetChild(this); drawIt(); } //--------------------------------------------------------------------------- void TfrmChild::setDriver(int d){ if(d == driverSelection) return; if(d == 1){ //opengl //first make sure that other forms are using GDI... int i=Form1->MDIChildCount; for(int j=0; jMDIChildren[j] == this) continue; if(((TfrmChild*)Form1->MDIChildren[j])->driverSelection == 1) ((TfrmChild*)Form1->MDIChildren[j])->setDriver(0); } if(mg){ delete mg; mg = NULL; } mg = new MyGraphicsOGL(this->Handle, -1.0, 1.0, -1.0, 1.0); }else{ if(mg){ delete mg; mg = NULL; } mg = new MyGraphicsGDI(-1.0, 1.0, -1.0, 1.0); } int wid=this->ClientWidth, hgt=this->ClientHeight; double widRatio=1.0, hgtRatio=1.0; if(wid > hgt) if(hgt > 0.0) widRatio = double(wid)/hgt; if(hgt > wid) if(wid > 0.0) hgtRatio = double(hgt)/wid; mg->setDimensions(wid, hgt); mg->fitToWindow(-1.0*widRatio, 1.0*widRatio, -1.0*hgtRatio, 1.0*hgtRatio); driverSelection = d; } //--------------------------------------------------------------------------- void TfrmChild::setAntiAlias(bool yep){ antiAlias = yep; mg->setAntiAlias(antiAlias); } //--------------------------------------------------------------------------- void TfrmChild::setCurrentOperation(int op){ currentOperation = op; currentWythoff[0] = wythoffChoices[currentOperation][0]; currentWythoff[1] = wythoffChoices[currentOperation][1]; currentWythoff[2] = wythoffChoices[currentOperation][2]; } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormClose(TObject *Sender, TCloseAction &Action){ Form1->StatusBar1->Panels->Items[1]->Text = ""; frmTools->RemoveChild(this); if(mg){ delete mg; mg = NULL; } Action = caFree; } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormDestroy(TObject *Sender){ if(mg){ delete mg; mg = NULL; } } //--------------------------------------------------------------------------- void TfrmChild::resetOrientation(){ currentIsometry = Isometry(one, zero, 1); } //--------------------------------------------------------------------------- void TfrmChild::makeSnubUniform(){ Vector newWythoff(currentPickableSchwarzPolygon.SchwarzPolygon.length); if(findBaryCoordsThatMakeSnubUniform(newWythoff, currentPickableSchwarzPolygon.SchwarzPolygon)){ currentWythoff = newWythoff; //update wythoff coeffs in tool window currentOperation = -1; if(frmTools->cbTruncation->ItemIndex != currentOperation) frmTools->cbTruncation->ItemIndex = currentOperation; frmTools->txtWythoff0->Text = String(currentWythoff[0]); frmTools->txtWythoff1->Text = String(currentWythoff[1]); frmTools->txtWythoff2->Text = String(currentWythoff[2]); } else{ } } //--------------------------------------------------------------------------- void TfrmChild::changeCurrentWythoffSoCanonicalVertIsAt(complex p){ currentOperation = OMNITRUNCATED; Isometry isometryTakingPToSchwarzPolygon; int nFlips; if(currentPickableSchwarzPolygon.pick(p, isometryTakingPToSchwarzPolygon, nFlips)){ complex q; isometryTakingPToSchwarzPolygon.apply(p, q); unHBary2(currentWythoff, q, currentPickableSchwarzPolygon.SchwarzPolygon); } } //--------------------------------------------------------------------------- void TfrmChild::drawIt(){ mg->fillWindow(settings.backColor); mg->setLineThickness(lineThickness); Isometry smallestIsometry = currentIsometry; DrawOmnitruncatedTiling(mg, &settings, currentIsometry, schlafli_p, schlafli_q, currentWythoff, smallestIsometry, currentPickableSchwarzPolygon); currentIsometry = smallestIsometry; FormPaint(NULL); } //---------------------------------------------------------- void __fastcall TfrmChild::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ prevX = X; prevY = Y; double localScaleX = 1., localScaleY = 1.; int localTransX=0, localTransY=0; if(this->ClientWidth > this->ClientHeight){ localScaleX = double(this->ClientWidth) / double(this->ClientHeight); localTransX = (this->ClientWidth - this->ClientHeight)/2; } else{ localScaleY = double(this->ClientHeight) / double(this->ClientWidth); localTransY = (this->ClientHeight - this->ClientWidth)/2; } if(Button == mbLeft){ mouseDownLeft = true; }else if(Button == mbRight){ mouseDownRight = true; complex p((-1. + (double(prevX+localTransX)*localScaleX/(this->ClientWidth-1))*((1.)-(-1.))), (-1. + (1.-double(prevY+localTransY)*localScaleY/(this->ClientHeight-1))*((1.)-(-1.)))); if (settings.hyperbolicModel == KLEIN_DISK) k2p(p); changeCurrentWythoffSoCanonicalVertIsAt(p); }else if(Button == mbMiddle){ mouseDownMiddle = true; } frames = 0; ctime = GetTickCount(); } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ mouseDownLeft = false; mouseDownRight = false; mouseDownMiddle = false; Form1->StatusBar1->Panels->Items[0]->Text = ""; } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y){ double localScaleX = 1., localScaleY = 1.; int localTransX=0, localTransY=0; if(this->ClientWidth > this->ClientHeight){ localScaleX = double(this->ClientWidth) / double(this->ClientHeight); localTransX = (this->ClientWidth - this->ClientHeight)/2; } else{ localScaleY = double(this->ClientHeight) / double(this->ClientWidth); localTransY = (this->ClientHeight - this->ClientWidth)/2; } if(mouseDownRight){ complex p(LERP(-1.0,1.0,double(X-localTransX)*localScaleX/double(this->ClientWidth-1)), LERP(-1.0,1.0,1.0-double(Y-localTransY)*localScaleY/double(ClientHeight-1))); if (settings.hyperbolicModel == KLEIN_DISK) k2p(p); changeCurrentWythoffSoCanonicalVertIsAt(p); //update wythoff coeffs in tool window currentOperation = -1; if(frmTools->cbTruncation->ItemIndex != currentOperation) frmTools->cbTruncation->ItemIndex = currentOperation; frmTools->txtWythoff0->Text = String(currentWythoff[0]); frmTools->txtWythoff1->Text = String(currentWythoff[1]); frmTools->txtWythoff2->Text = String(currentWythoff[2]); drawIt(); } if(mouseDownLeft){ complex p(LERP(-1.0,1.0,double(X-localTransX)*localScaleX/(ClientWidth-1)), LERP(-1.0,1.0,1.0-double(Y-localTransY)*localScaleY/(ClientHeight-1))); complex pp(LERP(-1.0,1.0,double(prevX-localTransX)*localScaleX/(ClientWidth-1)), LERP(-1.0,1.0,1.0-double(prevY-localTransY)*localScaleY/(ClientHeight-1))); if (settings.hyperbolicModel == KLEIN_DISK){ k2p(p); k2p(pp); } Isometry increment; switch (motionModel){ case TRACKBALL: increment = Isometry(one, p-pp, 1); break; case DRAG_GEODESIC: //increment = (Isometry(one,pp,1) * Isometry(one, Isometry(one,-pp,1).apply(p), 1) * Isometry(one,-pp, 1)); break; case DRAG_NONPRECESSING: increment = Isometry(one,p,1) * Isometry(one, -pp, 1); break; case DRAG_PURETRANSLATE_CLAMPED: { double max = .9999; // strange, but it's ambiguous at 1 if (HYPOTSQRD(pp[0],pp[1]) > max*max){ double hyp = myhypot(pp[0],pp[1]); if(hyp == 0.) return; double scale = max / hyp; pp *= scale; } if (HYPOTSQRD(p[0],p[1]) > max*max){ double hyp = myhypot(pp[0],pp[1]); if(hyp == 0.) return; double scale = max / hyp; p *= scale; } } case DRAG_PURETRANSLATE: increment = Isometry::pureTranslation(pp, p); break; default: break; } currentIsometry = increment * currentIsometry; drawIt(); if(GetTickCount() - ctime >= 1000){ ctime = GetTickCount(); Form1->StatusBar1->Panels->Items[0]->Text = ("Frames per sec: " + String(frames)); Form1->StatusBar1->Repaint(); frames = 0; } } if(mouseDownMiddle){ double angle = X - prevX; angle /= 100.; Isometry increment = Isometry::pureRotation(angle); currentIsometry = increment * currentIsometry; drawIt(); } prevX = X; prevY = Y; } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormPaint(TObject *Sender){ mg->doPaint(this->Canvas->Handle); frames++; } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormActivate(TObject *Sender){ frmTools->AssignChild(this); } //--------------------------------------------------------------------------- void __fastcall TfrmChild::FormResize(TObject *Sender){ if(!mg) return; int wid=this->ClientWidth, hgt=this->ClientHeight; double widRatio=1.0, hgtRatio=1.0; if(wid > hgt) if(hgt > 0.0) widRatio = double(wid)/hgt; if(hgt > wid) if(wid > 0.0) hgtRatio = double(hgt)/wid; mg->setDimensions(wid, hgt); mg->fitToWindow(-1.0*widRatio, 1.0*widRatio, -1.0*hgtRatio, 1.0*hgtRatio); drawIt(); Form1->StatusBar1->Panels->Items[1]->Text = ("Picture Size: " + String(ClientWidth) + " x " + String(ClientHeight)); } //---------------------------------------------------------------------------