/// <summary> /// Compute surface data. /// </summary> protected void Generate(FracValues act_val, int zyklen, double screensize, int formula, bool perspective) { Random rand = new Random(); _maxUpdateSteps = ParameterDict.Current.GetInt("View.UpdateSteps"); double xd, yd, zd; double x, y, z; double dephAdd = ParameterDict.Current.GetInt("View.DephAdd") * screensize; act_val = act_val.Clone(); Formulas formulas = new Formulas(_pData); _lastUsedFormulas = formulas; if (ParameterDict.Current["Intern.Formula.Source"].Trim() == "") { formulas.InternFormula = new Fractrace.TomoGeometry.VecRotMandel2d(); } else { Fractrace.TomoGeometry.TomoFormulaFactory fac = new Fractrace.TomoGeometry.TomoFormulaFactory(); formulas.InternFormula = fac.CreateFromString(ParameterDict.Current["Intern.Formula.Source"]); } if (formulas.InternFormula == null) { return; } formulas.InternFormula.Init(); double centerX = ParameterDict.Current.GetDouble("Scene.CenterX"); double centerY = ParameterDict.Current.GetDouble("Scene.CenterY"); double centerZ = ParameterDict.Current.GetDouble("Scene.CenterZ"); Rotation rotView = new Rotation(); rotView.Init(centerX, centerY, centerZ, ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); formulas.Transforms.Add(rotView); // TODO: only use in compatibility mode. Rotation rot = new Rotation(); rot.Init(); formulas.Transforms.Add(rot); if (_isRightView) { RightEyeView stereoTransform = new RightEyeView(); stereoTransform.Init(); formulas.Transforms.Add(stereoTransform); } _maxxIter = _width; _maxyIter = (int)(ParameterDict.Current.GetDouble("View.Deph") * screensize); if (IsSmallPreview() && _updateCount == 0) { _maxyIter = _maxxIter; } _maxzIter = _height; int MINX_ITER = 0; int MINY_ITER = 0; int MINZ_ITER = 0; int xschl = 0, yschl = 0, zschl = 0, xx = 0, yy = 0; double wix = 0, wiy = 0, wiz = 0; double jx = 0, jy = 0, jz = 0, jzz = 0; jx = ParameterDict.Current.GetDouble("Formula.Static.jx"); jy = ParameterDict.Current.GetDouble("Formula.Static.jy"); jz = ParameterDict.Current.GetDouble("Formula.Static.jz"); jzz = ParameterDict.Current.GetDouble("Formula.Static.jzz"); // Innenbereich int minCycle = (int)ParameterDict.Current.GetDouble("Formula.Static.MinCycle"); if (minCycle == 0) { minCycle = zyklen; } // Offset für den Maximalzyklus für die klassische 2D-Darstellung //int cycleAdd = 128; wix = act_val.arc.x; wiy = act_val.arc.y; wiz = act_val.arc.z; xd = (act_val.end_tupel.x - act_val.start_tupel.x) / (_maxxIter - MINX_ITER); yd = (act_val.end_tupel.y - act_val.start_tupel.y) / (_maxyIter - MINY_ITER); zd = (act_val.end_tupel.z - act_val.start_tupel.z) / (_maxzIter - MINZ_ITER); if (_oldData != null) { yd = yd / (_updateCount); if (_updateCount < 5) { _maxyIter *= _updateCount; } } if (_transformUpdate) { yd *= 3.0; } double xcenter = (act_val.start_tupel.x + act_val.end_tupel.x) / 2.0; double zcenter = (act_val.start_tupel.z + act_val.end_tupel.z) / 2.0; bool isYborder = true; // Projektion initialisieren und der Berechnung zuordnen: // TODO: Projektion über Einstellungen abwählbar machen double cameraDeph = act_val.end_tupel.y - act_val.start_tupel.y; cameraDeph *= ParameterDict.Current.GetDouble("Transformation.Camera.Position"); Vec3 camera = new Vec3(xcenter, act_val.end_tupel.y + cameraDeph, zcenter); Vec3 viewPoint = new Vec3(xcenter, act_val.end_tupel.y, zcenter); Projection proj = new Projection(camera, viewPoint); if (!ParameterDict.Current.GetBool("Transformation.Camera.IsometricProjection")) { formulas.Projection = proj; } // Bei der Postererstellung werden die Parameter der räumlichen Projektion auf das mittlere Bild // ausgerichtet und anschließend die Grenzen verschoben double xPoster = ParameterDict.Current.GetInt("View.PosterX"); double zPoster = ParameterDict.Current.GetInt("View.PosterZ"); double xDiff = act_val.end_tupel.x - act_val.start_tupel.x; double zDiff = act_val.end_tupel.z - act_val.start_tupel.z; act_val.end_tupel.x += xDiff * xPoster; act_val.start_tupel.x += xDiff * xPoster; act_val.end_tupel.z += zDiff * zPoster; act_val.start_tupel.z += zDiff * zPoster; // Start der Iteration in der Reihenfolge: z,x,y (y entspricht der Tiefe) z = act_val.end_tupel.z + zd; for (zschl = (int)(_maxzIter); zschl >= (MINZ_ITER); zschl -= 1) { // Nur wenn der Scheduler die Erlaubnis gibt, zschl zu benutzen, // die Berechnung ausführen (sonst nächste Iteration) if (IsAvailable(_maxzIter - zschl)) { System.Windows.Forms.Application.DoEvents(); z = act_val.end_tupel.z - (double)zd * (_maxzIter - zschl); for (xschl = (int)(MINX_ITER); xschl <= _maxxIter; xschl += 1) { if (_abort) { return; } x = act_val.start_tupel.x + (double)xd * xschl; isYborder = true; xx = xschl; yy = _maxzIter - zschl; if (double.IsNaN(x)) { return; } // Used for better start values in update iteration double yAdd = rand.NextDouble() * yd; // In last computation a voxel ist found at (xx,zz) bool centerIsSet = false; // In last computation at least on voxel ist found near (xx,zz) bool areaIsSet = false; double yAddCenter = 0; bool needComputing = true; if (_oldPictureData != null) { needComputing = false; PixelInfo pxInfoTest = _oldPictureData.Points[xx, yy]; if (pxInfoTest != null && pxInfoTest.Coord != null) { yAddCenter = pxInfoTest.Coord.Y; yAdd = yAddCenter; centerIsSet = true; } for (int xxi = -1; xxi <= 1; xxi++) { for (int yyi = -1; yyi <= 1; yyi++) { int xxposi = xx + xxi; int yyposi = yy + yyi; if (xxposi >= 0 && xxposi <= _maxxIter && yyposi >= 0 && yyposi <= _maxzIter) { PixelInfo pxInfo = _oldPictureData.Points[xxposi, yyposi]; if (pxInfo != null && pxInfo.Coord != null) { areaIsSet = true; double yAddTemp = pxInfo.Coord.Y; if (yAdd < yAddTemp || !centerIsSet) { yAdd = yAddTemp; } } } } } } if (yAdd + yd < act_val.end_tupel.y) { if (centerIsSet) { if (yAddCenter + 4.0 * yd < yAdd) { needComputing = true; yAdd = yAdd - act_val.end_tupel.y + 2.0 * ((double)_updateCount) * yd + rand.NextDouble() * yd; _gData.Picture[xx, yy] = _oldData.Picture[xx, yy]; } } else { if (areaIsSet) { needComputing = true; yAdd = rand.NextDouble() * yd; } } } if (needComputing) { // yadd cannot be easy handled (because of inside rendering). for (yschl = (int)(_maxyIter); yschl >= MINY_ITER - dephAdd; yschl -= 1) { if (_abort) { return; } if (xx >= 0 && xx < _width && yy >= 0 && yy < _height) { if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { // aha, noch zeichnen // Test, ob Schnitt mit Begrenzung vorliegt y = act_val.end_tupel.y - (double)yd * (_maxyIter - yschl); y += yAdd; if (double.IsNaN(x) || double.IsNaN(y) || double.IsNaN(z)) { return; } int usedCycles = 0; bool inverse = false; if (_gData == null) { System.Diagnostics.Debug.WriteLine("Error: GData == null"); return; } if ((_gData.Picture)[xx, yy] == 0) { usedCycles = formulas.Rechne(x, y, z, 0, zyklen, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); } if ((_gData.Picture)[xx, yy] == 2) {// Inverse computing inverse = true; usedCycles = formulas.Rechne(x, y, z, 0, minCycle, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); } if (usedCycles == 0) { // Iteration ist nicht abgebrochen, also weiterrechnen: //int oldPictureInfo = (_gData.Picture)[xx, yy]; // pictureInfo wird eventuell zurückgesetzt, wenn // die Farbberechnung wiederholt wird. _gData.Picture[xx, yy] = 1; // Punkt als gesetzt markieren VoxelInfo vInfo = new VoxelInfo(); _gData.PointInfo[xx, yy] = vInfo; vInfo.i = x; vInfo.j = y; vInfo.k = z; /* * cycleAdd = 1024; * if (minCycle >= 0) * { * cycleAdd = minCycle - zyklen; * } */ if (isYborder) { if (formulas.Rechne(x, y, z, 0, zyklen, wix, wiy, wiz, jx, jy, jz, jzz, formula, false) == 0) { (_gData.Picture)[xx, yy] = 2; // Mark point as not set. } } else {// inner Point if (inverse) { if (IsSmallPreview() && _updateCount == 0) { formulas.RayCastAt(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { formulas.FixPoint(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } } else { if (IsSmallPreview() && _updateCount == 0) { formulas.RayCastAt(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { formulas.FixPoint(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } } } } } } isYborder = false; } if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { if (_oldPictureData != null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } if (_oldData != null && _updateCount > 2) { if (_oldPictureData.Points[xx, yy] != null) { if (_pData.Points[xx, yy] == null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } else { if (_pData.Points[xx, yy].Coord.Y < _oldPictureData.Points[xx, yy].Coord.Y) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } } else { // Get the old values: _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } }
/// <summary> /// Compute surface data. /// </summary> protected void Generate(FracValues act_val, int zyklen, double screensize, int formula, bool perspective) { Random rand = new Random(); _maxUpdateSteps = ParameterDict.Current.GetInt("View.UpdateSteps"); double[] col = null; double xd, yd, zd; double x, y, z; double dephAdd = ParameterDict.Current.GetInt("View.DephAdd") * screensize; act_val = act_val.Clone(); Formulas formulas = new Formulas(_pData); _lastUsedFormulas = formulas; if (ParameterDict.Current["Intern.Formula.Source"].Trim() == "") { formulas.InternFormula = new Fractrace.TomoGeometry.VecRotMandel2d(); } else { Fractrace.TomoGeometry.TomoFormulaFactory fac = new Fractrace.TomoGeometry.TomoFormulaFactory(); formulas.InternFormula = fac.CreateFromString(ParameterDict.Current["Intern.Formula.Source"]); } if (formulas.InternFormula == null) return; formulas.InternFormula.Init(); double centerX = ParameterDict.Current.GetDouble("Scene.CenterX"); double centerY = ParameterDict.Current.GetDouble("Scene.CenterY"); double centerZ = ParameterDict.Current.GetDouble("Scene.CenterZ"); Rotation rotView = new Rotation(); rotView.Init(centerX, centerY, centerZ, ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); formulas.Transforms.Add(rotView); // TODO: only use in compatibility mode. Rotation rot = new Rotation(); rot.Init(); formulas.Transforms.Add(rot); if (_isRightView) { RightEyeView stereoTransform = new RightEyeView(); stereoTransform.Init(); formulas.Transforms.Add(stereoTransform); } col = formulas.col; _maxxIter = _width; _maxyIter = (int)(ParameterDict.Current.GetDouble("View.Deph") * screensize); if(IsSmallPreview()) _maxyIter = _maxxIter; _maxzIter = _height; int MINX_ITER = 0; int MINY_ITER = 0; int MINZ_ITER = 0; double fa1; int xschl = 0, yschl = 0, zschl = 0, xx = 0, yy = 0; double wix = 0, wiy = 0, wiz = 0; double jx = 0, jy = 0, jz = 0, jzz = 0; jx = ParameterDict.Current.GetDouble("Formula.Static.jx"); jy = ParameterDict.Current.GetDouble("Formula.Static.jy"); jz = ParameterDict.Current.GetDouble("Formula.Static.jz"); jzz = ParameterDict.Current.GetDouble("Formula.Static.jzz"); // Innenbereich int minCycle = (int)ParameterDict.Current.GetDouble("Formula.Static.MinCycle"); if (minCycle == 0) minCycle = zyklen; // Offset für den Maximalzyklus für die klassische 2D-Darstellung int cycleAdd = 128; wix = act_val.arc.x; wiy = act_val.arc.y; wiz = act_val.arc.z; xd = (act_val.end_tupel.x - act_val.start_tupel.x) / (_maxxIter - MINX_ITER); yd = (act_val.end_tupel.y - act_val.start_tupel.y) / (_maxyIter - MINY_ITER); zd = (act_val.end_tupel.z - act_val.start_tupel.z) / (_maxzIter - MINZ_ITER); if (_oldData != null) { yd = yd / (_updateCount); if (_updateCount < 5) { _maxyIter *= _updateCount; } } if (_transformUpdate) { yd *= 3.0; } double xcenter = (act_val.start_tupel.x + act_val.end_tupel.x) / 2.0; double ycenter = (act_val.start_tupel.y + act_val.end_tupel.y) / 2.0; double zcenter = (act_val.start_tupel.z + act_val.end_tupel.z) / 2.0; bool isYborder = true; // Projektion initialisieren und der Berechnung zuordnen: // TODO: Projektion über Einstellungen abwählbar machen double cameraDeph = act_val.end_tupel.y - act_val.start_tupel.y; cameraDeph *= ParameterDict.Current.GetDouble("Transformation.Perspective.Cameraposition"); Vec3 camera = new Vec3(xcenter, act_val.end_tupel.y + cameraDeph, zcenter); Vec3 viewPoint = new Vec3(xcenter, act_val.end_tupel.y, zcenter); Projection proj = new Projection(camera, viewPoint); if (ParameterDict.Current.GetBool("View.Perspective")) formulas.Projection = proj; // Bei der Postererstellung werden die Parameter der räumlichen Projektion auf das mittlere Bild // ausgerichtet und anschließend die Grenzen verschoben double xPoster = ParameterDict.Current.GetInt("View.PosterX"); double zPoster = ParameterDict.Current.GetInt("View.PosterZ"); double xDiff = act_val.end_tupel.x - act_val.start_tupel.x; double zDiff = act_val.end_tupel.z - act_val.start_tupel.z; act_val.end_tupel.x += xDiff * xPoster; act_val.start_tupel.x += xDiff * xPoster; act_val.end_tupel.z += zDiff * zPoster; act_val.start_tupel.z += zDiff * zPoster; // Start der Iteration in der Reihenfolge: z,x,y (y entspricht der Tiefe) z = act_val.end_tupel.z + zd; for (zschl = (int)(_maxzIter); zschl >= (MINZ_ITER); zschl -= 1) { // Nur wenn der Scheduler die Erlaubnis gibt, zschl zu benutzen, // die Berechnung ausführen (sonst nächste Iteration) if (IsAvailable(_maxzIter - zschl)) { System.Windows.Forms.Application.DoEvents(); z = act_val.end_tupel.z - (double)zd * (_maxzIter - zschl); bool minYDetected = false; for (xschl = (int)(MINX_ITER); xschl <= _maxxIter; xschl += 1) { if (_abort) { return; } x = act_val.start_tupel.x + (double)xd * xschl; double miny = 0; isYborder = true; xx = xschl; yy = _maxzIter - zschl; if (double.IsNaN(x) ) return ; // Used for better start values in update iteration double yAdd = rand.NextDouble() * yd; // In last computation a voxel ist found at (xx,zz) bool centerIsSet = false; // In last computation at least on voxel ist found near (xx,zz) bool areaIsSet = false; double yAddCenter = 0; bool needComputing = true; if (_oldPictureData != null) { needComputing = false; PixelInfo pxInfoTest = _oldPictureData.Points[xx, yy]; if (pxInfoTest != null && pxInfoTest.Coord != null) { yAddCenter = pxInfoTest.Coord.Y; yAdd = yAddCenter; centerIsSet = true; } for (int xxi = -1; xxi <= 1; xxi++) { for (int yyi = -1; yyi <= 1; yyi++) { int xxposi = xx + xxi; int yyposi = yy + yyi; if (xxposi >= 0 && xxposi <= _maxxIter && yyposi >= 0 && yyposi <= _maxzIter) { PixelInfo pxInfo = _oldPictureData.Points[xxposi, yyposi]; if (pxInfo != null && pxInfo.Coord != null) { areaIsSet = true; double yAddTemp = pxInfo.Coord.Y; if (yAdd < yAddTemp || !centerIsSet) yAdd = yAddTemp; } } } } } if (yAdd + yd < act_val.end_tupel.y) { if (centerIsSet) { if (yAddCenter + 4.0 * yd < yAdd) { needComputing = true; yAdd = yAdd - act_val.end_tupel.y + 2.0 * ((double)_updateCount) * yd + rand.NextDouble() * yd; _gData.Picture[xx, yy] = _oldData.Picture[xx, yy]; } } else { if (areaIsSet) { needComputing = true; yAdd = rand.NextDouble() * yd; } } } if (needComputing) { // yadd cannot be easy handled (because of inside rendering). for (yschl = (int)(_maxyIter); yschl >= MINY_ITER - dephAdd; yschl -= 1) { if (_abort) return; if (xx >= 0 && xx < _width && yy >= 0 && yy < _height) { if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { // aha, noch zeichnen // Test, ob Schnitt mit Begrenzung vorliegt y = act_val.end_tupel.y - (double)yd * (_maxyIter - yschl); y += yAdd; if (double.IsNaN(x) || double.IsNaN(y) || double.IsNaN(z)) return; fa1 = 0; int usedCycles = 0; bool inverse = false; if (_gData == null) { System.Diagnostics.Debug.WriteLine("Error: GData == null"); return; } if ((_gData.Picture)[xx, yy] == 0) usedCycles = formulas.Rechne(x, y, z, 0, zyklen, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); if ((_gData.Picture)[xx, yy] == 2) {// Inverse computing inverse = true; usedCycles = formulas.Rechne(x, y, z, 0, minCycle, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); } if (usedCycles == 0) { if (!minYDetected) miny = yschl; minYDetected = true; // Iteration ist nicht abgebrochen, also weiterrechnen: int oldPictureInfo = (_gData.Picture)[xx, yy]; // pictureInfo wird eventuell zurückgesetzt, wenn // die Farbberechnung wiederholt wird. _gData.Picture[xx, yy] = 1; // Punkt als gesetzt markieren VoxelInfo vInfo = new VoxelInfo(); _gData.PointInfo[xx, yy] = vInfo; vInfo.i = x; vInfo.j = y; vInfo.k = z; cycleAdd = 1024; if (minCycle >= 0) { cycleAdd = minCycle - zyklen; } if (isYborder) { // es liegt Schnitt mit Begrenzung vor fa1 = formulas.Rechne(x, y, z, 0, zyklen + cycleAdd, wix, wiy, wiz, jx, jy, jz, jzz, formula, false); if (fa1 == 0) { fa1 = -1; (_gData.Picture)[xx, yy] = 2; // Punkt nicht als gesetzt markieren } else fa1 = 255 * fa1 / (zyklen + cycleAdd); // debug only: alle Farbwerte auf 1 setzen col[0] = col[1] = col[2] = col[3] = 255; } else {// innerer Punkt if (inverse) { if (IsSmallPreview()) { fa1 = formulas.RayCastAt(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { fa1 = formulas.FixPoint(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } } else { if (IsSmallPreview()) { fa1 = formulas.RayCastAt(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { fa1 = formulas.FixPoint(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); fa1 = (col[0] + col[1] + col[2] + col[3]) / 4.0; } } } } } } isYborder = false; } if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { if (_oldPictureData != null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } if (_oldData != null && _updateCount > 2) { if (_oldPictureData.Points[xx, yy] != null) { if (_pData.Points[xx, yy] == null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } else { if (_pData.Points[xx, yy].Coord.Y < _oldPictureData.Points[xx, yy].Coord.Y) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } } else { // Get the old values: _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } }