Mandelbrot: Scrap the old app, initial workings of a new one.
Based upon a HTML5 fractal engine by @kerwizzy (relicensed as MIT and copyright assigned to Haiku, Inc. with permission from the author). Hacky and a mess, but it works, and has the potentiality to be much nicer than the previous Mandelbrot app. Already supports rendering & zooming in, but has hacks all over the place.
This commit is contained in:
parent
c8cfaef631
commit
86370d7b02
1817
src/apps/mandelbrot/Colorsets.h
Normal file
1817
src/apps/mandelbrot/Colorsets.h
Normal file
File diff suppressed because it is too large
Load Diff
372
src/apps/mandelbrot/FractalEngine.cpp
Normal file
372
src/apps/mandelbrot/FractalEngine.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright 2016, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Augustin Cavalier <waddlesplash>
|
||||
* kerwizzy
|
||||
*/
|
||||
#include "FractalEngine.h"
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Colorsets.h"
|
||||
#define colors Colorset_Royal
|
||||
|
||||
double zReal_end = 0;
|
||||
double zImaginary_end = 0;
|
||||
|
||||
double juliaC_a = 0;
|
||||
double juliaC_b = 1;
|
||||
|
||||
uint8 r = 0;
|
||||
uint8 g = 0;
|
||||
uint8 b = 0;
|
||||
|
||||
uint8 logChecked = 0;
|
||||
uint8 smoothChecked = 0;
|
||||
|
||||
uint8 gEscapeHorizon = 4; // set to 64 when doing smooth colors
|
||||
|
||||
int32 gIterations = 1024;
|
||||
|
||||
double gPower = 0;
|
||||
|
||||
void renderPixel_smooth(double real, double imaginary);
|
||||
void renderPixel_default(double real, double imaginary);
|
||||
int32 (*inSet)(double real, double imaginary);
|
||||
int32 inSet_mandelbrot(double real, double imaginary);
|
||||
int32 inSet_burningShip(double real, double imaginary);
|
||||
int32 inSet_tricornMandelbrot(double real, double imaginary);
|
||||
|
||||
void (*renderPixel)(double real, double imaginary);
|
||||
|
||||
void renderPixel_default(double real, double imaginary)
|
||||
{
|
||||
int32 iterToEscape = (*inSet)(real, imaginary);
|
||||
uint16 loc = 0;
|
||||
if (iterToEscape == -1) {
|
||||
// Didn't escape.
|
||||
loc = 999;
|
||||
} else {
|
||||
loc = 998 - (iterToEscape % 999);
|
||||
}
|
||||
|
||||
r = colors[loc * 3 + 0];
|
||||
g = colors[loc * 3 + 1];
|
||||
b = colors[loc * 3 + 2];
|
||||
}
|
||||
|
||||
void renderPixel_smooth(double real, double imaginary)
|
||||
{
|
||||
int32 outColor = (*inSet)(real, imaginary);
|
||||
int8 mapperDiff_r = 0;
|
||||
int8 mapperDiff_g = 0;
|
||||
int8 mapperDiff_b = 0;
|
||||
|
||||
int16 mapperLoc = 0;
|
||||
|
||||
double dist = sqrt(zReal_end * zReal_end + zImaginary_end * zImaginary_end);
|
||||
|
||||
double ratio = (1 - (log(log(dist))) / log(2));
|
||||
if (sqrt(real * real + imaginary * imaginary) > 8) {
|
||||
// Make the colors >8 be flat.
|
||||
ratio = -1.0821509904820257;
|
||||
outColor = 1;
|
||||
}
|
||||
|
||||
if (outColor == -1) {
|
||||
r = colors[999 * 3];
|
||||
g = colors[999 * 3 + 1];
|
||||
b = colors[999 * 3 + 2];
|
||||
return;
|
||||
}
|
||||
outColor = 998 - (outColor % 999);
|
||||
|
||||
mapperLoc = outColor * 3;
|
||||
|
||||
mapperDiff_r = colors[mapperLoc + 0] - colors[mapperLoc + 0 + 3];
|
||||
mapperDiff_g = colors[mapperLoc + 1] - colors[mapperLoc + 1 + 3];
|
||||
mapperDiff_b = colors[mapperLoc + 2] - colors[mapperLoc + 2 + 3];
|
||||
|
||||
r = mapperDiff_r * ratio + colors[mapperLoc + 0];
|
||||
g = mapperDiff_g * ratio + colors[mapperLoc + 1];
|
||||
b = mapperDiff_b * ratio + colors[mapperLoc + 2];
|
||||
}
|
||||
|
||||
int32 inSet_mandelbrot(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq + (-1 * (zImaginarySq)));
|
||||
|
||||
zImaginary = 2 * (zReal * zImaginary);
|
||||
zReal = nzReal;
|
||||
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
if ((zRealSq) + (zImaginarySq) >
|
||||
escapeHorizon) { // If it is outside the 2 unit circle...
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 inSet_burningShip(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
// It looks "upside down" otherwise.
|
||||
imaginary = -imaginary;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
zReal = fabs(zReal);
|
||||
zImaginary = fabs(zImaginary);
|
||||
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq + (-1 * (zImaginarySq)));
|
||||
|
||||
zImaginary = 2 * (zReal * zImaginary);
|
||||
zReal = nzReal;
|
||||
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
// If it is outside the 2 unit circle...
|
||||
if ((zRealSq) + (zImaginarySq) > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 inSet_tricornMandelbrot(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
real = -real;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
double znRe = zImaginary * -1;
|
||||
zImaginary = zReal * -1;
|
||||
zReal = znRe; // Swap the real and complex parts each time.
|
||||
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq + (-1 * (zImaginarySq)));
|
||||
|
||||
zImaginary = 2 * (zReal * zImaginary);
|
||||
zReal = nzReal;
|
||||
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
// If it is outside the 2 unit circle...
|
||||
if ((zRealSq) + (zImaginarySq) > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 inSet_julia(double real, double imaginary)
|
||||
{
|
||||
double zReal = real;
|
||||
double zImaginary = imaginary;
|
||||
|
||||
double muRe = juliaC_a;
|
||||
double muIm = juliaC_b;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq + (-1 * (zImaginarySq)));
|
||||
|
||||
zImaginary = 2 * (zReal * zImaginary);
|
||||
zReal = nzReal;
|
||||
|
||||
zReal += muRe;
|
||||
zImaginary += muIm;
|
||||
|
||||
// If it is outside the 2 unit circle...
|
||||
if ((zRealSq) + (zImaginarySq) > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 inSet_mandelbrot_orbitTrap(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
double closest = 10000000;
|
||||
double distance = 0;
|
||||
double lineDist = 0;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq + (-1 * (zImaginarySq)));
|
||||
|
||||
zImaginary = 2 * (zReal * zImaginary);
|
||||
zReal = nzReal;
|
||||
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
distance = sqrt((zRealSq) + (zImaginarySq));
|
||||
lineDist = fabs((zReal) + (zImaginary));
|
||||
|
||||
// If it is closer than ever before...
|
||||
if (lineDist < closest)
|
||||
closest = lineDist;
|
||||
|
||||
if (distance > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
return floor(4 * log(4 / closest));
|
||||
}
|
||||
}
|
||||
return floor(4 * log(4 / closest));
|
||||
}
|
||||
|
||||
int32 inSet_multibrot_3(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
double zRealSq = zReal * zReal;
|
||||
double zImaginarySq = zImaginary * zImaginary;
|
||||
double nzReal = (zRealSq * zReal - 3 * zReal * (zImaginarySq));
|
||||
|
||||
zImaginary = 3 * ((zRealSq)*zImaginary) - (zImaginarySq * zImaginary);
|
||||
|
||||
zReal = nzReal;
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
// If it is outside the 2 unit circle...
|
||||
if ((zRealSq) + (zImaginarySq) > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 inSet_fractional(double real, double imaginary)
|
||||
{
|
||||
double zReal = 0;
|
||||
double zImaginary = 0;
|
||||
|
||||
double r = 0;
|
||||
double t = 0;
|
||||
|
||||
double power = gPower;
|
||||
|
||||
int32 iterations = gIterations;
|
||||
uint8 escapeHorizon = gEscapeHorizon;
|
||||
|
||||
int32 i = 0;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
r = sqrt(zReal * zReal + zImaginary * zImaginary);
|
||||
r = pow(r, power);
|
||||
t = atan2(zImaginary, zReal) * power;
|
||||
|
||||
double nzReal = r * cos(t);
|
||||
zImaginary = r * sin(t);
|
||||
|
||||
zReal = nzReal;
|
||||
zReal += real;
|
||||
zImaginary += imaginary;
|
||||
|
||||
// If it is outside the 2 unit circle...
|
||||
if ((zReal * zReal) + (zImaginary * zImaginary) > escapeHorizon) {
|
||||
zReal_end = zReal;
|
||||
zImaginary_end = zImaginary;
|
||||
|
||||
return i; // stop it from running longer
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define buf_SetPixel(x, y, r, g, b) \
|
||||
buf[width * y * 3 + x * 3 + 0] = r; \
|
||||
buf[width * y * 3 + x * 3 + 1] = g; \
|
||||
buf[width * y * 3 + x * 3 + 2] = b;
|
||||
BBitmap* FractalEngine(uint32 width, uint32 height, double locationX,
|
||||
double locationY, double size)
|
||||
{
|
||||
uint16 halfcWidth = width / 2;
|
||||
uint16 halfcHeight = height / 2;
|
||||
|
||||
uint32 bufLen = width * height * 3;
|
||||
uint8* buf = new uint8[bufLen];
|
||||
|
||||
renderPixel = renderPixel_default;
|
||||
inSet = inSet_mandelbrot;
|
||||
|
||||
for (uint32 x = 0; x < width; x++) {
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
(*renderPixel)((x * size + locationX) - (halfcWidth * size),
|
||||
(y * -size + locationY) - (halfcHeight * -size));
|
||||
buf_SetPixel(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
BBitmap* ret = new BBitmap(BRect(0, 0, width - 1 , height - 1), 0, B_RGB24);
|
||||
ret->ImportBits(buf, bufLen, width * 3, 0, B_RGB24_BIG);
|
||||
return ret;
|
||||
}
|
20
src/apps/mandelbrot/FractalEngine.h
Normal file
20
src/apps/mandelbrot/FractalEngine.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2016, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Augustin Cavalier <waddlesplash>
|
||||
* kerwizzy
|
||||
*/
|
||||
#ifndef FRACTALENGINE_H
|
||||
#define FRACTALENGINE_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Bitmap.h>
|
||||
|
||||
|
||||
BBitmap* FractalEngine(uint32 width, uint32 height, double locationX,
|
||||
double locationY, double size);
|
||||
|
||||
|
||||
#endif /* FRACTALENGINE_H */
|
@ -1,11 +1,12 @@
|
||||
SubDir HAIKU_TOP src apps mandelbrot ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
AddSubDirSupportedPlatforms libbe_test ;
|
||||
|
||||
SubDirC++Flags -Wno-error ;
|
||||
|
||||
Application Mandelbrot :
|
||||
Mandelbrot.cpp
|
||||
tsb.cpp
|
||||
FractalEngine.cpp
|
||||
: be [ TargetLibsupc++ ] localestub
|
||||
: Mandelbrot.rdef
|
||||
;
|
||||
|
@ -1,31 +0,0 @@
|
||||
----------------------
|
||||
Be Sample Code License
|
||||
----------------------
|
||||
|
||||
Copyright 1991-1999, Be Incorporated.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions, and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,215 +1,185 @@
|
||||
/*
|
||||
Copyright 1993-1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 2016, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Augustin Cavalier <waddlesplash>
|
||||
*/
|
||||
|
||||
#include "tsb.h"
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Catalog.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <OS.h>
|
||||
#include <Roster.h>
|
||||
#include <ScrollView.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "FractalEngine.h"
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "Mandelbrot"
|
||||
#define B_TRANSLATION_CONTEXT "MandelbrotWindow"
|
||||
|
||||
|
||||
/* Those are the menu item id's of the main window */
|
||||
#define P1 0x60
|
||||
#define P2 0x61
|
||||
#define P3 0x62
|
||||
#define P4 0x63
|
||||
// #pragma mark - FractalView
|
||||
|
||||
class TMainWindow : public BWindow {
|
||||
public:
|
||||
TMainWindow(BRect bound, const char* name, window_type type,
|
||||
long flags);
|
||||
virtual ~TMainWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual bool QuitRequested();
|
||||
class FractalView : public BView {
|
||||
public:
|
||||
FractalView();
|
||||
~FractalView();
|
||||
|
||||
void UpdateScrollBars();
|
||||
virtual void AttachedToWindow();
|
||||
virtual void FrameResized(float, float)
|
||||
{ RedrawFractal(); }
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
private:
|
||||
TShowBit* fView;
|
||||
private:
|
||||
BBitmap* fBitmap;
|
||||
double fLocationX;
|
||||
double fLocationY;
|
||||
double fSize;
|
||||
|
||||
void RedrawFractal();
|
||||
};
|
||||
|
||||
|
||||
TMainWindow::TMainWindow(BRect bound, const char* name, window_type type,
|
||||
long flags)
|
||||
: BWindow(bound, name, type, flags)
|
||||
FractalView::FractalView()
|
||||
:
|
||||
BView(NULL, B_WILL_DRAW),
|
||||
fBitmap(NULL),
|
||||
fLocationX(0),
|
||||
fLocationY(0),
|
||||
fSize(0.005)
|
||||
{
|
||||
BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 1000, 15), "MB");
|
||||
BMenuItem* item;
|
||||
BMenu* menu;
|
||||
|
||||
menu = new BMenu(B_TRANSLATE("File"));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
|
||||
new BMessage(B_QUIT_REQUESTED), 'Q'));
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
menu = new BMenu(B_TRANSLATE("Palette"));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Palette 1"), new BMessage(P1)));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Palette 2"), new BMessage(P2)));
|
||||
menu->AddItem(item = new BMenuItem(B_TRANSLATE("Palette 3"),
|
||||
new BMessage(P3)));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Palette 4"), new BMessage(P4)));
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
item->SetMarked(true);
|
||||
menu->SetRadioMode(true);
|
||||
|
||||
menu = new BMenu(B_TRANSLATE("Iterations"));
|
||||
menu->AddItem(new BMenuItem("128", new BMessage(128)));
|
||||
menu->AddItem(item = new BMenuItem("256", new BMessage(256)));
|
||||
menu->AddItem(new BMenuItem("384", new BMessage(384)));
|
||||
menu->AddItem(new BMenuItem("512", new BMessage(512)));
|
||||
menu->AddItem(new BMenuItem("768", new BMessage(768)));
|
||||
menu->AddItem(new BMenuItem("1024", new BMessage(1024)));
|
||||
menu->AddItem(new BMenuItem("2048", new BMessage(2048)));
|
||||
menu->AddItem(new BMenuItem("4096", new BMessage(4096)));
|
||||
menu->AddItem(new BMenuItem("8192", new BMessage(8192)));
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
item->SetMarked(true);
|
||||
menu->SetRadioMode(true);
|
||||
|
||||
AddChild(menuBar);
|
||||
float barHeight = menuBar->Bounds().Height();
|
||||
|
||||
fView = new TShowBit(BRect(0, barHeight + 1, 188 - B_V_SCROLL_BAR_WIDTH,
|
||||
188 - B_H_SCROLL_BAR_HEIGHT), B_FOLLOW_ALL, B_WILL_DRAW);
|
||||
BScrollView *scrollView = new BScrollView("scroll view", fView,
|
||||
B_FOLLOW_ALL, B_WILL_DRAW, true, true, B_NO_BORDER);
|
||||
AddChild(scrollView);
|
||||
|
||||
SetSizeLimits(80, size_x + 13, 80 + 20, size_y + barHeight + 1 + 13);
|
||||
ResizeTo(size_x + 13, size_y + barHeight + 1 + 13);
|
||||
SetPulseRate(150000);
|
||||
UpdateScrollBars();
|
||||
}
|
||||
|
||||
|
||||
TMainWindow::~TMainWindow()
|
||||
FractalView::~FractalView()
|
||||
{
|
||||
delete fBitmap;
|
||||
}
|
||||
|
||||
|
||||
void FractalView::AttachedToWindow()
|
||||
{
|
||||
//RedrawFractal();
|
||||
}
|
||||
|
||||
|
||||
void FractalView::MouseDown(BPoint where)
|
||||
{
|
||||
BRect frame = Frame();
|
||||
fLocationX = ((where.x - frame.Width() / 2) * fSize + fLocationX);
|
||||
fLocationY = ((where.y - frame.Height() / 2) * -fSize + fLocationY);
|
||||
fSize /= 2;
|
||||
RedrawFractal();
|
||||
}
|
||||
|
||||
|
||||
void FractalView::RedrawFractal()
|
||||
{
|
||||
delete fBitmap;
|
||||
fBitmap = FractalEngine(Frame().Width(), Frame().Height(), fLocationX,
|
||||
fLocationY, fSize);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void FractalView::Draw(BRect updateRect)
|
||||
{
|
||||
DrawBitmap(fBitmap, updateRect, updateRect);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - MandelbrotWindow
|
||||
|
||||
|
||||
class MandelbrotWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
|
||||
MandelbrotWindow(BRect frame);
|
||||
~MandelbrotWindow() {}
|
||||
|
||||
virtual void MessageReceived(BMessage* msg);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
FractalView* fFractalView;
|
||||
};
|
||||
|
||||
|
||||
MandelbrotWindow::MandelbrotWindow(BRect frame)
|
||||
:
|
||||
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("Mandelbrot"), B_TITLED_WINDOW_LOOK,
|
||||
B_NORMAL_WINDOW_FEEL, 0L),
|
||||
fFractalView(new FractalView)
|
||||
{
|
||||
BMenuBar* menuBar = new BMenuBar("MenuBar");
|
||||
BLayoutBuilder::Menu<>(menuBar)
|
||||
.AddMenu(B_TRANSLATE("File"))
|
||||
.AddItem(B_TRANSLATE("Quit"), B_QUIT_REQUESTED, 'Q')
|
||||
.End()
|
||||
.End();
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||
.SetInsets(0)
|
||||
.Add(menuBar)
|
||||
.Add(fFractalView)
|
||||
.End();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TMainWindow::UpdateScrollBars()
|
||||
MandelbrotWindow::MessageReceived(BMessage* msg)
|
||||
{
|
||||
BScrollView* scrollview;
|
||||
BScrollBar* scrollbar;
|
||||
BRect visible_extent;
|
||||
BRect total_extent;
|
||||
BRect bound;
|
||||
BRect my_bounds;
|
||||
long max;
|
||||
|
||||
Lock();
|
||||
if ((scrollview = (BScrollView*)FindView("scroll view"))) {
|
||||
bound.Set(0, 0, size_x, size_y);
|
||||
my_bounds = Bounds();
|
||||
|
||||
visible_extent = bound & my_bounds;
|
||||
total_extent = bound | my_bounds;
|
||||
|
||||
scrollbar = scrollview->ScrollBar(B_HORIZONTAL);
|
||||
max = (long) (bound.Width() - my_bounds.Width());
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
scrollbar->SetRange(0, max);
|
||||
scrollbar->SetProportion(visible_extent.Width() / total_extent.Width());
|
||||
|
||||
scrollbar = scrollview->ScrollBar(B_VERTICAL);
|
||||
max = (long) (bound.Height() - my_bounds.Height());
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
scrollbar->SetRange(0, max);
|
||||
scrollbar->SetProportion(visible_extent.Height() / total_extent.Height());
|
||||
switch (msg->what) {
|
||||
default:
|
||||
BWindow::MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TMainWindow::FrameResized(float, float)
|
||||
{
|
||||
UpdateScrollBars();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TMainWindow::QuitRequested()
|
||||
MandelbrotWindow::QuitRequested()
|
||||
{
|
||||
if (fView->busy) {
|
||||
fView->exit_now = true;
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return false;
|
||||
if (BWindow::QuitRequested()) {
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - MandelbrotApp
|
||||
|
||||
|
||||
class MandelbrotApp : public BApplication
|
||||
{
|
||||
public:
|
||||
MandelbrotApp()
|
||||
: BApplication("application/x-vnd.Haiku-Mandelbrot") {}
|
||||
|
||||
void ReadyToRun();
|
||||
bool QuitRequested() { return true; }
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
TMainWindow::MessageReceived(BMessage* message)
|
||||
MandelbrotApp::ReadyToRun()
|
||||
{
|
||||
switch (message->what) {
|
||||
case P1:
|
||||
case P2:
|
||||
case P3:
|
||||
case P4:
|
||||
fView->set_palette(message->what - P1);
|
||||
break;
|
||||
|
||||
case 128:
|
||||
case 256:
|
||||
case 384:
|
||||
case 512:
|
||||
case 768:
|
||||
case 1024:
|
||||
case 2048:
|
||||
case 4096:
|
||||
case 8192:
|
||||
fView->set_iter(message->what);
|
||||
break;
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
MandelbrotWindow* wind = new MandelbrotWindow(BRect(0, 0, 640, 480));
|
||||
wind->CenterOnScreen();
|
||||
wind->Show();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
main(int, char**)
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
BApplication* app = new BApplication("application/x-vnd.Haiku-Mandelbrot");
|
||||
|
||||
BWindow* window = new TMainWindow(BRect(100, 100, 288, 288),
|
||||
B_TRANSLATE_SYSTEM_NAME("Mandelbrot"), B_DOCUMENT_WINDOW,
|
||||
B_WILL_ACCEPT_FIRST_CLICK);
|
||||
window->Show();
|
||||
|
||||
app->Run();
|
||||
delete app;
|
||||
MandelbrotApp().Run();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
resource app_signature "application/x-vnd.Haiku-Mandelbrot";
|
||||
|
||||
resource app_name_catalog_entry "x-vnd.Haiku-Mandelbrot:System name:Mandelbrot";
|
||||
|
||||
resource app_flags B_MULTIPLE_LAUNCH;
|
||||
|
||||
resource app_version {
|
||||
major = 1,
|
||||
middle = 0,
|
||||
minor = 0,
|
||||
variety = B_APPV_DEVELOPMENT,
|
||||
internal = 0,
|
||||
short_info = "Mandelbrot",
|
||||
long_info = "Mandelbrot"
|
||||
};
|
||||
|
||||
resource vector_icon {
|
||||
$"6E6369660C04006B0500020006023B4FDF3A26DEBE07943F1FB649C6A13E02F4"
|
||||
@ -23,10 +38,3 @@ resource vector_icon {
|
||||
$"000A030107000A040108000A050109000A0701041001178100040A010104000A"
|
||||
$"09010A000A09010C000A0A010D000A0A010B00"
|
||||
};
|
||||
|
||||
resource app_signature "application/x-vnd.Haiku-Mandelbrot";
|
||||
|
||||
resource app_name_catalog_entry "x-vnd.Haiku-Mandelbrot:System name:Mandelbrot";
|
||||
|
||||
resource app_flags B_MULTIPLE_LAUNCH;
|
||||
|
||||
|
@ -1,609 +0,0 @@
|
||||
//******************************************************************************
|
||||
//
|
||||
// File: tsb.cpp
|
||||
//
|
||||
//******************************************************************************
|
||||
|
||||
/*
|
||||
Copyright 1993-1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include <Debug.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <OS.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include "tsb.h"
|
||||
|
||||
#ifndef _INTERFACE_DEFS_H
|
||||
#include <InterfaceDefs.h>
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static TShowBit *tsbb;
|
||||
static long niter = 256;
|
||||
static uchar palette[256];
|
||||
|
||||
|
||||
void TShowBit::MouseDown(BPoint where)
|
||||
{
|
||||
if (!this->Window()->IsActive()) {
|
||||
this->Window()->Activate(TRUE);
|
||||
this->Window()->UpdateIfNeeded();
|
||||
}
|
||||
|
||||
if (busy)
|
||||
return;
|
||||
|
||||
if ((modifiers() & B_SHIFT_KEY) == 0) {
|
||||
change_selection(where.x, where.y);
|
||||
if ((selection.bottom - selection.top) < 4)
|
||||
return;
|
||||
}
|
||||
redraw_mand();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TShowBit::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch(message->what) {
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
//float factor = 1;
|
||||
float change = message->FindFloat("be:wheel_delta_y");
|
||||
BPoint where;
|
||||
GetMouse(&where, 0, 0);
|
||||
|
||||
selection = Bounds();
|
||||
|
||||
if (change < 0) {
|
||||
// zoom in
|
||||
selection.top = (where.y + selection.top) / 2;
|
||||
selection.bottom = (where.y + selection.bottom) / 2;
|
||||
selection.left = (where.x + selection.left) / 2;
|
||||
selection.right = (where.x + selection.right) / 2;
|
||||
} else {
|
||||
// zoom out
|
||||
selection.top = - where.y + selection.top * 2;
|
||||
selection.bottom = - where.y + selection.bottom * 2;
|
||||
selection.left = - where.x + selection.left * 2;
|
||||
selection.right = - where.x + selection.right * 2;
|
||||
}
|
||||
redraw_mand();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TShowBit::redraw_mand()
|
||||
{
|
||||
double px0;
|
||||
double py0;
|
||||
double scale0;
|
||||
|
||||
if (modifiers() & B_SHIFT_KEY) {
|
||||
px -= (scale / 2.0);
|
||||
py -= (scale / 2.0);
|
||||
scale *= 2.0;
|
||||
} else {
|
||||
px0 = px + (scale * (selection.left / (1.0*size_x)));
|
||||
py0 = py + (scale * (selection.top / (1.0*size_x)));
|
||||
scale0 = scale * ((selection.bottom-selection.top) / (1.0*size_x));
|
||||
|
||||
px = px0; py = py0; scale = scale0;
|
||||
}
|
||||
selection.Set(-1000, -1000, -1000, -1000);
|
||||
mand(px, py, scale, scale);
|
||||
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::set_iter(long it)
|
||||
{
|
||||
if (it != iter) {
|
||||
iter = it;
|
||||
niter = it;
|
||||
selection.Set(-1000, -1000, -1000, -1000);
|
||||
mand(px, py, scale, scale);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::set_palette(long code)
|
||||
{
|
||||
rgb_color c = {0, 0, 0, 255};
|
||||
long i;
|
||||
|
||||
BScreen screen( Window() );
|
||||
|
||||
if (code == 0) {
|
||||
for (i = 0; i < 256; i++)
|
||||
palette[i] = (i >> 1) & 0x1f;
|
||||
}
|
||||
if (code == 1) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c.red = i * 4;
|
||||
c.green = i * 7;
|
||||
c.blue = 256-(i - i * 5);
|
||||
palette[i] = screen.IndexForColor(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (code == 2) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c.red = (i * 7);
|
||||
c.green = i/2;
|
||||
c.blue = 256-(i * 3);
|
||||
palette[i] = screen.IndexForColor(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (code == 3) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c.red = 256-(i * 6);
|
||||
c.green = (i * 7);
|
||||
c.blue = 0;
|
||||
palette[i] = screen.IndexForColor(c);
|
||||
}
|
||||
}
|
||||
mand(px, py, scale, scale);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
TShowBit::TShowBit(BRect r, uint32 resizeMask, uint32 flags) :
|
||||
BView(r, "", resizeMask, flags | B_WILL_DRAW | B_PULSE_NEEDED)
|
||||
{
|
||||
BRect bitmap_r;
|
||||
char *bits;
|
||||
|
||||
busy = FALSE;
|
||||
exit_now = FALSE;
|
||||
tsbb = this;
|
||||
bitmap_r.Set(0, 0, size_x - 1, size_y - 1);
|
||||
selection.Set(-1000, -1000, -1000, -1000);
|
||||
iter = 256;
|
||||
|
||||
the_bitmap = new BBitmap(bitmap_r, B_COLOR_8_BIT);
|
||||
bits = (char *)the_bitmap->Bits();
|
||||
memset(bits, 0x00, size_x*size_y);
|
||||
px = -2.5;
|
||||
py = -2.0;
|
||||
scale = 4.0;
|
||||
set_palette(2);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
TShowBit::~TShowBit()
|
||||
{
|
||||
delete the_bitmap;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::Draw(BRect update_rect)
|
||||
{
|
||||
DrawBitmap(the_bitmap, BPoint(0, 0));
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
|
||||
int iterate_double(double a, double b)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double xsq;
|
||||
double ysq;
|
||||
int i = 0, iter = niter;
|
||||
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
|
||||
while (i < iter) {
|
||||
xsq = x * x;
|
||||
ysq = y * y;
|
||||
y = (2.0 * x * y) + b;
|
||||
i++;
|
||||
x = a + (xsq - ysq);
|
||||
|
||||
if ((xsq + ysq) > 4.0)
|
||||
return(i);
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
//extern "C" int iterate(float a, float b);
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
int iterate_float(float a, float b)
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float xsq;
|
||||
float ysq;
|
||||
long i;
|
||||
int iter = niter;
|
||||
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
i = 0;
|
||||
|
||||
while (i < iter) {
|
||||
xsq = x * x;
|
||||
ysq = y * y;
|
||||
y = (2.0f * x * y) + b;
|
||||
i++;
|
||||
x = a + (xsq - ysq);
|
||||
|
||||
if ((xsq + ysq) > 4.0f)
|
||||
return(i);
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
double vvx;
|
||||
double vvy;
|
||||
double ssx;
|
||||
char t1_done;
|
||||
char t2_done;
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
int32 __calc1(void *arg)
|
||||
{
|
||||
tsbb->manda(vvx, vvy, ssx, ssx);
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
int32 __calc2(void *arg)
|
||||
{
|
||||
tsbb->mandb(vvx, vvy, ssx, ssx);
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
uchar tmp[256];
|
||||
uchar pc[32][32];
|
||||
uchar tmp1[256];
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::mand(double vx, double vy, double sx, double sy)
|
||||
{
|
||||
vvx = vx; vvy = vy; ssx = sx;
|
||||
t1_done = 0; t2_done = 0;
|
||||
|
||||
precompute(vx, vy, sx, sy);
|
||||
|
||||
resume_thread(spawn_thread(__calc1, "calc1", B_NORMAL_PRIORITY, NULL));
|
||||
resume_thread(spawn_thread(__calc2, "calc2", B_NORMAL_PRIORITY, NULL));
|
||||
busy = TRUE;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::Pulse()
|
||||
{
|
||||
// PRINT(("pulsing (%d)\n", busy));
|
||||
if (busy) {
|
||||
Draw(BRect(0,0,0,0));
|
||||
if (t1_done && t2_done) {
|
||||
busy = FALSE;
|
||||
exit_now = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::precompute(double vx, double vy, double sx, double sy)
|
||||
{
|
||||
long x, y;
|
||||
double cx, cy;
|
||||
double scale = sx;
|
||||
|
||||
sx = sx / (32.0);
|
||||
sy = sy / (32.0);
|
||||
cy = vy;
|
||||
|
||||
for (y = 0; y < 32; y++) {
|
||||
cy += sy;
|
||||
cx = vx;
|
||||
if (scale < 0.000025 || niter != 256) {
|
||||
for (x = 0; x < 32; x++) {
|
||||
cx += sx;
|
||||
pc[x][y] = iterate_double(cx, cy);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (x = 0; x < 32; x++) {
|
||||
cx += sx;
|
||||
pc[x][y] = iterate_float(cx, cy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::mandb(double vx, double vy, double sx, double sy)
|
||||
{
|
||||
long x, y;
|
||||
long bx;
|
||||
double cx, cy;
|
||||
int v;
|
||||
uchar *bits = (uchar *)the_bitmap->Bits();
|
||||
uchar *b0;
|
||||
long y12;
|
||||
long x12;
|
||||
double scale = sx;
|
||||
|
||||
sx = sx / (size_x * 1.0);
|
||||
sy = sy / (size_y * 1.0);
|
||||
cy = vy;
|
||||
|
||||
cy += sy;
|
||||
sy *= 2.0;
|
||||
for (y = 1; y < size_y; y+=2) {
|
||||
y12 = y / 12;
|
||||
cy += sy;
|
||||
cx = vx;
|
||||
b0 = bits + (y * size_x);
|
||||
for (bx = 0; bx < size_x; bx += 12) {
|
||||
x12 = (bx+6) / 12;
|
||||
v = pc[x12][y12];
|
||||
|
||||
if (exit_now)
|
||||
goto done;
|
||||
|
||||
if (v == pc[x12+1][y12] &&
|
||||
v == pc[x12][y12+1] &&
|
||||
v == pc[x12-1][y12] &&
|
||||
v == pc[x12][y12-1] &&
|
||||
v == pc[x12-2][y12]) {
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (scale < 0.000025 || niter != 256) {
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
v = iterate_double(cx, cy);
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
else
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
v = iterate_float(cx, cy);
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
t2_done = 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::manda(double vx, double vy, double sx, double sy)
|
||||
{
|
||||
long x, y;
|
||||
long bx;
|
||||
double cx, cy;
|
||||
int v;
|
||||
uchar *bits = (uchar *)the_bitmap->Bits();
|
||||
uchar *b0;
|
||||
long y12;
|
||||
long x12;
|
||||
double scale = sx;
|
||||
|
||||
sx = sx / (size_x * 1.0);
|
||||
sy = sy / (size_y * 1.0);
|
||||
cy = vy;
|
||||
|
||||
sy *= 2.0;
|
||||
for (y = 0; y < size_y; y+=2) {
|
||||
y12 = y / 12;
|
||||
cy += sy;
|
||||
cx = vx;
|
||||
b0 = bits + (y * size_x);
|
||||
for (bx = 0; bx < size_x; bx += 12) {
|
||||
x12 = (bx+6) / 12;
|
||||
v = pc[x12][y12];
|
||||
|
||||
if (exit_now)
|
||||
goto done;
|
||||
|
||||
if (v == pc[x12+1][y12] &&
|
||||
v == pc[x12][y12+1] &&
|
||||
v == pc[x12-1][y12] &&
|
||||
v == pc[x12][y12-1] &&
|
||||
v == pc[x12-2][y12]) {
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (scale < 0.000025 || niter != 256) {
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
v = iterate_double(cx, cy);
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
else
|
||||
for (x = bx; x < (bx+12); x++) {
|
||||
cx += sx;
|
||||
v = iterate_float(cx, cy);
|
||||
*b0++ = palette[v & 0xff];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
t1_done = 1;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
long TShowBit::limit_v(long v)
|
||||
{
|
||||
if (v > (size_y - 1))
|
||||
v = (size_y - 1);
|
||||
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
return(v);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
long TShowBit::limit_h(long v)
|
||||
{
|
||||
if (v > (size_x - 1))
|
||||
v = size_x - 1;
|
||||
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
return(v);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
BRect TShowBit::sort_rect(BRect *aRect)
|
||||
{
|
||||
BRect tmp_rect;
|
||||
long tmp;
|
||||
|
||||
tmp_rect = *aRect;
|
||||
if (tmp_rect.bottom < tmp_rect.top) {
|
||||
tmp = (long)tmp_rect.top;
|
||||
tmp_rect.top = tmp_rect.bottom;
|
||||
tmp_rect.bottom = tmp;
|
||||
}
|
||||
|
||||
if (tmp_rect.left > tmp_rect.right) {
|
||||
tmp = (long) tmp_rect.right;
|
||||
tmp_rect.right = tmp_rect.left;
|
||||
tmp_rect.left = tmp;
|
||||
}
|
||||
|
||||
tmp_rect.top = limit_v(tmp_rect.top);
|
||||
tmp_rect.left = limit_h(tmp_rect.left);
|
||||
tmp_rect.bottom = limit_v(tmp_rect.bottom);
|
||||
tmp_rect.right = limit_h(tmp_rect.right);
|
||||
|
||||
return(tmp_rect);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void TShowBit::clip(long *h, long *v)
|
||||
{
|
||||
if (*h > (size_x - 1))
|
||||
*h = (size_x - 1);
|
||||
if (*h < 0)
|
||||
*h = 0;
|
||||
if (*v > (size_y - 1))
|
||||
*v = size_y - 1;
|
||||
if (*v < 0)
|
||||
*v = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
char TShowBit::has_selection()
|
||||
{
|
||||
if (((selection.bottom - selection.top) + (selection.right - selection.left)) < 5)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void TShowBit::change_selection(long h, long v)
|
||||
{
|
||||
uint32 buttons;
|
||||
long h0;
|
||||
long v0;
|
||||
BRect new_select;
|
||||
BRect old_select;
|
||||
BRect tmp_rect;
|
||||
long max;
|
||||
long width, height;
|
||||
|
||||
clip(&h, &v);
|
||||
new_select.top = v;
|
||||
new_select.left = h;
|
||||
old_select = selection;
|
||||
|
||||
SetDrawingMode(B_OP_INVERT);
|
||||
|
||||
do {
|
||||
BPoint where;
|
||||
GetMouse(&where, &buttons);
|
||||
h0 = (long) where.x;
|
||||
v0 = (long) where.y;
|
||||
width = h0 - h;
|
||||
height = v0 - v;
|
||||
|
||||
max = std::max(std::abs(height), std::abs(width));
|
||||
|
||||
v0 = (v0 > v) ? (v + max) : (v - max);
|
||||
h0 = (h0 > h) ? (h + max) : (h - max);
|
||||
|
||||
clip(&h0, &v0);
|
||||
new_select.right = h0;
|
||||
new_select.bottom = v0;
|
||||
|
||||
if ((old_select.top != new_select.top)
|
||||
|| (old_select.bottom != new_select.bottom)
|
||||
|| (old_select.right != new_select.right)
|
||||
|| (old_select.left != new_select.left)) {
|
||||
|
||||
tmp_rect = sort_rect(&new_select);
|
||||
StrokeRect(tmp_rect);
|
||||
|
||||
tmp_rect = sort_rect(&old_select);
|
||||
StrokeRect(tmp_rect);
|
||||
|
||||
old_select = new_select;
|
||||
Flush();
|
||||
}
|
||||
|
||||
snooze(20000);
|
||||
} while (buttons);
|
||||
|
||||
selection = sort_rect(&new_select);
|
||||
if (!has_selection()) {
|
||||
StrokeRect(selection);
|
||||
selection.Set(-1000, -1000, -1000, -1000);
|
||||
}
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef _VIEW_H
|
||||
#include <View.h>
|
||||
#endif
|
||||
#ifndef _BITMAP_H
|
||||
#include <Bitmap.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef TSB
|
||||
#define TSB
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
#define size_x 384
|
||||
#define size_y 384
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
class TShowBit : public BView {
|
||||
public:
|
||||
BBitmap *the_bitmap;
|
||||
bool busy;
|
||||
bool exit_now;
|
||||
BRect selection;
|
||||
double px;
|
||||
double py;
|
||||
double scale;
|
||||
long iter;
|
||||
|
||||
TShowBit(BRect r, uint32 resizeMask, uint32 flags);
|
||||
virtual ~TShowBit();
|
||||
virtual void Draw(BRect);
|
||||
virtual void MouseDown(BPoint where);
|
||||
void MessageReceived(BMessage* message);
|
||||
virtual void Pulse();
|
||||
void mand(double vx, double vy, double sx, double sy);
|
||||
long limit_v(long v);
|
||||
long limit_h(long h);
|
||||
BRect sort_rect(BRect *aRect);
|
||||
void clip(long *h, long *v);
|
||||
void change_selection(long h, long v);
|
||||
char has_selection();
|
||||
void redraw_mand();
|
||||
void mandb(double vx, double vy, double sx, double sy);
|
||||
void manda(double vx, double vy, double sx, double sy);
|
||||
void set_palette(long code);
|
||||
void set_iter(long i);
|
||||
void precompute(double vx, double vy, double sx, double sy);
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user