|
Up
Design
About
BOOL CSlideWnd::GenerateFractal(int nWidth, int nHeight, BOOL bFullScreen=FALSE) { // Tests every point in the current subset of // the complex plane, and colours it according // to it's escape behaviour // If bFullScreen is TRUE, we don't want to display the fractal // as it generates. Instead, we generate behind the scenes, // and display progress lights CFractopiaApp* pApp = (CFractopiaApp*)AfxGetApp(); CFractopiaDlg* pParent = (CFractopiaDlg*)GetParent(); // If the Formula dialog is active, // refresh its controls with current fractal data pParent->RefreshFormulaDialog(); // First, we're generating, so set the "generating" flag // We use this flag to ensure that only one fractal image is // generated at a time SetGenerating(TRUE); // Next, initialise the quit flag. This may be set to true later, // if the user decides to interrupt fractal generation, or if we // need to end the app cleanly. SetQuitFlag(FALSE); // Change to a "wait" cursor // Note: the CWaitCursor object will be deleted when it goes out of scope CWaitCursor wait; if (bFullScreen) // we're generating a full screen fractal image { // ask the user to wait pParent->WriteToStatusArea("please wait..."); } // Now we need a new fractal image bitmap if (!bFullScreen) { // delete the old thumbnail image... delete m_pDoc->m_pFractalImage; // and construct a new one m_pDoc->m_pFractalImage = new CDIBitmap(nWidth, nHeight, m_pDoc->m_hLogicalPalette); // Now clear the screen by painting the new (blank) bitmap // (we don't do this if we're generating a full screen image, // in which case we want to leave the old thumnail image // on screen while we generate) Invalidate(TRUE); // We are about to create a virgin, unsaved new fractal. // If it won't have been saved, we won't be in a position // to Preview it, so disable the CFractopiaDlg Preview button. // (and do this before the fractal is generated) pParent->m_btnPreview.EnableWindow(FALSE); // While we're at it, don't forget to update the iterations // spin control on the CFractopiaSSFormView. pParent->RefreshFormulaDialog(); } // Specify our starting co-ordinates // in the complex plane... double x = m_pDoc->m_pFractalData->Z_Origin().X(), yi = m_pDoc->m_pFractalData->Z_Origin().Y(); // ... and the distance between each point // in the plane, at the current zoom level double dGrainWidth = m_pDoc->m_pFractalData->Z_Width() / nWidth; double dGrainHeight = m_pDoc->m_pFractalData->Z_Height() / nHeight; // Colour all the (complex) points for (int nRow = 0; nRow < nHeight; nRow++) { for (int nCol = 0; nCol < nWidth; nCol++) { m_cpTestPoint.SetX(x); m_cpTestPoint.SetY(yi); // find the escape orbit for this point int nEscapeOrbit = m_pDoc->TestPoint(m_cpTestPoint); // map the escape orbit to a colour value switch (nEscapeOrbit) { case -1: m_nColourValue = 10; // lake colour break; default: m_nColourValue = (nEscapeOrbit % m_pDoc->m_nPaletteEntries) + 11; // other colours } // store colour value directly in the fractal image bitmap if (!bFullScreen) { m_pDoc->m_pFractalImage->PaintBit(nCol, nRow, m_nColourValue); } else { m_pDoc->m_pBigFractalImage->PaintBit(nCol, nRow, m_nColourValue); } x += dGrainWidth; // advance along x axis } // Interrupt app to process *any* messages in the queue. // This allows the "Rendering" dialog box to be freely moved, // minimised or closed. if (!PeekAndPump()) return FALSE; // If the user has interrupted fractal generation, or even // terminated the program mid generation, exit the loop if (m_bQuit) { // We aren't generating anymore. Reset the flag OutputDebugString("*** Quitting mid fractal generation ***\n"); SetGenerating(FALSE); return FALSE; } if (bFullScreen) { // if we're generating a full screen fractal image, // *don't* paint the line we just generated // - update the progress lights instead int nPercent = int(nRow / (float)nHeight * 16); //100); pParent->ShowBuildProgress(nPercent); } else { // Paint the line we just generated (immediately) CRect rOneLine(0, nRow, nWidth, nRow + 1); InvalidateRect(rOneLine, FALSE); UpdateWindow(); } // we (may) have lost the wait cursor, so restore it. wait.Restore(); x = m_pDoc->m_pFractalData->Z_Origin().X(); // return to leftmost x position yi -= dGrainHeight; // go down to next yi position } // The fractal image has been generated. Now tidy up. if (bFullScreen) { // if we're generating a full screen fractal image... // reset Regenerated flag which will have been set if // CFractopiaDlg::OnRegenerate() was previously invoked m_pDoc->SetRegeneratedFlag(FALSE); // Beep to let the user know we've finished calculating at last! // (on full screen render only) MessageBeep(MB_OK); // turn off all the progress lights, and take down status message pParent->ResetBuildProgress(); pParent->WriteToStatusArea(" "); } if (!bFullScreen) { // The "document" has been modified. Set the flag. m_pDoc->SetModifiedFlag(TRUE); // Save the new fractal to the undo list, // in case the user wants to UNDO later ((CFractopiaDlg*)GetParent())->SaveToUndoList(); } // We aren't generating anymore. Reset the flag SetGenerating(FALSE); // reenable previews pParent->m_btnPreview.EnableWindow(TRUE); // Note that the default + cursor is restored at the end of this // function, when "wait" (the CWaitCursor object), goes out of scope. return TRUE; }