Ejemplo n.º 1
0
ArtSVP *
art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2)
{
  ArtSVP *svp2_mod;
  ArtSVP *svp3, *svp_new;
  ArtSvpWriter *swr;
  int i;

  svp2_mod = (ArtSVP *) svp2; /* get rid of the const for a while */

  /* First invert svp2 to "turn it inside out" */
  for (i = 0; i < svp2_mod->n_segs; i++)
    svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;

  svp3 = art_svp_merge (svp1, svp2_mod);
  swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
  art_svp_intersector (svp3, swr);
  svp_new = art_svp_writer_rewind_reap (swr);
  art_free (svp3); /* shallow free because svp3 contains shared segments */

  /* Flip svp2 back to its original state */
  for (i = 0; i < svp2_mod->n_segs; i++)
    svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;

  return svp_new;
}
Ejemplo n.º 2
0
/**
 * art_svp_diff: Compute the symmetric difference of two sorted vector paths.
 * @svp1: One sorted vector path.
 * @svp2: The other sorted vector path.
 *
 * Computes the symmetric of the two argument svp's. Given two svp's
 * with winding numbers of 0 and 1 everywhere, the resulting winding
 * number will be 1 where either, but not both, of the argument svp's
 * has a winding number 1, 0 otherwise. The result is newly allocated.
 *
 * Currently, this routine has accuracy problems pending the
 * implementation of the new intersector.
 *
 * Return value: The symmetric difference of @svp1 and @svp2.
 **/
ArtSVP *
art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2)
{
#ifdef ART_USE_NEW_INTERSECTOR 
  ArtSVP *svp3, *svp_new;
  ArtSvpWriter *swr;

  svp3 = art_svp_merge (svp1, svp2);
  swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
  art_svp_intersector (svp3, swr);
  svp_new = art_svp_writer_rewind_reap (swr);
  art_free (svp3); /* shallow free because svp3 contains shared segments */

  return svp_new;
#else
  ArtSVP *svp3, *svp4, *svp_new;

  svp3 = art_svp_merge_perturbed (svp1, svp2);
  svp4 = art_svp_uncross (svp3);
  art_svp_free (svp3);

  svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_ODDEVEN);
  art_svp_free (svp4);
  return svp_new;
#endif
}
Ejemplo n.º 3
0
/**
 * art_svp_intersect: Compute the intersection of two sorted vector paths.
 * @svp1: One sorted vector path.
 * @svp2: The other sorted vector path.
 *
 * Computes the intersection of the two argument svp's. Given two
 * svp's with winding numbers of 0 and 1 everywhere, the resulting
 * winding number will be 1 where both of the argument svp's has a
 * winding number 1, 0 otherwise. The result is newly allocated.
 *
 * Currently, this routine has accuracy problems pending the
 * implementation of the new intersector.
 *
 * Return value: The intersection of @svp1 and @svp2.
 **/
ArtSVP *
art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2)
{
#ifdef ART_USE_NEW_INTERSECTOR 
  ArtSVP *svp3, *svp_new;
  ArtSvpWriter *swr;
#ifdef	ROBIN_DEBUG
	dump_svp("art_svp_intersect svp1", svp1);
	dump_svp("art_svp_intersect svp2", svp2);
#endif

  svp3 = art_svp_merge (svp1, svp2);
  swr = art_svp_writer_rewind_new (ART_WIND_RULE_INTERSECT);
  art_svp_intersector (svp3, swr);
  svp_new = art_svp_writer_rewind_reap (swr);
  art_free (svp3); /* shallow free because svp3 contains shared segments */
#ifdef	ROBIN_DEBUG
  dump_svp("art_svp_intersect svp_new", svp_new);
#endif

  return svp_new;
#else
  ArtSVP *svp3, *svp4, *svp_new;

  svp3 = art_svp_merge_perturbed (svp1, svp2);
  svp4 = art_svp_uncross (svp3);
  art_svp_free (svp3);

  svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_INTERSECT);
  art_svp_free (svp4);
  return svp_new;
