home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / sel2path / sel2path_adv_dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  16.0 KB  |  387 lines

  1. /*
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This is a plug-in for the GIMP.
  5.  *
  6.  * Plugin to convert a selection to a path.
  7.  *
  8.  * Copyright (C) 1999 Andy Thomas  alt@gimp.org
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  * 
  24.  */
  25.  
  26. /* Change log:-
  27.  * 0.1 First version.
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <types.h>
  33.  
  34.  
  35. #include <libgimp/gimp.h>
  36. #include <libgimp/gimpui.h>
  37.  
  38.  
  39. #define SCALE_WIDTH 100
  40.  
  41. static GSList * adjust_widgets = NULL;
  42.  
  43.  
  44. /* Reset to recommended defaults */
  45. void
  46. reset_adv_dialog (void)
  47. {
  48.   GSList    *list;
  49.   GtkObject *widget;
  50.   gdouble   *value;
  51.   
  52.   for (list = adjust_widgets; list; list = g_slist_next (list))
  53.     {
  54.       widget = GTK_OBJECT (list->data);
  55.       value  = (gdouble *) gtk_object_get_data (widget ,"default_value");
  56.  
  57.       if (GTK_IS_ADJUSTMENT (widget))
  58.     {
  59.       gtk_adjustment_set_value (GTK_ADJUSTMENT (widget), 
  60.                     *value);
  61.     }
  62.       else if (GTK_IS_TOGGLE_BUTTON (widget))
  63.     {
  64.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
  65.                     (gboolean)(*value));
  66.     }
  67.       else
  68.     g_warning ("Internal widget list error");
  69.     }
  70. }
  71.  
  72. gpointer
  73. def_val (gdouble default_value)
  74. {
  75.   gdouble *value = g_new0 (gdouble, 1);
  76.   *value = default_value;
  77.   return (value);
  78. }
  79.  
  80. GtkWidget *
  81. dialog_create_selection_area (SELVALS *sels)
  82. {
  83.   GtkWidget *table;
  84.   GtkWidget *check;
  85.   GtkObject *adj;
  86.   gint       row;
  87.  
  88.   gimp_help_init ();
  89.  
  90.   table = gtk_table_new (20, 3, FALSE);
  91.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  92.   gtk_table_set_col_spacings (GTK_TABLE (table), 2);
  93.   row = 0;
  94.  
  95.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  96.                   "Align Threshold:", SCALE_WIDTH, 0,
  97.                   sels->align_threshold, 
  98.                   0.2, 2.0, 0.1, 0.1, 2,
  99.                   TRUE, 0, 0,
  100.                   "If two endpoints are closer than this,"
  101.                   "they are made to be equal.", NULL);
  102.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  103.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  104.                       &sels->align_threshold);
  105.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  106.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.5));
  107.  
  108.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  109.                   "Corner Always Threshold:", SCALE_WIDTH, 0,
  110.                   sels->corner_always_threshold, 
  111.                   30, 180, 1, 1, 2,
  112.                   TRUE, 0, 0,
  113.                   "If the angle defined by a point and its predecessors " 
  114.                   "and successors is smaller than this, it's a corner, "
  115.                   "even if it's within `corner_surround' pixels of a "
  116.                   "point with a smaller angle.", NULL);
  117.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  118.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  119.                       &sels->corner_always_threshold);
  120.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  121.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (60.0));
  122.  
  123.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  124.                   "Corner Surround:", SCALE_WIDTH, 0,
  125.                   sels->corner_surround, 
  126.                   3, 8, 1, 1, 0,
  127.                   TRUE, 0, 0,
  128.                   "Number of points to consider when determining if a "
  129.                   "point is a corner or not.", NULL);
  130.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  131.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  132.                       &sels->corner_surround);
  133.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  134.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (4.0));
  135.  
  136.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  137.                   "Corner Threshold:", SCALE_WIDTH, 0,
  138.                   sels->corner_threshold, 
  139.                   0, 180, 1, 1, 2,
  140.                   TRUE, 0, 0,
  141.                   "If a point, its predecessors, and its successors "
  142.                   "define an angle smaller than this, it's a corner.", 
  143.                   NULL);
  144.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  145.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  146.                       &sels->corner_threshold);
  147.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  148.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (100.0));
  149.  
  150.  
  151.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  152.                   "Error Threshold:", SCALE_WIDTH, 0,
  153.                   sels->error_threshold, 
  154.                   0.2, 10, 0.1, 0.1, 2,
  155.                   TRUE, 0, 0,
  156.                   "Amount of error at which a fitted spline is "
  157.                   "unacceptable.  If any pixel is further away "
  158.                   "than this from the fitted curve, we try again.", 
  159.                   NULL);
  160.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  161.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  162.                       &sels->error_threshold);
  163.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  164.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.40));
  165.  
  166.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  167.                   "Filter Alternative Surround:", SCALE_WIDTH, 0,
  168.                   sels->filter_alternative_surround, 
  169.                   1, 10, 1, 1, 0,
  170.                   TRUE, 0, 0,
  171.                   "A second number of adjacent points to consider "
  172.                   "when filtering.", NULL);
  173.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  174.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  175.                       &sels->filter_alternative_surround);
  176.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  177.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (1.0));
  178.  
  179.  
  180.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  181.                   "Filter Epsilon:", SCALE_WIDTH, 0,
  182.                   sels->filter_epsilon, 
  183.                   5, 40, 1, 1, 2,
  184.                   TRUE, 0, 0,
  185.                   "If the angles between the vectors produced by "
  186.                   "filter_surround and filter_alternative_surround "
  187.                   "points differ by more than this, use the one from "
  188.                   "filter_alternative_surround.", NULL);
  189.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  190.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  191.                       &sels->filter_epsilon);
  192.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  193.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (10.0));
  194.  
  195.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  196.                   "Filter Iteration Count:", SCALE_WIDTH, 0,
  197.                   sels->filter_iteration_count, 
  198.                   4, 70, 1, 1, 0,
  199.                   TRUE, 0, 0,
  200.                   "Number of times to smooth original data points.  "
  201.                   "Increasing this number dramatically --- to 50 or "
  202.                   "so --- can produce vastly better results.  But if "
  203.                   "any points that ``should'' be corners aren't found, "
  204.                   "the curve goes to hell around that point.", NULL);
  205.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  206.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  207.                       &sels->filter_iteration_count);
  208.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  209.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (4.0));
  210.  
  211.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  212.                   "Filter Percent:", SCALE_WIDTH, 0,
  213.                   sels->filter_percent, 
  214.                   0, 1, 0.05, 0.01, 2,
  215.                   TRUE, 0, 0,
  216.                   "To produce the new point, use the old point plus "
  217.                   "this times the neighbors.", NULL);
  218.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  219.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  220.                       &sels->filter_percent);
  221.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  222.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.33));
  223.  
  224.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  225.                   "Filter Secondary Surround:", SCALE_WIDTH, 0,
  226.                   sels->filter_secondary_surround, 
  227.                   3, 10, 1, 1, 0,
  228.                   TRUE, 0, 0,
  229.                   "Number of adjacent points to consider if "
  230.                   "`filter_surround' points defines a straight line.", 
  231.                   NULL);
  232.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  233.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  234.                       &sels->filter_secondary_surround);
  235.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  236.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (3.0));
  237.  
  238.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  239.                   "Filter Surround:", SCALE_WIDTH, 0,
  240.                   sels->filter_surround, 
  241.                   2, 10, 1, 1, 0,
  242.                   TRUE, 0, 0,
  243.                   "Number of adjacent points to consider when filtering.", 
  244.                   NULL);
  245.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  246.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  247.                       &sels->filter_surround);
  248.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  249.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (2.0));
  250.  
  251.   check = gtk_check_button_new_with_label ("Keep Knees");
  252.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), sels->keep_knees);  
  253.   gtk_table_attach (GTK_TABLE (table), check, 1, 3, row, row + 1,
  254.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  255.   gimp_help_set_help_data (GTK_WIDGET (check), 
  256.                "Says whether or not to remove ``knee'' "
  257.                "points after finding the outline.", NULL);
  258.   gtk_signal_connect (GTK_OBJECT (check), "toggled",
  259.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  260.               &sels->keep_knees);
  261.   gtk_widget_show (check);
  262.   adjust_widgets = g_slist_append (adjust_widgets, check);
  263.   gtk_object_set_data (GTK_OBJECT (check), "default_value", def_val ((gdouble)FALSE));
  264.   row++;
  265.  
  266.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  267.                   "Line Reversion Threshold:", SCALE_WIDTH, 0,
  268.                   sels->line_reversion_threshold, 
  269.                   0.01, 0.2, 0.01, 0.01, 3,
  270.                   TRUE, 0, 0,
  271.                   "If a spline is closer to a straight line than this, "
  272.                   "it remains a straight line, even if it would otherwise "
  273.                   "be changed back to a curve. This is weighted by the "
  274.                   "square of the curve length, to make shorter curves "
  275.                   "more likely to be reverted.", NULL);
  276.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  277.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  278.                       &sels->line_reversion_threshold);
  279.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  280.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.01));
  281.  
  282.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  283.                   "Line Threshold:", SCALE_WIDTH, 0,
  284.                   sels->line_threshold, 
  285.                   0.2, 4, 0.1, 0.01, 2,
  286.                   TRUE, 0, 0,
  287.                   "How many pixels (on the average) a spline can "
  288.                   "diverge from the line determined by its endpoints "
  289.                   "before it is changed to a straight line.", NULL);
  290.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  291.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  292.                       &sels->line_threshold);
  293.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  294.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.5));
  295.  
  296.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  297.                   "Reparametrize Improvement:", SCALE_WIDTH, 0,
  298.                   sels->reparameterize_improvement,
  299.                   0, 1, 0.05, 0.01, 2,
  300.                   TRUE, 0, 0,
  301.                   "If reparameterization doesn't improve the fit by this "
  302.                   "much percent, stop doing it. ""Amount of error at which "
  303.                   "it is pointless to reparameterize.", NULL);
  304.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  305.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  306.                       &sels->reparameterize_improvement);
  307.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  308.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.01));
  309.  
  310.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  311.                   "Reparametrize Threshold:", SCALE_WIDTH, 0,
  312.                   sels->reparameterize_threshold, 
  313.                   1, 50, 0.5, 0.5, 2,
  314.                   TRUE, 0, 0,
  315.                   "Amount of error at which it is pointless to reparameterize.  "
  316.                   "This happens, for example, when we are trying to fit the "
  317.                   "outline of the outside of an `O' with a single spline.  "
  318.                   "The initial fit is not good enough for the Newton-Raphson "
  319.                   "iteration to improve it.  It may be that it would be better "
  320.                   "to detect the cases where we didn't find any corners.", NULL);
  321.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  322.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  323.                       &sels->reparameterize_threshold);
  324.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  325.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (1.0));
  326.  
  327.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  328.                   "Subdivide Search:", SCALE_WIDTH, 0,
  329.                   sels->subdivide_search,
  330.                   0.05, 1, 0.05, 0.01, 2,
  331.                   TRUE, 0, 0,
  332.                   "Percentage of the curve away from the worst point "
  333.                   "to look for a better place to subdivide.", NULL);
  334.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  335.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  336.                       &sels->subdivide_search);
  337.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  338.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.1));
  339.  
  340.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  341.                   "Subdivide Surround:", SCALE_WIDTH, 0,
  342.                   sels->subdivide_surround,
  343.                   2, 10, 1, 1, 0,
  344.                   TRUE, 0, 0,
  345.                   "Number of points to consider when deciding whether "
  346.                   "a given point is a better place to subdivide.", 
  347.                   NULL);
  348.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  349.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  350.                       &sels->subdivide_surround);
  351.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  352.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (4.0));
  353.  
  354.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  355.                   "Subdivide Threshold:", SCALE_WIDTH, 0,
  356.                   sels->subdivide_threshold,
  357.                   0.01, 1, 0.01, 0.01, 2,
  358.                   TRUE, 0, 0,
  359.                   "How many pixels a point can diverge from a straight "
  360.                   "line and still be considered a better place to "
  361.                   "subdivide.", NULL);
  362.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  363.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  364.                       &sels->subdivide_threshold);
  365.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  366.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (0.03));
  367.  
  368.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  369.                   "Tangent Surround:", SCALE_WIDTH, 0,
  370.                   sels->tangent_surround,
  371.                   2, 10, 1, 1, 0,
  372.                   TRUE, 0, 0,
  373.                   "Number of points to look at on either side of a "
  374.                   "point when computing the approximation to the "
  375.                   "tangent at that point.", NULL);
  376.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  377.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  378.                       &sels->tangent_surround);
  379.   adjust_widgets = g_slist_append (adjust_widgets, adj);
  380.   gtk_object_set_data (GTK_OBJECT (adj), "default_value", def_val (3.0));
  381.  
  382.   return GTK_WIDGET(table);
  383. }
  384.  
  385.  
  386.  
  387.