You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
829 lines
21 KiB
829 lines
21 KiB
// quantumfractals.cs - Port of eeqt to Qt#
|
|
// Author: Adam Treat <manyoso@yahoo.com>
|
|
// (c) 2002 Adam Treat
|
|
// Licensed under the terms of the GNU GPL
|
|
|
|
namespace Qf {
|
|
|
|
using Qt;
|
|
using System;
|
|
using System.Threading;
|
|
|
|
public class FractalViewer : TQMainWindow {
|
|
|
|
//Menuing
|
|
private TQMenuBar menubar;
|
|
private TQPopupMenu filemenu;
|
|
private TQPopupMenu shapemenu;
|
|
private TQPopupMenu settingsmenu;
|
|
|
|
public static int Main (string[] args)
|
|
{
|
|
//Initialize and start the main event loop
|
|
TQApplication app = new TQApplication (args);
|
|
FractalViewer view = new FractalViewer ();
|
|
app.SetMainWidget (view);
|
|
view.Show ();
|
|
return app.Exec ();
|
|
}
|
|
|
|
public FractalViewer (): base (null, "main")
|
|
{
|
|
SetCaption ("Quantum Fractals");
|
|
|
|
//Setup the display
|
|
Display display = new Display (this);
|
|
SetCentralWidget (display);
|
|
|
|
//Setup the filemenu
|
|
filemenu = new TQPopupMenu (null, "filemenu");
|
|
filemenu.InsertItem ("&Screenshot", display, TQ_SLOT ("SlotScreenshot()"));
|
|
filemenu.InsertSeparator ();
|
|
filemenu.InsertItem ("&Quit", tqApp, TQ_SLOT ("quit()"));
|
|
|
|
//Setup the shapemenu
|
|
shapemenu = new TQPopupMenu (null, "typemenu");
|
|
shapemenu.InsertItem( "&Tetrahedron", 0);
|
|
shapemenu.InsertItem( "&Cube", 1);
|
|
shapemenu.InsertItem( "&Octahedron", 2);
|
|
shapemenu.InsertItem( "&Icosahedron", 3);
|
|
shapemenu.InsertItem( "&Dodecahedron", 4);
|
|
shapemenu.InsertItem( "&Double Tetrahedron", 5);
|
|
shapemenu.InsertItem( "&Icosidodecahedron", 6);
|
|
|
|
//Connect the shapemenu
|
|
TQObject.Connect (shapemenu, TQ_SIGNAL ("activated(int)"),
|
|
display, TQ_SLOT("SlotShapeMenu(int)"));
|
|
|
|
//Setup the settingsmenu
|
|
settingsmenu = new TQPopupMenu (null, "settingsmenu");
|
|
settingsmenu.InsertItem ("&Alpha", display, TQ_SLOT ("SlotSetAlpha()"));
|
|
|
|
//Setup the menubar
|
|
menubar = new TQMenuBar (this, "");
|
|
menubar.InsertItem ("&File", filemenu);
|
|
menubar.InsertItem ("&Shape", shapemenu);
|
|
menubar.InsertItem ("&Settings", settingsmenu);
|
|
}
|
|
}
|
|
|
|
public class Display: TQWidget, IQuantumFractal {
|
|
|
|
//Labels
|
|
TQLabel count;
|
|
TQLabel shape;
|
|
TQLabel alpha;
|
|
|
|
//Buttons
|
|
TQPushButton start;
|
|
TQPushButton stop;
|
|
TQPushButton reset;
|
|
TQPushButton gray;
|
|
TQPushButton intense;
|
|
|
|
//Drawable region
|
|
TQPaintBuffer buffer;
|
|
|
|
//Layouts
|
|
TQVBoxLayout layout;
|
|
TQHBoxLayout buttons;
|
|
TQVBoxLayout labels;
|
|
|
|
//Engine controller variables
|
|
int[] topDensity = new int[0];
|
|
int[] bottomDensity = new int[0];
|
|
int resolution = 400;
|
|
int scale = 1;
|
|
double centerX = 0;
|
|
double centerY = 0;
|
|
int i = 0;
|
|
bool Grayscale = true;
|
|
bool Intense = false;
|
|
bool Running = false;
|
|
bool WasRunning = false;
|
|
|
|
//The engine
|
|
QuantumFractals qf;
|
|
Thread engine;
|
|
|
|
public Display (TQWidget parent): base (parent)
|
|
{
|
|
//Setup the sizes
|
|
TQSize size = new TQSize (resolution, resolution);
|
|
parent.SetBaseSize (size);
|
|
|
|
//Some nice colors
|
|
SetPaletteBackgroundColor (new TQColor ("Black"));
|
|
SetPaletteForegroundColor (new TQColor ("LightBlue"));
|
|
|
|
//Setup the buttons
|
|
start = new TQPushButton ("Start", this);
|
|
stop = new TQPushButton ("Stop", this);
|
|
reset = new TQPushButton ("Reset", this);
|
|
gray = new TQPushButton ("Color", this);
|
|
intense = new TQPushButton ("Intensity", this);
|
|
|
|
//Setup the labels
|
|
count = new TQLabel (this);
|
|
alpha = new TQLabel (this);
|
|
shape = new TQLabel (this);
|
|
|
|
//Setup the drawable
|
|
buffer = new TQPaintBuffer (this);
|
|
buffer.SetMinimumSize (size);
|
|
|
|
//Create the layouts
|
|
layout = new TQVBoxLayout (this);
|
|
buttons = new TQHBoxLayout (layout);
|
|
|
|
//Add some buttons
|
|
buttons.AddWidget (start);
|
|
buttons.AddWidget (stop);
|
|
buttons.AddWidget (reset);
|
|
buttons.AddWidget (gray);
|
|
buttons.AddWidget (intense);
|
|
|
|
//Connect the buttons and SlotQuit
|
|
TQObject.Connect (start, TQ_SIGNAL ("clicked()"),
|
|
this, TQ_SLOT ("SlotStart()"));
|
|
TQObject.Connect (stop, TQ_SIGNAL ("clicked()"),
|
|
this, TQ_SLOT ("SlotStop()"));
|
|
TQObject.Connect (reset, TQ_SIGNAL ("clicked()"),
|
|
this, TQ_SLOT ("SlotReset()"));
|
|
TQObject.Connect (gray, TQ_SIGNAL ("clicked()"),
|
|
this, TQ_SLOT ("SlotGray()"));
|
|
TQObject.Connect (intense, TQ_SIGNAL ("clicked()"),
|
|
this, TQ_SLOT ("SlotIntense()"));
|
|
TQObject.Connect (buffer, TQ_SIGNAL ("Painted()"),
|
|
this, TQ_SLOT ("SlotSetLabels()"));
|
|
TQObject.Connect (tqApp, TQ_SIGNAL ("lastWindowClosed ()"),
|
|
this, TQ_SLOT ("SlotQuit ()"));
|
|
|
|
//Layout labels
|
|
labels = new TQVBoxLayout (layout);
|
|
labels.AddWidget (count);
|
|
labels.AddWidget (shape);
|
|
labels.AddWidget (alpha);
|
|
|
|
//Layout buffer
|
|
layout.AddWidget (buffer, 1);
|
|
|
|
//Finally create the data engine
|
|
qf = new QuantumFractals (this);
|
|
|
|
//Handle resize events
|
|
resizeEvent += new ResizeEvent (TouchResize);
|
|
}
|
|
|
|
//This is where the controller receives data from the engine
|
|
public void UpdateData (double[] d)
|
|
{
|
|
i++; //Keep track of the number of points
|
|
|
|
//Set the density arrays to match the resolution
|
|
if (resolution * resolution != topDensity.Length) {
|
|
topDensity = new int[resolution * resolution];
|
|
bottomDensity = new int[resolution * resolution];
|
|
}
|
|
|
|
//setup the sphere
|
|
int res = resolution;
|
|
int res2 = res / 2;
|
|
int x = res / 2 + (int)(res2 * scale * (d[0] - centerX));
|
|
int y = res / 2 + (int)(res2 * scale * (d[1] - centerY));
|
|
double z = d[2];
|
|
|
|
if ((x < res) && (x >= 0) && (y >= 0) && (y < res)) {
|
|
|
|
if (z >= 0)
|
|
topDensity[y * resolution + x]++;
|
|
else
|
|
bottomDensity[y * resolution + x]++;
|
|
|
|
}
|
|
|
|
//Convert the density into a color
|
|
int top = topDensity[y * resolution + x];
|
|
//int bot = bottomDensity[y * resolution + x];
|
|
top = Math.Min (top, 255);
|
|
//bot = Math.Min (bot, 255);
|
|
|
|
//Log color system not working well :(
|
|
if (Intense) {
|
|
top = (int)(Math.Log (top + 1));
|
|
//bot = (int)(Math.Log (bot + 1));
|
|
}
|
|
|
|
int topdepth = RGB (top,top,top);
|
|
//int botdepth = RGB (bot,bot,bot);
|
|
|
|
//Finally draw the pixel
|
|
SetPixel (x, y, topdepth);
|
|
//SetPixel (x, y, botdepth);
|
|
}
|
|
|
|
//Calls the drawable
|
|
public void SetPixel (int x, int y, int depth)
|
|
{
|
|
buffer.PaintPixel (x, y, depth);
|
|
}
|
|
|
|
//Convert the color into a depth
|
|
public int RGB (int r, int g, int b)
|
|
{
|
|
if (!Grayscale) {
|
|
|
|
r = Intensity (r < 128 ? 128 - r : 0);
|
|
g = Intensity (128 - Math.Abs (g - 128));
|
|
b = Intensity (b < 128 ? 0 : b - 128);
|
|
|
|
} else {
|
|
|
|
r = Intensity (r);
|
|
g = Intensity (g);
|
|
b = Intensity (b);
|
|
|
|
}
|
|
//Console.WriteLine ("{0} {1} {2}", r,g,b);
|
|
return 256 * 256 * r + 256 * g + b;
|
|
}
|
|
|
|
//This provides more detail
|
|
private int Intensity(int val)
|
|
{
|
|
int ret;
|
|
|
|
double bases = 64;
|
|
double scale = 256.0 / (256.0 - bases);
|
|
ret = (int)(bases + ((double)val) / scale);
|
|
|
|
//if gray then black, if color then white
|
|
if (val == 0 && Grayscale)
|
|
ret = 0;
|
|
else if (val == 0)
|
|
ret = 255;
|
|
return ret;
|
|
}
|
|
|
|
//Draw the labels
|
|
private void SlotSetLabels ()
|
|
{
|
|
count.SetText ("Count: " + i.ToString ());
|
|
shape.SetText ("Shape: " + qf.GetPolytope ());
|
|
alpha.SetText ("Alpha: " + qf.Alpha.ToString ());
|
|
}
|
|
|
|
//Start the engine
|
|
private void SlotStart ()
|
|
{
|
|
engine = new Thread(new ThreadStart(qf.Start));
|
|
engine.Start ();
|
|
Running = true;
|
|
}
|
|
|
|
//Stop the engine
|
|
private void SlotStop ()
|
|
{
|
|
if (engine != null)
|
|
if (engine.IsAlive)
|
|
engine.Abort ();
|
|
Running = false;
|
|
}
|
|
|
|
//Reset everything
|
|
private void SlotReset ()
|
|
{
|
|
SlotStop ();
|
|
ResetBuffer ();
|
|
SlotStart ();
|
|
}
|
|
|
|
//Reset the drawable
|
|
private void ResetBuffer ()
|
|
{
|
|
i = 0;
|
|
SlotSetLabels ();
|
|
topDensity = new int[0];
|
|
bottomDensity = new int[0];
|
|
buffer.Reset ();
|
|
}
|
|
|
|
//Toggles the color scheme
|
|
private void SlotGray ()
|
|
{
|
|
Grayscale = !Grayscale;
|
|
}
|
|
|
|
//Toggles log color scheme
|
|
//Not working so well :(
|
|
private void SlotIntense ()
|
|
{
|
|
Intense = !Intense;
|
|
}
|
|
|
|
//Change the platonic shape
|
|
private void SlotShapeMenu (int item)
|
|
{
|
|
WasRunning = Running ? true : false;
|
|
|
|
SlotStop ();
|
|
ResetBuffer ();
|
|
|
|
switch(item) {
|
|
|
|
case 0:
|
|
qf.SetPolytope (0);
|
|
break;
|
|
case 1:
|
|
qf.SetPolytope (1);
|
|
break;
|
|
case 2:
|
|
qf.SetPolytope (2);
|
|
break;
|
|
case 3:
|
|
qf.SetPolytope (3);
|
|
break;
|
|
case 4:
|
|
qf.SetPolytope (4);
|
|
break;
|
|
case 5:
|
|
qf.SetPolytope (5);
|
|
break;
|
|
case 6:
|
|
qf.SetPolytope (6);
|
|
break;
|
|
Default:
|
|
qf.SetPolytope (0);
|
|
break;
|
|
}
|
|
|
|
if (WasRunning)
|
|
SlotStart ();
|
|
}
|
|
|
|
//Save the drawable as a screenshot
|
|
private void SlotScreenshot ()
|
|
{
|
|
WasRunning = Running ? true : false;
|
|
|
|
SlotStop ();
|
|
string filename = TQFileDialog.GetSaveFileName (
|
|
|
|
TQDir.HomeDirPath (), "*", this, "save",
|
|
"Save Screenshot", "*.png", true
|
|
);
|
|
|
|
if (filename != null)
|
|
buffer.Save (filename);
|
|
|
|
if (WasRunning)
|
|
SlotStart ();
|
|
}
|
|
|
|
//Set the alpha engine variable
|
|
private void SlotSetAlpha ()
|
|
{
|
|
WasRunning = Running ? true : false;
|
|
|
|
SlotStop ();
|
|
qf.Alpha = TQInputDialog.GetDouble (
|
|
|
|
"Set Alpha", "Alpha: ", qf.Alpha, 0, 2, 32
|
|
);
|
|
|
|
if (WasRunning)
|
|
SlotStart ();
|
|
else
|
|
SlotSetLabels ();
|
|
}
|
|
|
|
//Make sure to quit all threads upon exit
|
|
private void SlotQuit ()
|
|
{
|
|
SlotStop ();
|
|
buffer.Stop ();
|
|
}
|
|
|
|
//Need to reset the resolution upon resize
|
|
private void TouchResize (TQResizeEvent e)
|
|
{
|
|
int height = buffer.Size ().Height ();
|
|
int width = buffer.Size ().Width ();
|
|
|
|
resolution = height > width ? width : height;
|
|
}
|
|
}
|
|
|
|
[DeclareQtSignal ("Painted()")]
|
|
public class TQPaintBuffer : TQFrame {
|
|
|
|
//Drawables
|
|
private TQPixmap buffer;
|
|
private TQImage image;
|
|
|
|
//Timer
|
|
private TimerCallback call;
|
|
private Timer timer;
|
|
|
|
public TQPaintBuffer (TQWidget parent) : base (parent)
|
|
{
|
|
SetBackgroundMode (Qt.BackgroundMode.NoBackground);
|
|
|
|
//Create drawables
|
|
buffer = new TQPixmap ();
|
|
image = new TQImage (Size (), 32);
|
|
|
|
//Setup the event handlers
|
|
paintEvent += new PaintEvent (TouchPaint);
|
|
resizeEvent += new ResizeEvent (TouchResize);
|
|
focusInEvent += new FocusInEvent (TouchFocus);
|
|
focusOutEvent += new FocusOutEvent (TouchFocus);
|
|
|
|
//Start the timer
|
|
call = new TimerCallback(PaintImage);
|
|
timer = new Timer(call, null, 1000, 1000);
|
|
|
|
}
|
|
|
|
//Resets the drawables
|
|
public void Reset ()
|
|
{
|
|
buffer = new TQPixmap ();
|
|
image = new TQImage (Size (), 32);
|
|
PaintImage (null);
|
|
}
|
|
|
|
//Paints a pixel to the image
|
|
public void PaintPixel (int x, int y, int depth)
|
|
{
|
|
lock (this) {
|
|
if (x < image.Width () && y < image.Height ())
|
|
image.SetPixel (x, y, (uint)depth);
|
|
}
|
|
}
|
|
|
|
//Saves the image to a file
|
|
public void Save (string filename)
|
|
{
|
|
image.Save (filename, "PNG");
|
|
}
|
|
|
|
//Paints the image to the screen and emits Painted
|
|
private void PaintImage (object state)
|
|
{
|
|
buffer.ConvertFromImage (image);
|
|
PerformPaint ();
|
|
Emit ("Painted()");
|
|
}
|
|
|
|
//The actual bitblt to the screen
|
|
private void PerformPaint ()
|
|
{
|
|
BitBlt(this, 0, 0, buffer,
|
|
0, 0, -1, -1, RasterOp.CopyROP, false);
|
|
}
|
|
|
|
//Receive focus events
|
|
private void TouchFocus (TQFocusEvent e)
|
|
{
|
|
PerformPaint ();
|
|
}
|
|
|
|
//Receive paint events
|
|
private void TouchPaint (TQPaintEvent e)
|
|
{
|
|
PerformPaint ();
|
|
}
|
|
|
|
//Receive resize events
|
|
private void TouchResize (TQResizeEvent e)
|
|
{
|
|
image = new TQImage (e.Size (), 32);
|
|
buffer.Resize (e.Size());
|
|
buffer.Fill (new TQColor("black"));
|
|
BitBlt (buffer, 0, 0, new TQPixmap (buffer),
|
|
0, 0, -1, -1, RasterOp.CopyROP, false);
|
|
}
|
|
|
|
//Dispose of the timer
|
|
public void Stop ()
|
|
{
|
|
timer.Dispose ();
|
|
}
|
|
}
|
|
|
|
public interface IQuantumFractal {
|
|
|
|
void UpdateData (Double [] data);
|
|
}
|
|
|
|
//Polytope types
|
|
public enum Shapes {
|
|
TETRAHEDRON = 0,
|
|
CUBE = 1,
|
|
OCTAHEDRON = 2,
|
|
ICOSAHEDRON = 3,
|
|
DODECAHEDRON = 4,
|
|
DOUBLE_TETRAHEDRON = 5,
|
|
ICOSIDODECAHEDRON = 6
|
|
}
|
|
|
|
public class QuantumFractals {
|
|
|
|
private int t = 0;
|
|
private double[] p; //Detector probabilities
|
|
private double[] fp; //Fractal point
|
|
private double[][] n; //Detector points
|
|
private double[] counter; //Detect counter
|
|
private double alpha = 0.61803398874989288039384209090709; //Initialize to 1/phi
|
|
|
|
private Random random;
|
|
private Shapes polytope;
|
|
private IQuantumFractal consumer;
|
|
|
|
public QuantumFractals (IQuantumFractal consumer)
|
|
{
|
|
this.consumer = consumer;
|
|
SetPolytope (0);
|
|
Init ();
|
|
}
|
|
|
|
public double Alpha
|
|
{
|
|
get { return alpha; }
|
|
set { alpha = value; }
|
|
}
|
|
|
|
private void Init ()
|
|
{
|
|
random = new Random ();
|
|
|
|
//Default values
|
|
t = 0;
|
|
|
|
counter = new double[n.Length]; //Detect counter
|
|
fp = new double[3]; //Fractal point
|
|
p = new double[n.Length];
|
|
|
|
//Initial state
|
|
fp[0] = random.NextDouble () -0.5;
|
|
fp[1] = random.NextDouble () -0.5;
|
|
fp[2] = random.NextDouble () -0.5;
|
|
|
|
double sum = Math.Sqrt (Product (fp, fp));
|
|
|
|
fp[0] = fp[0] / sum;
|
|
fp[1] = fp[1] / sum;
|
|
fp[2] = fp[2] / sum;
|
|
}
|
|
|
|
//Main fractal generator loop
|
|
public void Start ()
|
|
{
|
|
Init ();
|
|
|
|
//double n1 = (1.0) / n.Length as double;
|
|
double n1 = (1.0) / n.Length;
|
|
|
|
double alpha12 = 2 * alpha / (n.Length * (1 + alpha * alpha));
|
|
|
|
do {
|
|
//Increase t
|
|
t++;
|
|
|
|
//Calculate detector click probabilities
|
|
for (int i = 0; i < p.Length; i++)
|
|
p[i] = n1 + alpha12 * Product (n[i], fp);
|
|
|
|
//Get next random number
|
|
double r = random.NextDouble ();
|
|
|
|
//Check which detector that clicked
|
|
double ptmp = 0;
|
|
double[] detector = null;
|
|
|
|
for (int i = 0; i < p.Length; i++) {
|
|
|
|
ptmp += p[i];
|
|
|
|
if (r <= ptmp) {
|
|
//We found which detector clicked
|
|
detector = n[i];
|
|
counter[i]++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (detector == null)
|
|
detector = n[p.Length - 1];
|
|
|
|
//Project
|
|
double sc = Product (fp, detector);
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
fp[j]= (1 - alpha * alpha) * fp[j] + 2 * alpha * (1 + alpha * sc) * detector[j];
|
|
|
|
//Normalize
|
|
double norm = Math.Sqrt (Product (fp, fp));
|
|
|
|
for (int j=0; j<3; j++)
|
|
fp[j] /= norm;
|
|
|
|
consumer.UpdateData (fp);
|
|
|
|
} while (true);
|
|
}
|
|
|
|
|
|
//Calculate the scalar product of two vectors
|
|
private double Product (double[] v1, double[] v2)
|
|
{
|
|
double sc = 0;
|
|
for(int i=0; i < v1.Length; i++)
|
|
sc += v1[i] * v2[i];
|
|
return sc;
|
|
}
|
|
|
|
public string GetPolytope ()
|
|
{
|
|
string ret = String.Empty;
|
|
switch (polytope) {
|
|
case Shapes.TETRAHEDRON:
|
|
ret = "Tetrahedron";
|
|
break;
|
|
case Shapes.CUBE:
|
|
ret = "Cube";
|
|
break;
|
|
case Shapes.OCTAHEDRON:
|
|
ret = "Octahedron";
|
|
break;
|
|
case Shapes.ICOSAHEDRON:
|
|
ret = "Icosahedron";
|
|
break;
|
|
case Shapes.DODECAHEDRON:
|
|
ret = "Dodecahedron";
|
|
break;
|
|
case Shapes.DOUBLE_TETRAHEDRON:
|
|
ret = "Double Tetrahedron";
|
|
break;
|
|
case Shapes.ICOSIDODECAHEDRON:
|
|
ret = "Icosidodecahedron";
|
|
break;
|
|
Default:
|
|
ret = "Unknown";
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public void SetPolytope (int type)
|
|
{
|
|
polytope = (Qf.Shapes)type;
|
|
|
|
switch (type) {
|
|
|
|
case 0: {
|
|
|
|
n = new double[4][];
|
|
n[0] = new double[] {0,0,1.0};
|
|
n[1] = new double[] {0.9428090415820634,0,-0.3333333333333333};
|
|
n[2] = new double[] {-0.4714045207910317,0.816496580927726,-0.3333333333333333};
|
|
n[3] = new double[] {-0.4714045207910317, -0.816496580927726, -0.3333333333333333};
|
|
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
|
|
n = new double[8][];
|
|
n[0] = new double[] {0, 0, 1.0};
|
|
n[1] = new double[] {0.9428090415820634, 0, 0.3333333333333333};
|
|
n[2] = new double[] {-0.4714045207910317, 0.816496580927726, 0.3333333333333333};
|
|
n[3] = new double[] {-0.4714045207910317, -0.816496580927726, 0.3333333333333333};
|
|
n[4] = new double[] {0.4714045207910317, 0.816496580927726, -0.3333333333333333};
|
|
n[5] = new double[] {0.4714045207910317, -0.816496580927726, -0.3333333333333333};
|
|
n[6] = new double[] {-0.9428090415820634, 0, -0.3333333333333333};
|
|
n[7] = new double[] {0, 0, -1.0};
|
|
break;
|
|
}
|
|
|
|
case 2: {
|
|
|
|
n = new double[6][];
|
|
n[0] = new double[] {0, 0, 1.0};
|
|
n[1] = new double[] {1.0, 0, 0};
|
|
n[2] = new double[] {0, 1.0, 0};
|
|
n[3] = new double[] {-1.0, 0, 0};
|
|
n[4] = new double[] {0, -1.0, 0};
|
|
n[5] = new double[] {0, 0, -1.0};
|
|
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
|
|
n = new double[12][];
|
|
n[0] = new double[] {0, 0, 1.0};
|
|
n[1] = new double[] {0.8944271909999159, 0, 0.4472135954999579};
|
|
n[2] = new double[] {0.276393202250021, 0.85065080835204, 0.4472135954999579};
|
|
n[3] = new double[] {-0.723606797749979, 0.5257311121191336, 0.4472135954999579};
|
|
n[4] = new double[] {-0.723606797749979, -0.5257311121191336, 0.4472135954999579};
|
|
n[5] = new double[] {0.276393202250021, -0.85065080835204, 0.4472135954999579};
|
|
n[6] = new double[] {0.723606797749979, 0.5257311121191336, -0.4472135954999579};
|
|
n[7] = new double[] {0.723606797749979, -0.5257311121191336, -0.4472135954999579};
|
|
n[8] = new double[] {-0.276393202250021, 0.85065080835204, -0.4472135954999579};
|
|
n[9] = new double[] {-0.8944271909999159, 0, -0.4472135954999579};
|
|
n[10] = new double[] {-0.276393202250021, -0.85065080835204, -0.4472135954999579};
|
|
n[11] = new double[] {0, 0, -1.0};
|
|
|
|
break;
|
|
}
|
|
|
|
case 4: {
|
|
|
|
n = new double[20][];
|
|
n[0] = new double[] {0, 0, 1.0};
|
|
n[1] = new double[] {0.6666666666666666, 0, 0.7453559924999299};
|
|
n[2] = new double[] {-0.3333333333333333, 0.5773502691896257, 0.7453559924999299};
|
|
n[3] = new double[] {-0.3333333333333333, -0.5773502691896257, 0.7453559924999299};
|
|
n[4] = new double[] {0.7453559924999299, 0.5773502691896257, 0.3333333333333333};
|
|
n[5] = new double[] {0.7453559924999299, -0.5773502691896257, 0.3333333333333333};
|
|
n[6] = new double[] {-0.8726779962499649, 0.35682208977308993, 0.3333333333333333};
|
|
n[7] = new double[] {0.12732200375003502, 0.9341723589627157, 0.3333333333333333};
|
|
n[8] = new double[] {0.12732200375003502, -0.9341723589627157, 0.3333333333333333};
|
|
n[9] = new double[] {-0.8726779962499649, -0.35682208977308993, 0.3333333333333333};
|
|
n[10] = new double[] {0.8726779962499649, 0.35682208977308993, -0.3333333333333333};
|
|
n[11] = new double[] {0.8726779962499649, -0.35682208977308993, -0.3333333333333333};
|
|
n[12] = new double[] {-0.7453559924999299, 0.5773502691896257, -0.3333333333333333};
|
|
n[13] = new double[] {-0.12732200375003502, 0.9341723589627157, -0.3333333333333333};
|
|
n[14] = new double[] {-0.12732200375003502, -0.9341723589627157, -0.3333333333333333};
|
|
n[15] = new double[] {-0.7453559924999299, -0.5773502691896257, -0.3333333333333333};
|
|
n[16] = new double[] {0.3333333333333333, 0.5773502691896257, -0.7453559924999299};
|
|
n[17] = new double[] {0.3333333333333333, -0.5773502691896257, -0.7453559924999299};
|
|
n[18] = new double[] {-0.6666666666666666, 0, -0.7453559924999299};
|
|
n[19] = new double[] {0, 0, -1.0};
|
|
break;
|
|
}
|
|
|
|
case 5: {
|
|
|
|
n = new double[8][];
|
|
n[0] = new double[] {0,0,1.0};
|
|
n[1] = new double[] {0.9428090415820634,0,-0.3333333333333333};
|
|
n[2] = new double[] {-0.4714045207910317,0.816496580927726,-0.3333333333333333};
|
|
n[3] = new double[] {-0.4714045207910317, -0.816496580927726, -0.3333333333333333};
|
|
n[4] = new double[] {0,0,-1.0};
|
|
n[5] = new double[] {-0.9428090415820634,0,0.3333333333333333};
|
|
n[6] = new double[] {0.4714045207910317,-0.816496580927726,0.3333333333333333};
|
|
n[7] = new double[] {0.4714045207910317, 0.816496580927726, 0.3333333333333333};
|
|
|
|
break;
|
|
}
|
|
|
|
case 6: {
|
|
|
|
double u=0.5;
|
|
double v=0.8090169943749475; // (1/2)*phi
|
|
double w=0.3090169943749474; // (1/2)/phi
|
|
|
|
n = new double[30][];
|
|
n[0] = new double[] {1,0,0};
|
|
n[1] = new double[] {-1,0,0};
|
|
n[2] = new double[] {0,1,0};
|
|
n[3] = new double[] {0,-1,0};
|
|
n[4] = new double[] {0,0,1};
|
|
n[5] = new double[] {0,0,-1};
|
|
n[6] = new double[] {u,v,w};
|
|
n[7] = new double[] {-u,v,w};
|
|
n[8] = new double[] {u,-v,w};
|
|
n[9] = new double[] {u,v,-w};
|
|
n[10] = new double[] {-u,-v,w};
|
|
n[11] = new double[] {u,-v,-w};
|
|
n[12] = new double[] {-u,v,-w};
|
|
n[13] = new double[] {-u,-v,-w};
|
|
n[14] = new double[] {v,w,u};
|
|
n[15] = new double[] {v,w,-u};
|
|
n[16] = new double[] {-v,w,u};
|
|
n[17] = new double[] {v,-w,u};
|
|
n[18] = new double[] {-v,w,-u};
|
|
n[19] = new double[] {-v,-w,u};
|
|
n[20] = new double[] {v,-w,-u};
|
|
n[21] = new double[] {-v,-w,-u};
|
|
n[22] = new double[] {w,u,v};
|
|
n[23] = new double[] {w,-u,v};
|
|
n[24] = new double[] {w,u,-v};
|
|
n[25] = new double[] {-w,u,v};
|
|
n[26] = new double[] {w,-u,-v};
|
|
n[27] = new double[] {-w,u,-v};
|
|
n[28] = new double[] {-w,-u,v};
|
|
n[29] = new double[] {-w,-u,-v};
|
|
break;
|
|
}
|
|
|
|
Default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|