#endif
}
Ejemplo n.º 4
0
ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule)
{
    ArtSvpWriter * swr = art_svp_writer_rewind_new(rule);

    double zoom = 1.0;
    intbbox_t bbox = get_svp_bbox(svp, zoom);

    art_svp_intersector(svp, swr);
    ArtSVP*result = art_svp_writer_rewind_reap(swr);
    clean_svp(result);
    if(!check_svp(result)) {
	current_svp = result;
	art_report_error(); // might set art_error_in_intersector
    } else {
        msg("<verbose> Comparing polygon renderings of size %dx%d and %dx%d", bbox.width, bbox.height, bbox.width, bbox.height);
        unsigned char*data1 = render_svp(svp, &bbox, zoom, rule);
        unsigned char*data2 = render_svp(result, &bbox, zoom, ART_WIND_RULE_ODDEVEN);
        if(!compare_bitmaps(&bbox, data1, data2)) {
            msg("<verbose> Bad SVP rewinding result- polygons don't match");
            current_svp = result;
            art_report_error(); // might set art_error_in_intersector
        }
        free(data1);
        free(data2);
    }

    if(art_error_in_intersector) {
	msg("<verbose> Error in polygon processing");
	art_svp_free(result);
	art_error_in_intersector=0;
	return 0;
    }
    return result;
}
Ejemplo n.º 5
0
/**
 * art_svp_vpath_stroke: Stroke a vector path.
 * @vpath: #ArtVPath to stroke.
 * @join: Join style.
 * @cap: Cap style.
 * @line_width: Width of stroke.
 * @miter_limit: Miter limit.
 * @flatness: Flatness.
 *
 * Computes an svp representing the stroked outline of @vpath. The
 * width of the stroked line is @line_width.
 *
 * Lines are joined according to the @join rule. Possible values are
 * ART_PATH_STROKE_JOIN_MITER (for mitered joins),
 * ART_PATH_STROKE_JOIN_ROUND (for round joins), and
 * ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join
 * is converted to a bevelled join if the miter would extend to a
 * distance of more than @miter_limit * @line_width from the actual
 * join point.
 *
 * If there are open subpaths, the ends of these subpaths are capped
 * according to the @cap rule. Possible values are
 * ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end
 * point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at
 * the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap,
 * extending half @line_width past the end point).
 *
 * The @flatness parameter controls the accuracy of the rendering. It
 * is most important for determining the number of points to use to
 * approximate circular arcs for round lines and joins. In general, the
 * resulting vector path will be within @flatness pixels of the "ideal"
 * path containing actual circular arcs. I reserve the right to use
 * the @flatness parameter to convert bevelled joins to miters for very
 * small turn angles, as this would reduce the number of points in the
 * resulting outline path.
 *
 * The resulting path is "clean" with respect to self-intersections, i.e.
 * the winding number is 0 or 1 at each point.
 *
 * Return value: Resulting stroked outline in svp format.
 **/
ArtSVP *
art_svp_vpath_stroke (ArtVpath *vpath,
                      ArtPathStrokeJoinType join,
                      ArtPathStrokeCapType cap,
                      double line_width,
                      double miter_limit,
                      double flatness)
{
#ifdef ART_USE_NEW_INTERSECTOR
    ArtVpath *vpath_stroke;
    ArtSVP *svp, *svp2;
    ArtSvpWriter *swr;

    vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
                   line_width, miter_limit, flatness);
#ifdef VERBOSE
    print_ps_vpath (vpath_stroke);
#endif
    svp = art_svp_from_vpath (vpath_stroke);
#ifdef VERBOSE
    print_ps_svp (svp);
#endif
    art_free (vpath_stroke);

    swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
    art_svp_intersector (svp, swr);

    svp2 = art_svp_writer_rewind_reap (swr);
#ifdef VERBOSE
    print_ps_svp (svp2);
#endif
    art_svp_free (svp);
    return svp2;
#else
    ArtVpath *vpath_stroke, *vpath2;
    ArtSVP *svp, *svp2, *svp3;

    vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
                   line_width, miter_limit, flatness);
#ifdef VERBOSE
    print_ps_vpath (vpath_stroke);
#endif
    vpath2 = art_vpath_perturb (vpath_stroke);
#ifdef VERBOSE
    print_ps_vpath (vpath2);
#endif
    art_free (vpath_stroke);
    svp = art_svp_from_vpath (vpath2);
#ifdef VERBOSE
    print_ps_svp (svp);
#endif
    art_free (vpath2);
    svp2 = art_svp_uncross (svp);
#ifdef VERBOSE
    print_ps_svp (svp2);
#endif
    art_svp_free (svp);
    svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_NONZERO);
#ifdef VERBOSE
    print_ps_svp (svp3);
#endif
    art_svp_free (svp2);

    return svp3;
#endif
}
Ejemplo n.º 6
0
static void
test_intersect (void)
{
    ArtVpath vpath[] = {

#if 0
        /* two triangles */
        { ART_MOVETO, 100, 100 },
        { ART_LINETO, 300, 400 },
        { ART_LINETO, 400, 200 },
        { ART_LINETO, 100, 100 },
        { ART_MOVETO, 110, 110 },
        { ART_LINETO, 310, 410 },
        { ART_LINETO, 410, 210 },
        { ART_LINETO, 110, 110 },
#endif

#if 0
        /* a bowtie */
        { ART_MOVETO, 100, 100 },
        { ART_LINETO, 400, 400 },
        { ART_LINETO, 400, 100 },
        { ART_LINETO, 100, 400 },
        { ART_LINETO, 100, 100 },
#endif

#if 1
        /* a square */
        { ART_MOVETO, 100, 100 },
        { ART_LINETO, 100, 400 },
        { ART_LINETO, 400, 400 },
        { ART_LINETO, 400, 100 },
        { ART_LINETO, 100, 100 },
#endif

#if 1
        /* another square */
#define XOFF 10
#define YOFF 10
        { ART_MOVETO, 100 + XOFF, 100 + YOFF },
        { ART_LINETO, 100 + XOFF, 400 + YOFF },
        { ART_LINETO, 400 + XOFF, 400 + YOFF },
        { ART_LINETO, 400 + XOFF, 100 + YOFF },
        { ART_LINETO, 100 + XOFF, 100 + YOFF },
#endif

        { ART_END, 0, 0}
    };
    ArtSVP *svp, *svp2;
    ArtSvpWriter *swr;

    svp = art_svp_from_vpath (vpath);

#define RUN_INTERSECT
#ifdef RUN_INTERSECT
    swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
    art_svp_intersector (svp, swr);

    svp2 = art_svp_writer_rewind_reap (swr);
#endif

#if 0
    output_svp_ppm (svp2);
#else
    print_svp (svp2);
#endif

    art_svp_free (svp);

#ifdef RUN_INTERSECT
    art_svp_free (svp2);
#endif
}