コード例 #1
0
        private unsafe void OnExportSelectedButtonClick(object sender, EventArgs e)
        {
            ListView.Item selected = listView.FocusedItem;
            if (selected == null)
            {
                // Nothing to export...
                return;
            }

            ArithmeticExpression ae = selected.NumericValueSource as ArithmeticExpression;

            if (ae == null)
            {
                MessageBox.Show(this, Tx.T("dataset.errors.item not supported"), Tx.T("main.error"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            long xFi = 0, xLi = 0, distance = 0;

            if (ae.VariableName != null)
            {
                double xF_ = graph.MinVisibleX;
                double xL_ = graph.MaxVisibleX;

                if (xF_ >= xL_)
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.cannot determine interval"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (Math.Sign(xF_) != Math.Sign(xL_))
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.interval with zero"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // Swap first and last for negative "x" values
                xFi = *(long *)&xF_;
                xLi = *(long *)&xL_;
                if (xFi > xLi)
                {
                    long swap = xLi;
                    xLi = xFi;
                    xFi = swap;
                }
                distance = (xLi - xFi);

                if (distance < 0)
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.interval too big"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (distance > 10 * 1000 * 1000)
                {
                    long   sizeInMB = (distance * 8 * 2 / 1024 / 1024);
                    string sizeString;
                    if (sizeInMB > 100L * 1024L)
                    {
                        sizeString = Tx.N(sizeInMB / 1024) + " GB";
                    }
                    else
                    {
                        sizeString = Tx.N(sizeInMB) + " MB";
                    }

                    if (MessageBox.Show(this, Tx.T("dataset.errors.file too big", Tx.N(distance), sizeString), Tx.T("main.warning"),
                                        MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                    {
                        return;
                    }
                }
            }

            using (SaveFileDialog dialog = new SaveFileDialog()) {
                const string ext = ".fvis-values";

                dialog.Filter           = Tx.T("dataset.filetype") + " (*" + ext + ")|*" + ext;
                dialog.FilterIndex      = 0;
                dialog.RestoreDirectory = true;
                dialog.Title            = Tx.T("dataset.save");

                string filename     = selected.Text;
                char[] invalidChars = Path.GetInvalidFileNameChars();
                for (int i = 0; i < invalidChars.Length; i++)
                {
                    filename = filename.Replace(invalidChars[i], '_');
                }

                dialog.FileName = filename + ext;

                if (dialog.ShowDialog(this) != DialogResult.OK)
                {
                    return;
                }

                filename = dialog.FileName;

                ProgressDialog progressDialog = new ProgressDialog();
                progressDialog.Text            = Tx.T("dataset.saving.title");
                progressDialog.MainInstruction = Tx.T("dataset.saving.description");
                progressDialog.Line1           = Tx.T("dataset.saving.progress", "0", Tx.N(xLi - xFi));
                progressDialog.Show(this);

                ThreadPool.UnsafeQueueUserWorkItem(delegate {
                    using (FileStream s = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
                        using (BinaryWriter bw = new BinaryWriter(s)) {
                            bw.Write(new[] { (byte)'f', (byte)'V', (byte)'i', (byte)'s' });

                            const int flags = 0;
                            bw.Write(flags);

                            string description = selected.Text;
                            bw.Write(description);

                            // Save graph viewport settings
                            long axisX         = graph.AxisX;
                            long axisY         = graph.AxisY;
                            double scaleFactor = graph.ScaleFactor;

                            bw.Write(axisX);
                            bw.Write(axisY);
                            bw.Write(scaleFactor);

                            if (ae.VariableName == null)
                            {
                                // Constant function, save only one value
                                double y = ae.Evaluate(double.NaN);

                                const long count = 2;
                                bw.Write(count);

                                bw.Write(double.MinValue);
                                bw.Write(y);
                                bw.Write(double.MaxValue);
                                bw.Write(y);
                            }
                            else
                            {
                                bw.Write(distance + 1);

                                Stopwatch sw       = Stopwatch.StartNew();
                                long lastProcessed = xFi;

                                for (long xi = xFi; xi <= xLi; xi++)
                                {
                                    double x = *(double *)&xi;
                                    double y = ae.Evaluate(x);

                                    bw.Write(x);
                                    bw.Write(y);

                                    if (sw.ElapsedMilliseconds > 4000)
                                    {
                                        if (progressDialog.IsCancelled)
                                        {
                                            break;
                                        }

                                        sw.Stop();

                                        long delta         = (xi - lastProcessed);
                                        long rate          = delta * 1000 / (long)sw.Elapsed.TotalMilliseconds;
                                        TimeSpan remaining = TimeSpan.FromSeconds((xLi - xi) / rate);

                                        lastProcessed = xi;

                                        BeginInvoke((MethodInvoker) delegate {
                                            progressDialog.Line1    = Tx.T("dataset.saving.progress", Tx.N(lastProcessed - xFi), Tx.N(xLi - xFi));
                                            progressDialog.Line2    = Tx.T("main.remaining time", remaining.ToTextString());
                                            progressDialog.Progress = (int)((lastProcessed - xFi) * 100 / (xLi - xFi));
                                        });

                                        sw.Restart();
                                    }
                                }

                                sw.Stop();
                            }
                        }

                    if (progressDialog.IsCancelled)
                    {
                        try {
                            File.Delete(filename);
                        } catch {
                            // Nothing to do...
                        }
                    }

                    BeginInvoke((MethodInvoker) delegate {
                        progressDialog.TaskCompleted();
                    });
                }, null);
            }
        }
コード例 #2
0
        private unsafe void OnRunButtonClick(object sender, EventArgs e)
        {
            if (!EstimateTime(false))
            {
                return;
            }

            double start, end;

            double.TryParse(startTextBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out start);
            double.TryParse(endTextBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out end);

            if (estimatedTime.TotalMinutes > 0.5)
            {
                string timeString;
                if (estimatedTime == TimeSpan.MaxValue)
                {
                    timeString = Tx.T("time.infinitely");
                }
                else
                {
                    timeString = estimatedTime.ToTextString();
                }

                if (MessageBox.Show(this, Tx.T("find diffs.errors.interval too big", Tx.N(distance), timeString), Tx.T("main.warning"),
                                    MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                {
                    return;
                }
            }

            long starti = *(long *)&start;
            long endi   = *(long *)&end;

            if (starti > endi)
            {
                long swap = starti;
                starti = endi;
                endi   = swap;
            }
            distance = (endi - starti);

            long currentProcessed = 0, lastProcessed = 0;
            long differencesFound = 0;

            SpinLock syncLock = new SpinLock();

            ProgressDialog progressDialog = new ProgressDialog {
                Text            = Tx.T("find diffs.finding.title"),
                MainInstruction = Tx.T("find diffs.finding.description"),
                Line1           = Tx.T("find diffs.finding.progress", "0", Tx.N(distance)),
                ShowInTaskbar   = false,
                MinimizeBox     = false
            };

            ThreadPool.UnsafeQueueUserWorkItem(delegate {
                BeginInvoke((MethodInvoker) delegate {
                    progressDialog.ShowDialog(this);
                });

                Stopwatch sw = Stopwatch.StartNew();

                Parallel.For(starti, endi, (xi, state) => {
                    double x = *(double *)&xi;

                    bool isFirst        = true;
                    double computedMinY = double.MaxValue, computedMaxY = double.MinValue;

                    foreach (ListView.Item item in listView.Items)
                    {
                        if (item.NumericValueSource == null || item.CheckState != CheckState.Checked)
                        {
                            continue;
                        }

                        double y = item.NumericValueSource.Evaluate(x);

                        if (isFirst)
                        {
                            isFirst      = false;
                            computedMinY = y;
                            computedMaxY = y;
                        }
                        else
                        {
                            if (y > computedMaxY)
                            {
                                computedMaxY = y;
                            }
                            else if (y < computedMinY)
                            {
                                computedMinY = y;
                            }
                        }
                    }

                    bool lockTaken = false;
                    syncLock.Enter(ref lockTaken);

                    if (!isFirst && computedMinY != computedMaxY)
                    {
                        graph.AddDifferenceUnsafe(x, computedMinY, computedMaxY);
                        differencesFound++;
                    }

                    if (sw.ElapsedMilliseconds > 4000)
                    {
                        if (progressDialog.IsCancelled)
                        {
                            if (lockTaken)
                            {
                                syncLock.Exit();
                            }
                            state.Stop();
                            return;
                        }

                        sw.Stop();

                        long delta         = (currentProcessed - lastProcessed);
                        long rate          = delta * 1000 / (long)sw.Elapsed.TotalMilliseconds;
                        TimeSpan remaining = TimeSpan.FromSeconds((distance - currentProcessed) / rate);

                        lastProcessed = currentProcessed;

                        BeginInvoke((MethodInvoker) delegate {
                            progressDialog.Line1    = Tx.T("find diffs.finding.progress", Tx.N(lastProcessed), Tx.N(distance));
                            progressDialog.Line2    = Tx.T("main.remaining time", remaining.ToTextString());
                            progressDialog.Progress = (int)(lastProcessed * 100 / distance);
                        });

                        sw.Restart();
                    }

                    currentProcessed++;

                    if (lockTaken)
                    {
                        syncLock.Exit();
                    }
                });

                sw.Stop();

                BeginInvoke((MethodInvoker) delegate {
                    progressDialog.TaskCompleted();

                    if (!progressDialog.IsCancelled)
                    {
                        MessageBox.Show(this,
                                        Tx.T("find diffs.complete.description",
                                             Tx.N(distance),
                                             Tx.N(differencesFound),
                                             Tx.N(differencesFound * 100 / distance)),
                                        Tx.T("find diffs.complete.title"),
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                });
            }, null);
        }