/* Copyright (c) 2004-2005, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define DKFIGTOO_C 1 #include "dkfig.h" $(trace-include) /* {{{ alphabet, used for string encoding of numbers */ static char alphabet[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }; /* }}} */ $!trace-code #define TRACE_DEBUG 1 /* {{{ trace_bezier_point Debug output for a Bezier point. */ #if TRACE_DEBUG static void trace_bezier_point DK_P1(dk_fig_bezier_point *,bp) { FILE *f; f = dktrace_file(); if(f) { fprintf(f, "value: x=%lg y=%lg\n", (bp->value).x, (bp->value).y); fprintf(f, "lcontrol: x=%lg y=%lg\n", (bp->lcontrol).x, (bp->lcontrol).y); fprintf(f, "rcontrol: x=%lg y=%lg\n", (bp->rcontrol).x, (bp->rcontrol).y); } } #endif /* }}} */ /* {{{ dkfig_tool_invert_y Check whether y is inverted (positive numbers downward). */ int dkfig_tool_invert_y DK_P1(dk_fig_drawing *,d) { int back = 1; if(d) { if(d->cstype == 1) { if((d->opt1) & DKFIG_OPT_USE_CS_SETTING) { back = 0; } } } return back; } /* }}} */ /* {{{ null_point Initialize point. */ static void null_point DK_P1(dk_fig_point *,p) { p->x = p->y = 0.0; } /* }}} */ /* {{{ dkfig_tool_null_arrow Initialize arrowhead structure. */ void dkfig_tool_null_arrow DK_P1(dk_fig_arrow *,a) { if(a) { a->type = 0; a->style = 0; a->thickness = 0.0; a->w = 0.0; a->h = 0.0; a->alpha = 0.0; null_point(&(a->p1)); null_point(&(a->p2)); null_point(&(a->p3)); null_point(&(a->p4)); a->numpoints = 0; a->decrease = 0.0; } } /* }}} */ /* {{{ dkfig_tool_calc_arrow Calculate arrowhead points. */ int dkfig_tool_calc_arrow DK_P6(dk_fig_arrow *,a, dk_fig_point *,p,\ double,phi, dk_fig_fpd *,f, dk_fig_drawing *,d, dk_fig_conversion *,c) { int back = 0; int matherr = 0; double lw, dist, deltal, radius, w, h, sf, pointdec; $? "+ dkfig_tool_calc_arrow" if((a) && (p) && (f) && (d)) { $? ". arguments ok" back = 1; lw = dist = a->alpha = deltal = 0.0; sf = 1.0; a->numpoints = 3; /* lw = (dkma_l_to_double(f->lt) * d->fres) / 80.0; */ lw = dkma_div_double_ok( dkma_mul_double_ok(dkma_l_to_double(f->lt), d->fres, &matherr), (((d->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) ? 160.0 : 80.0), &matherr ); $? ". w=%lg h=%lg", a->w, a->h a->alpha = dkma_atan2((0.5 * a->w), a->h); $? ". alpha = %lg (%lg degree)", a->alpha, (180.0 * a->alpha)/M_PI /* For beveled and rounded arrowheads, the length correction deltal is half of the linewidth. */ deltal = 0.5 * lw; $? ". lw=%lg deltal=%lg", lw, deltal /* For mitered arrowhead we need a trigonometric calculation. */ if(d->ahlj == 0) { deltal = dkma_div_double_ok(deltal, sin(a->alpha), &matherr); $? ". deltal=%lg", deltal } /* pointdec is the "top" corner of the arrowhead, a->decrease is the amount to decrease the line. */ pointdec = a->decrease = deltal; $? ". decrease (1) = %lg pointdec = %lg", a->decrease, pointdec /* Find optimum decrease if no metapost arrowheads are in use and the arrowhead is mitered. */ $? ". base driver number = %d", c->bdnum if(d->ahlj == 0) { if((!((d->opt1) & DKFIG_OPT_METAPOST_ARROWHEADS)) || (c->bdnum > 1)) { double cmin, cmax; cmin = dkma_div_double_ok((0.5 * lw), tan(a->alpha), &matherr); cmax = dkma_mul_double_ok(2.0, pointdec, &matherr); a->decrease = 0.5 * dkma_add_double_ok(cmin, cmax, &matherr); $? ". cmin=%lf cmax=%lf decrease=%lf", cmin, cmax, a->decrease } } $? ". decrease (2) = %lg", a->decrease w = a->w; h = a->h; /* radius = sqrt(0.25*w*w+h*h); */ radius = sqrt( dkma_add_double_ok( (0.25 * dkma_mul_double_ok(w, w, &matherr)), dkma_mul_double_ok(h, h, &matherr), &matherr ) ); /* (a->p2).x = p->x - pointdec * cos(phi); */ (a->p2).x = dkma_sub_double_ok(p->x, (pointdec * cos(phi)), &matherr); /* (a->p2).y = p->y - pointdec * sin(phi); */ if(dkfig_tool_invert_y(d)) { (a->p2).y = dkma_add_double_ok(p->y, (pointdec * sin(phi)), &matherr); } else { (a->p2).y = dkma_sub_double_ok(p->y, (pointdec * sin(phi)), &matherr); } /* p1->x = p2->x + radius * cos(phi + M_PI - a->alpha); */ (a->p1).x = dkma_add_double_ok( (a->p2).x, (radius * cos(phi + M_PI - a->alpha)), &matherr ); if(dkfig_tool_invert_y(d)) { (a->p1).y = dkma_sub_double_ok( (a->p2).y, (radius * sin(phi + M_PI - a->alpha)), &matherr ); } else { (a->p1).y = dkma_add_double_ok( (a->p2).y, (radius * sin(phi + M_PI - a->alpha)), &matherr ); } (a->p3).x = dkma_add_double_ok( (a->p2).x, (radius * cos(phi + M_PI + a->alpha)), &matherr ); if(dkfig_tool_invert_y(d)) { (a->p3).y = dkma_sub_double_ok( (a->p2).y, (radius * sin(phi + M_PI + a->alpha)), &matherr ); } else { (a->p3).y = dkma_add_double_ok( (a->p2).y, (radius * sin(phi + M_PI + a->alpha)), &matherr ); } switch(a->type) { case 2: sf = 0.75; a->numpoints = 4; break; case 3: sf = 1.25; a->numpoints = 4; break; } (a->p4).x = dkma_sub_double_ok( (a->p2).x, (dkma_mul_double_ok(sf, h, &matherr) * cos(phi)), &matherr ); if(dkfig_tool_invert_y(d)) { (a->p4).y = dkma_add_double_ok( (a->p2).y, (dkma_mul_double_ok(sf, h, &matherr) * sin(phi)), &matherr ); } else { (a->p4).y = dkma_sub_double_ok( (a->p2).y, (dkma_mul_double_ok(sf, h, &matherr) * sin(phi)), &matherr ); } } $? ". P1(%lg;%lg) P2(%lg;%lg) P3(%lg;%lg) P4(%lg;%lg)", (a->p1).x, (a->p1).y, (a->p2).x, (a->p2).y, (a->p3).x, (a->p3).y, (a->p4).x, (a->p4).y if(matherr) { back = 0; } $? "- dkfig_tool_calc_arrow %d", back return back; } /* }}} */ /* {{{ dkfig_tool_null_fpd Initialize a pattern-fill-and-draw style info */ void dkfig_tool_null_fpd DK_P1(dk_fig_fpd *,p) { p->cl = 0; /* not closed */ p->ot = -1; /* unknown sub type */ p->ls = 0; /* line style contigous */ p->lt = 0UL; /* no line thickness */ p->pc = -1; /* unknown pen color */ p->fc = -1; /* unknown fill color */ p->af = -1; /* unknown fill style */ p->js = 0; /* linjoin=0 */ p->cs = 0; /* linecap=0 */ p->ar = 0; /* no arrowheads */ p->sv = 0.0; /* style value 0.0 */ p->ps = 0; /* no pen style */ dkfig_tool_null_arrow(&(p->ahf)); /* emtpy arrowhead structures */ dkfig_tool_null_arrow(&(p->ahb)); } /* }}} */ /* {{{ correct_fonth_for_plain_tex Plain TeX does not provide all the font handling instructions we want to use with LaTeX. So we need to apply corrections. */ static void correct_fonth_for_plain_tex DK_P1(dk_fig_fonth_t *,fhptr) { $? "+ correct_fonth_for_plain_text handling(old)=%d font=%d", fhptr->handling, fhptr->fontno if(fhptr->handling == 4) { $? ". correction for plain TeX" fhptr->handling = 3; if((fhptr->oflags) & 4) { $? ". PS font" fhptr->fontno = fhptr->ofontno; if(fhptr->fontno < 0) fhptr->fontno = 0; if(fhptr->fontno > 34) fhptr->fontno = 34; } else { $? ". features" switch(fhptr->ofontno) { case 2: { $? ". bold" fhptr->fontno = 2; } break; case 3: { $? ". italic" fhptr->fontno = 1; } break; case 4: { $? ". sans serif" fhptr->fontno = 16; } break; case 5: { $? ". typewriter" fhptr->fontno = 12; } break; default: { fhptr->fontno = 0; $? ". default/roman" } break; } } } if(fhptr->handling == 5) { fhptr->handling = 2; } $? "- correct_fonth_for_plain_text handling(new)=%d font=%d",fhptr->handling,fhptr->fontno } /* }}} */ /* {{{ dkfig_tool_correct_for_plain_tex Correct all font handling structures if plain TeX is used. */ void dkfig_tool_correct_for_plain_tex DK_P1(dk_fig_conversion *,c) { dk_fig_drawing *d = NULL; dk_fig_fonth_t *fhptr = NULL; dk_fig_object *o = NULL; $? "+ dkfig_tool_correct_for_plain_tex" if(c) { $? ". conversion ok" if((c->opt1) & DKFIG_OPT_OLD_TEX) { $? ". plain TeX" o = c->drwng; if(o) { d = (dk_fig_drawing *)(o->data); if(d) { $? ". drawing ok" if(d->fonthi) { $? ". fonthi ok" dksto_it_reset(d->fonthi); while((fhptr=(dk_fig_fonth_t *)dksto_it_next(d->fonthi)) != NULL) { $? ". yet another fonth" correct_fonth_for_plain_tex(fhptr); } } else { $? "! no fonthi" } } } } else { $? ". LaTeX" } } $? "- dkfig_tool_correct_for_plain_tex" } /* }}} */ /* {{{ dkfig_tool_bb_reset Reset a bounding box information. */ void dkfig_tool_bb_reset DK_P1(dk_fig_bb *,bb) { $? "+ dkfig_tool_bb_reset %s", TR_PTR(bb) if(bb) { bb->xmin = bb->xmax = bb->ymin = bb->ymax = 0.0; bb->flags = 0x00; } $? "- dkfig_tool_bb_reset" } /* }}} */ /* {{{ dkfig_tool_bb_add_x/y Add co-ordinates. */ void dkfig_tool_bb_add_x DK_P2(dk_fig_bb *,bb, double,x) { $? "+ dkfig_tool_bb_add_x %s %lg", TR_PTR(bb),x if(bb) { if(bb->flags & 0x01) { if(x < bb->xmin) bb->xmin = x; if(x > bb->xmax) bb->xmax = x; } else { bb->xmin = bb->xmax = x; bb->flags |= 0x01; } } $? "- dkfig_tool_bb_add_x" } void dkfig_tool_bb_add_y DK_P2(dk_fig_bb *,bb, double,y) { $? "+ dkfig_tool_bb_add_y %s %lg", TR_PTR(bb), y if(bb) { if(bb->flags & 0x02) { if(y < bb->ymin) bb->ymin = y; if(y > bb->ymax) bb->ymax = y; } else { bb->ymin = bb->ymax = y; bb->flags |= 0x02; } } $? "- dkfig_tool_bb_add_y" } /* }}} */ /* {{{ dkfig_tool_bb_get_xmin/xmax/ymin/ymax Get the minimum and maximum values. */ double dkfig_tool_bb_get_xmin DK_P1(dk_fig_bb *,bb) { double back = 0.0; $? "+ dkfig_tool_bb_get_xmin %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x01) { back = bb->xmin; } } $? "- dkfig_tool_bb_get_xmin %lg", back return back; } double dkfig_tool_bb_get_xmax DK_P1(dk_fig_bb *,bb) { double back = 0.0; $? "+ dkfig_tool_bb_get_xmax %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x01) { back = bb->xmax; } } $? "- dkfig_tool_bb_get_xmax %lg", back return back; } double dkfig_tool_bb_get_ymin DK_P1(dk_fig_bb *,bb) { double back = 0.0; $? "+ dkfig_tool_bb_get_ymin %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x02) { back = bb->ymin; } } $? "- dkfig_tool_bb_get_ymin %lg", back return back; } double dkfig_tool_bb_get_ymax DK_P1(dk_fig_bb *,bb) { double back = 0.0; $? "+ dkfig_tool_bb_get_ymax %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x02) { back = bb->ymax; } } $? "_ dkfig_tool_bb_get_ymax %lg", back return back; } /* }}} */ /* {{{ dkfig_tool_bb_have_x/dkfig_tool_bb_have_y Check whether the bounding box data contains information about x- or y-co-ordinates. */ int dkfig_tool_bb_have_x DK_P1(dk_fig_bb *,bb) { int back = 0; $? "+ dkfig_tool_bb_have_x %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x01) back = 1; } $? "- dkfig_tool_bb_have_x %d", back return back; } int dkfig_tool_bb_have_y DK_P1(dk_fig_bb *,bb) { int back = 0; $? "+ dkfig_tool_bb_have_y %s", TR_PTR(bb) if(bb) { if(bb->flags & 0x02) back = 1; } $? "- dkfig_tool_bb_have_y %d", back return back; } /* }}} */ /* {{{ dkfig_tool_bb_add Add a primitives bounding box src to the drawing's bounding box dest. */ void dkfig_tool_bb_add DK_P2(dk_fig_bb *,dest, dk_fig_bb *,src) { $? "+ dkfig_tool_bb_add %s %s", TR_PTR(dest), TR_PTR(src) if(dest && src) { if(src->flags & 0x01) { dkfig_tool_bb_add_x(dest, src->xmin); dkfig_tool_bb_add_x(dest, src->xmax); } if(src->flags & 0x02) { dkfig_tool_bb_add_y(dest, src->ymin); dkfig_tool_bb_add_y(dest, src->ymax); } } $? "- dkfig_tool_bb_add" } /* }}} */ /* {{{ in_range Check whether the value "val" is in the given range. */ static int in_range DK_P3(double,left, double,right, double,val) { int back = 0; double min, max; $? "+ in_range left=%lg right=%lg val=%lg", left, right, val if(left < right) { min = left; max = right; } else { min = right; max = left; } if((min <= val) && (val <= max)) { back = 1; } $? "- in_range %d", back return back; } /* }}} */ /* {{{ add_point_to_bb Add one point to a bounding box. */ static void add_point_to_bb DK_P3(dk_fig_bb *,bb, dk_fig_point *,p, double,lwh) { double v; int matherr; $? "+ add_point_to_bb" matherr = 0; v = dkma_add_double_ok(p->x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(bb, v); } matherr = 0; v = dkma_sub_double_ok(p->x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(bb, v); } matherr = 0; v = dkma_add_double_ok(p->y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(bb, v); } matherr = 0; v = dkma_sub_double_ok(p->y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(bb, v); } $? "- add_point_to_bb" } /* }}} */ /* {{{ add_arrow_to_bb Add arrowhead data to bounding box. */ static void add_arrow_to_bb DK_P3(dk_fig_bb *,bb, dk_fig_arrow *,a, double,lwh) { $? "+ add_arrow_to_bb" add_point_to_bb(bb, &(a->p1), lwh); add_point_to_bb(bb, &(a->p2), lwh); add_point_to_bb(bb, &(a->p3), lwh); if(a->numpoints > 3) { add_point_to_bb(bb, &(a->p4), lwh); } $? "- add_arrow_to_bb" } /* }}} */ /* {{{ Several functions to find arc extrema */ static void top_arc_inside_extrema DK_P1(dk_fig_arc_calc *,arc) { $? "+ top_arc_inside_extrema" if(in_range(arc->aa, arc->ac, 0.0)) { $? ". right" arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(arc->aa, arc->ac, M_PI_2)) { $? ". top" arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(arc->aa, arc->ac, M_PI)) { $? ". left" arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } $? "- top_arc_inside_extrema" } static void top_arc_outside_extrema DK_P1(dk_fig_arc_calc *,arc) { double min, max; $? "+ top_arc_outside_extrema" if(arc->aa < arc->ac) { min = arc->aa; max = arc->ac; } else { min = arc->ac; max = arc->aa; } min += 2.0 * M_PI; if(in_range(min, max, 0.0)) { $? ". right" arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, M_PI_2)) { $? ". top" arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, M_PI)) { $? ". left" arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, (M_PI + M_PI_2))) { $? ". bottom" arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, (2.0 * M_PI))) { $? ". right" arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, (2.0 * M_PI + M_PI_2))) { arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, (3.0 * M_PI))) { arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } $? "- top_arc_outside_extrema" } static void top_arc_extrema DK_P1(dk_fig_arc_calc *,arc) { int inside; $? "+ top_arc_extrema" inside = in_range(arc->aa, arc->ac, arc->ab); if(inside) { top_arc_inside_extrema(arc); if(arc->aa <= arc->ac) { arc->astart = arc->aa; arc->alength = arc->ac - arc->aa; } else { arc->astart = arc->ac; arc->alength = arc->aa - arc->ac; arc->revert = 1; } } else { top_arc_outside_extrema(arc); if(arc->ac <= arc->aa) { arc->astart = arc->aa; arc->alength = 2 * M_PI + arc->ac - arc->aa; } else { arc->astart = arc->ac; arc->alength = 2 * M_PI + arc->aa - arc->ac; arc->revert = 1; } } $? "- top_arc_extrema" } static void bottom_arc_inside_extrema DK_P1(dk_fig_arc_calc *,arc) { if(in_range(arc->aa, arc->ac, (0.0 - M_PI_2))) { $? ". bottom" arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } } static void bottom_arc_outside_extrema DK_P1(dk_fig_arc_calc *,arc) { double min, max; if(arc->aa < arc->ac) { min = arc->aa; max = arc->ac; } else { min = arc->ac; max = arc->aa; } min += 2.0 * M_PI; if(in_range(min, max, (0.0 - M_PI))) { arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, (0.0 - M_PI_2))) { arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, 0.0)) { arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, M_PI_2)) { arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, M_PI)) { arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(min, max, (M_PI + M_PI_2))) { arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(min, max, (2.0 * M_PI))) { arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } } static void bottom_arc_extrema DK_P1(dk_fig_arc_calc *,arc) { int inside; $? "+ bottom_arc_extrema" inside = in_range(arc->aa, arc->ac, arc->ab); if(inside) { bottom_arc_inside_extrema(arc); if(arc->aa <= arc->ac) { arc->astart = arc->aa; arc->alength = arc->ac - arc->aa; } else { arc->astart = arc->ac; arc->alength = arc->aa - arc->ac; arc->revert = 1; } } else { bottom_arc_outside_extrema(arc); if(arc->ac <= arc->aa) { arc->astart = arc->aa; arc->alength = 2.0 * M_PI + arc->ac - arc->aa; } else { arc->astart = arc->ac; arc->alength = 2.0 * M_PI + arc->aa - arc->ac; arc->revert = 1; } } $? "- bottom_arc_extrema" } static void left_side_extrema DK_P3(dk_fig_arc_calc *,arc, double,pos, double,neg) { if(in_range(pos, (neg + 2.0 * M_PI), M_PI_2)) { arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(pos, (neg + 2.0 * M_PI), (0.0 - M_PI_2))) { arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(pos, (neg + 2.0 * M_PI), M_PI)) { arc->xleft = dkma_sub_double_ok(arc->xm, arc->ra, &(arc->mathok)); } } static void right_side_extrema DK_P3(dk_fig_arc_calc *,arc, double,pos, double,neg) { if(in_range(neg,pos,0.0)) { arc->xright = dkma_add_double_ok(arc->xm, arc->ra, &(arc->mathok)); } if(in_range(neg, pos, (0.0 - M_PI_2))) { arc->ybottom = dkma_sub_double_ok(arc->ym, arc->ra, &(arc->mathok)); } if(in_range(neg, pos, M_PI_2)) { arc->ytop = dkma_add_double_ok(arc->ym, arc->ra, &(arc->mathok)); } } static void side_arc_extrema DK_P1(dk_fig_arc_calc *,arc) { double pos, neg; if(arc->aa < 0.0) { neg = arc->aa; pos = arc->ac; } else { neg = arc->ac; pos = arc->aa; } if(arc->ab >= 0.0) { if(arc->ab >= pos) { left_side_extrema(arc, pos, neg); } else { right_side_extrema(arc, pos, neg); } } else { if(arc->ab <= neg) { left_side_extrema(arc, pos, neg); } else { right_side_extrema(arc, pos, neg); } } } /* }}} */ /* {{{ arc_extrema Search for minimum and maximum x and y. */ static void arc_extrema DK_P1(dk_fig_arc_calc *,arc) { if(arc->aa >= 0.0) { if(arc->ac >= 0.0) { top_arc_extrema(arc); } else { side_arc_extrema(arc); if((arc->ab >= arc->aa) || (arc->ab <= arc->ac)) { arc->astart = arc->aa; arc->alength = 2.0 * M_PI + arc->ac - arc->aa; } else { arc->astart = arc->ac; arc->alength = arc->aa - arc->ac; arc->revert = 1; } } } else { if(arc->ac >= 0.0) { $? ". aa<0, ac>0" side_arc_extrema(arc); if((arc->ab >= arc->ac) || (arc->ab <= arc->aa)) { arc->astart = arc->ac; arc->alength = 2.0 * M_PI + arc->aa - arc->ac; arc->revert = 1; $? ". revert" } else { arc->astart = arc->aa; $? ". no revert" arc->alength = arc->ac - arc->aa; } } else { bottom_arc_extrema(arc); } } } /* }}} */ /* {{{ calculate_arc_center Calculate the center point for three given points. On success the arc->mathok component is unchanged. On errors (2 or three equal points or three points on on line) the component is set. */ static void calculate_arc_center DK_P1(dk_fig_arc_calc *,arc) { double t, zaehler, nenner; $? "+ calculate_arc_center" #if NO_MATH_CHECK zaehler = 0.5 * ((arc->xb - arc->xc) * (arc->xc - arc->xa) - (arc->yc - arc->yb) * (arc->yc - arc->ya)); $? ". zaehler(1) = %8.5lg", zaehler nenner = (arc->yb - arc->ya) * (arc->xb - arc->xc) - (arc->yc - arc->yb) * (arc->xa - arc->xb); $? ". nenner(1) = %8.5lg", nenner t = zaehler / nenner; $? ". t(1) = %8.5lg", t arc->xm = 0.5 * (arc->xa + arc->xb) + t * (arc->yb - arc->ya); arc->ym = 0.5 * (arc->ya + arc->yb) + t * (arc->xa - arc->xb); $? ". xm(1) = %8.5lg ym(1) = %8.5lg", arc->xm, arc->ym #endif zaehler = 0.5 * dkma_sub_double_ok( dkma_mul_double_ok( dkma_sub_double_ok(arc->xb, arc->xc, &(arc->mathok)), dkma_sub_double_ok(arc->xc, arc->xa, &(arc->mathok)), &(arc->mathok) ), dkma_mul_double_ok( dkma_sub_double_ok(arc->yc, arc->yb, &(arc->mathok)), dkma_sub_double_ok(arc->yc, arc->ya, &(arc->mathok)), &(arc->mathok) ), &(arc->mathok) ); $? ". zaehler(2) = %8.5lg", zaehler nenner = dkma_sub_double_ok( dkma_mul_double_ok( dkma_sub_double_ok(arc->yb, arc->ya, &(arc->mathok)), dkma_sub_double_ok(arc->xb, arc->xc, &(arc->mathok)), &(arc->mathok) ), dkma_mul_double_ok( dkma_sub_double_ok(arc->yc, arc->yb, &(arc->mathok)), dkma_sub_double_ok(arc->xa, arc->xb, &(arc->mathok)), &(arc->mathok) ), &(arc->mathok) ); $? ". nenner(2) = %8.5lg", nenner t = dkma_div_double_ok(zaehler, nenner, &(arc->mathok)); $? ". t(2) = %8.5lg", t arc->xm = dkma_add_double_ok( (0.5 * dkma_add_double_ok(arc->xa, arc->xb, &(arc->mathok))), dkma_mul_double_ok( t, dkma_sub_double_ok(arc->yb, arc->ya, &(arc->mathok)), &(arc->mathok) ), &(arc->mathok) ); arc->ym = dkma_add_double_ok( (0.5 * dkma_add_double_ok(arc->ya, arc->yb, &(arc->mathok))), dkma_mul_double_ok( t, dkma_sub_double_ok(arc->xa, arc->xb, &(arc->mathok)), &(arc->mathok) ), &(arc->mathok) ); $? ". xm(2) = %8.5lg ym(2) = %8.5lg", arc->xm, arc->ym $? "- calculate_arc_center xm=%8.5lg ym=%8.5lg", arc->xm, arc->ym } /* }}} */ /* {{{ dkfig_tool_arc_calc Calculate xleft, xright, ytop and ybottom for an arc in mathematical coordinates (positive y's go upwards). */ void dkfig_tool_arc_calc DK_P1(dk_fig_arc_calc *,arc) { double detx, dety; $? "+ dkfig_tool_arc_calc" arc->xm = arc->ym = arc->ra = 0.0; arc->aa = arc->ab = arc->ac = 0.0; arc->astart = arc->alength = 0.0; arc->revert = 0; arc->xleft = arc->xright = arc->ytop = arc->ybottom = 0.0; arc->mathok = 0; calculate_arc_center(arc); if(!(arc->mathok)) { $? ". arc center x=%lg y=%lg", arc->xm, arc->ym detx = dkma_sub_double_ok(arc->xm, arc->xa, &(arc->mathok)); dety = dkma_sub_double_ok(arc->ym, arc->ya, &(arc->mathok)); arc->ra = sqrt( dkma_add_double_ok( dkma_mul_double_ok(detx, detx, &(arc->mathok)), dkma_mul_double_ok(dety, dety, &(arc->mathok)), &(arc->mathok) ) ); $? ". arc radius r=%8.5lg", arc->ra arc->aa = dkma_atan2( dkma_sub_double_ok(arc->ya, arc->ym, &(arc->mathok)), dkma_sub_double_ok(arc->xa, arc->xm, &(arc->mathok)) ); $? ". alpha-a = %8.5lg (%8.5lg degree)", arc->aa, 180.0*(arc->aa)/M_PI arc->ab = dkma_atan2( dkma_sub_double_ok(arc->yb, arc->ym, &(arc->mathok)), dkma_sub_double_ok(arc->xb, arc->xm, &(arc->mathok)) ); $? ". alpha-b = %8.5lg (%8.5lg degree)", arc->ab, 180.0*(arc->ab)/M_PI arc->ac = dkma_atan2( dkma_sub_double_ok(arc->yc, arc->ym, &(arc->mathok)), dkma_sub_double_ok(arc->xc, arc->xm, &(arc->mathok)) ); $? ". alpha-c = %8.5lg (%8.5lg degree)", arc->ac, 180.0*(arc->ac)/M_PI arc->xleft = arc->xright = arc->xa; if(arc->xb < arc->xleft) arc->xleft = arc->xb; if(arc->xb > arc->xright) arc->xright = arc->xb; if(arc->xc < arc->xleft) arc->xleft = arc->xc; if(arc->xc > arc->xright) arc->xright = arc->xc; arc->ytop = arc->ybottom = arc->ya; if(arc->yb < arc->ybottom) arc->ybottom = arc->yb; if(arc->yb > arc->ytop) arc->ytop = arc->yb; if(arc->yc < arc->ybottom) arc->ybottom = arc->yc; if(arc->yc > arc->ytop) arc->ytop = arc->yc; arc_extrema(arc); } $? "- dkfig_tool_arc_calc start=%lg lgt=%lg", (180.0 * arc->astart / M_PI), (180.0 * arc->alength / M_PI) } /* }}} */ /* {{{ make_lwh Get half of the linewidth. */ static double make_lwh DK_P2(long,th, dk_fig_drawing *,d) { double back = 0.0; /* 2004/04/12 bug fixed: multiplication fres * was missing */ back = d->fres * dkma_l_to_double(th) / 160.0; if((d->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) { back *= 0.5; } return back; } /* }}} */ /* {{{ dkfig_tool_bb_arc Calculate bounding box information for an arc. */ void dkfig_tool_bb_arc DK_P2(dk_fig_object *,o, dk_fig_drawing *,d) { dk_fig_arc_calc arc; dk_fig_arc *p; double lwh = 0.0, value = 0.0; int mathok = 0; $? "+ dkfig_tool_bb_arc" if(o) { dkfig_tool_bb_reset(&(o->dbb)); } if(o && d) { p = (dk_fig_arc *)(o->data); if(p) { lwh = make_lwh((o->fpd).lt, d); arc.xa = arc.ya = arc.xb = arc.yb = arc.xc = arc.yc = 0.0; arc.xa = dkma_l_to_double(p->x1); arc.ya = 0.0 - dkma_l_to_double(p->y1); arc.xb = dkma_l_to_double(p->x2); arc.yb = 0.0 - dkma_l_to_double(p->y2); arc.xc = dkma_l_to_double(p->x3); arc.yc = 0.0 - dkma_l_to_double(p->y3); dkfig_tool_arc_calc(&arc); if(!(arc.mathok)) { dkfig_tool_bb_add_x(&(o->dbb), arc.xleft); dkfig_tool_bb_add_x(&(o->dbb), arc.xright); dkfig_tool_bb_add_y(&(o->dbb), (0.0 - arc.ytop)); dkfig_tool_bb_add_y(&(o->dbb), (0.0 - arc.ybottom)); mathok = 0; value = dkma_add_double_ok(arc.xright, lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_x(&(o->dbb), value); } mathok = 0; value = dkma_sub_double_ok(arc.xleft, lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_x(&(o->dbb), value); } mathok = 0; value = dkma_add_double_ok((0.0 - arc.ytop), lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_y(&(o->dbb), value); } mathok = 0; value = dkma_sub_double_ok((0.0 - arc.ytop), lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_y(&(o->dbb), value); } mathok = 0; value = dkma_add_double_ok((0.0 - arc.ybottom), lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_y(&(o->dbb), value); } mathok = 0; value = dkma_sub_double_ok((0.0 - arc.ybottom), lwh, &mathok); if(!mathok) { dkfig_tool_bb_add_y(&(o->dbb), value); } } if((o->fpd).ar & 1) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahf), lwh); } if((o->fpd).ar & 2) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahb), lwh); } } $? ". fl=%d xmin=%lg xmax=%lg ymin=%lg ymax=%lg", (int)((o->dbb).flags), (o->dbb).xmin, (o->dbb).xmax, (o->dbb).ymin, (o->dbb).ymax } $? "- dkfig_tool_bb_arc" } /* }}} */ /* {{{ dkfig_tool_bb_polyline Calculate bounding box data for a polyline. */ void dkfig_tool_bb_polyline DK_P2(dk_fig_object *,o, dk_fig_drawing *,d) { dk_fig_polyline *p; double lwh = 0.0; long *lptr = NULL; size_t i = 0; double value; $? "+ dkfig_tool_bb_polyline %s %s", TR_PTR(o), TR_PTR(d) if(o) { dkfig_tool_bb_reset(&(o->dbb)); } if(o && d) { p = (dk_fig_polyline *)(o->data); if(p) { lwh = make_lwh((o->fpd).lt, d); lptr = p->xvalues; if(lptr) { for(i = 0; i < p->npoints; i++) { value = dkma_l_to_double(*(lptr++)); dkfig_tool_bb_add_x(&(o->dbb), value); dkfig_tool_bb_add_x(&(o->dbb), (value-lwh)); dkfig_tool_bb_add_x(&(o->dbb), (value+lwh)); } } lptr = p->yvalues; if(lptr) { for(i = 0; i < p->npoints; i++) { value = dkma_l_to_double(*(lptr++)); dkfig_tool_bb_add_y(&(o->dbb), value); dkfig_tool_bb_add_y(&(o->dbb), (value-lwh)); dkfig_tool_bb_add_y(&(o->dbb), (value+lwh)); } } if((o->fpd).ar & 1) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahf), lwh); } if((o->fpd).ar & 2) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahb), lwh); } } $? ". fl=%d xmin=%lg xmax=%lg ymin=%lg ymax=%lg", (int)((o->dbb).flags), (o->dbb).xmin, (o->dbb).xmax, (o->dbb).ymin, (o->dbb).ymax } $? "- dkfig_tool_bb_polyline" } /* }}} */ /* {{{ dkfig_tool_bb_ellipse Calculate bounding box data for an ellipse. */ void dkfig_tool_bb_ellipse DK_P2(dk_fig_object *,o, dk_fig_drawing *,d) { dk_fig_rot_ellipse e; dk_fig_ellipse *p; double lwh; $? "+ dkfig_tool_bb_ellipse" if(o) { dkfig_tool_bb_reset(&(o->dbb)); } if(o && d) { p = (dk_fig_ellipse *)(o->data); if(p) { lwh = make_lwh((o->fpd).lt, d); e.rx = dkma_l_to_double(p->radiusx); e.ry = dkma_l_to_double(p->radiusy); e.phi0 = p->angle; dkfig_tool_rotated_ellipse(&e); /* centerx, centery */ dkfig_tool_bb_add_x(&(o->dbb), dkma_l_to_double(p->centerx)); dkfig_tool_bb_add_y(&(o->dbb), dkma_l_to_double(p->centery)); dkfig_tool_bb_add_x(&(o->dbb), (dkma_l_to_double(p->centerx) - e.w - lwh)); dkfig_tool_bb_add_y(&(o->dbb), (dkma_l_to_double(p->centery) - e.h - lwh)); dkfig_tool_bb_add_x(&(o->dbb), (dkma_l_to_double(p->centerx) + e.w + lwh)); dkfig_tool_bb_add_y(&(o->dbb), (dkma_l_to_double(p->centery) + e.h + lwh)); } } $? ". fl=%d xmin=%lg xmax=%lg ymin=%lg ymax=%lg", (int)((o->dbb).flags), (o->dbb).xmin, (o->dbb).xmax, (o->dbb).ymin, (o->dbb).ymax $? "- dkfig_tool_bb_ellipse" } /* }}} */ /* {{{ dkfig_tool_bb_spline Calculate bounding box data for a spline. */ void dkfig_tool_bb_spline DK_P2(dk_fig_object *,o, dk_fig_drawing *,d) { int matherr; dk_fig_spline *sptr; dk_fig_bezier_point *bptr; size_t bsegs, cbseg, lindex, rindex; double lwh, value, d0, d1; dk_bspline_t bsp; $? "+ dkfig_tool_bb_spline" lwh = 0.0; if(o) { $? ". object ok" dkfig_tool_bb_reset(&(o->dbb)); if(d) { $? ". d ok" sptr = (dk_fig_spline *)(o->data); if(sptr) { bptr = sptr->bpoints; if(bptr) { $? ". bpoints ok" lwh = make_lwh((o->fpd).lt, d); /* 2004/05/24 bug fixed: npoints was used instead of nbpoints */ bsegs = sptr->nbpoints - 1; switch((o->fpd).st) { case 1: case 3: case 5: bsegs = sptr->nbpoints; break; } for(cbseg = 0; cbseg < bsegs; cbseg++) { lindex = cbseg; rindex = lindex + 1; if(lindex >= sptr->nbpoints) { lindex = lindex - sptr->nbpoints; } if(rindex >= sptr->nbpoints) { rindex = rindex - sptr->nbpoints; } matherr = 0; value = dkma_add_double_ok((bptr[lindex]).value.x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok((bptr[lindex]).value.x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_add_double_ok((bptr[lindex]).value.y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok((bptr[lindex]).value.y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_add_double_ok((bptr[rindex]).value.x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok((bptr[rindex]).value.x, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_add_double_ok((bptr[rindex]).value.y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok((bptr[rindex]).value.y, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } $? ". x0 v=%lg c=%lg", (bptr[lindex]).value.x, (bptr[lindex]).rcontrol.x $? ". x1 c=%lg v=%lg", (bptr[rindex]).lcontrol.x, (bptr[rindex]).value.x d0 = ((bptr[lindex]).rcontrol.x - (bptr[lindex]).value.x) * 3.0; d1 = ((bptr[rindex]).value.x - (bptr[rindex]).lcontrol.x) * 3.0; if(dkbsp_minmax(&bsp, (bptr[lindex]).value.x, d0, (bptr[rindex]).value.x, d1)) { matherr = 0; value = dkma_add_double_ok(bsp.min, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok(bsp.min, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_add_double_ok(bsp.max, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok(bsp.max, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_x(&(o->dbb), value); } } $? ". y0 v=%lg c=%lg", (bptr[lindex]).value.y, (bptr[lindex]).rcontrol.y $? ". y1 c=%lg v=%lg", (bptr[rindex]).lcontrol.y, (bptr[rindex]).value.y d0 = ((bptr[lindex]).rcontrol.y - (bptr[lindex]).value.y) * 3.0; d1 = ((bptr[rindex]).value.y - (bptr[rindex]).lcontrol.y) * 3.0; if(dkbsp_minmax(&bsp, (bptr[lindex]).value.y, d0, (bptr[rindex]).value.y, d1)) { matherr = 0; value = dkma_add_double_ok(bsp.min, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok(bsp.min, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_add_double_ok(bsp.max, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } matherr = 0; value = dkma_sub_double_ok(bsp.max, lwh, &matherr); if(!matherr) { dkfig_tool_bb_add_y(&(o->dbb), value); } } } } if((o->fpd).ar & 1) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahf), lwh); } if((o->fpd).ar & 2) { add_arrow_to_bb(&(o->dbb), &((o->fpd).ahb), lwh); } } } } $? ". fl=%d xmin=%lg xmax=%lg ymin=%lg ymax=%lg", (int)((o->dbb).flags), (o->dbb).xmin, (o->dbb).xmax, (o->dbb).ymin, (o->dbb).ymax $? "- dkfig_tool_bb_spline" } /* }}} */ /* {{{ Distance of point (xp,yp) to a line through (0,0)--(x0,y0). */ double dkfig_tool_dist_pt_to_line0 DK_P4(double,xp,double,yp,double,x0,double,y0) { double back = 0.0; int mathok = 0; double tF, xF, yF, res, deltax, deltay; $? "+ dkfig_tool_dist_pt_to_line0 %lg %lg %lg %lg", xp,yp,x0,y0 tF = dkma_div_double_ok( dkma_add_double_ok( dkma_mul_double_ok(yp,y0,&mathok), dkma_mul_double_ok(xp,x0,&mathok), &mathok ), dkma_add_double_ok( dkma_mul_double_ok(y0,y0,&mathok), dkma_mul_double_ok(x0,x0,&mathok), &mathok ), &mathok ); xF = dkma_mul_double_ok(tF,x0,&mathok); yF = dkma_mul_double_ok(tF,y0,&mathok); deltax = dkma_sub_double_ok(xF,xp,&mathok); deltay = dkma_sub_double_ok(yF,yp,&mathok); res = sqrt( dkma_add_double_ok( dkma_mul_double_ok(deltax,deltax,&mathok), dkma_mul_double_ok(deltay,deltay,&mathok), &mathok ) ); if(!mathok) { back = res; } $? "- dkfig_tool_dist_pt_to_line0 %lg", back return back; } /* }}} */ /* {{{ dkfig_tool_rotated_ellipse Calculate width and height of a rotated ellipse. Inputs are rx, ry and phi0 (in radians). Output is w and h (single width and height from center to top and from center to right). */ void dkfig_tool_rotated_ellipse DK_P1(dk_fig_rot_ellipse *,e) { double th, tw, w, h, xp, yp; int mathok; $? "+ dkfig_tool_rotated_ellipse" if(e) { $? ". rx=%lg ry=%lg phi0=%lg", e->rx, e->ry, e->phi0 mathok = 0; e->h = 0.0; e->w = 0.0; th = dkma_atan2( dkma_mul_double_ok(e->ry, cos(e->phi0), &mathok), dkma_mul_double_ok(e->rx, sin(e->phi0), &mathok) ); $? ". th = %lg (%lg degree)", th, (180.0*th/M_PI) tw = dkma_atan2( (0.0 - dkma_mul_double_ok(e->ry, sin(e->phi0), &mathok)), dkma_mul_double_ok(e->rx, cos(e->phi0), &mathok) ); $? ". tw = %lg (%lg degree)", tw, (180.0*tw/M_PI) if(!mathok) { xp = dkma_mul_double_ok(e->rx, cos(th), &mathok); yp = dkma_mul_double_ok(e->ry, sin(th), &mathok); h = dkfig_tool_dist_pt_to_line0(xp,yp,cos(e->phi0),(0.0-sin(e->phi0))); xp = dkma_mul_double_ok(e->rx, cos(tw), &mathok); yp = dkma_mul_double_ok(e->ry, sin(tw), &mathok); w = dkfig_tool_dist_pt_to_line0( xp,yp,cos(M_PI_2 - e->phi0),sin(M_PI_2 - e->phi0) ); $? ". h=%lg w=%lg", h, w if(!mathok) { e->h = h; e->w = w; } } $? ". w=%lg h=%lg (mathok=%d)", e->w, e->h, mathok } $? "- dkfig_tool_rotated_ellipse" } /* }}} */ /* {{{ null_fig_point Initialize data structure for one Fig point. */ static void null_fig_point DK_P1(dk_fig_point *,pptr) { pptr->x = pptr->y = 0.0; } /* }}} */ /* {{{ null_bezier_point Initialize data structure for one Bezier point. */ static void null_bezier_point DK_P1(dk_fig_bezier_point *,pptr) { null_fig_point(&(pptr->value)); null_fig_point(&(pptr->lcontrol)); null_fig_point(&(pptr->rcontrol)); } /* }}} */ /* {{{ null_all_bezier_points Initialize all Bezier points in a spline object. */ static void null_all_bezier_points DK_P2(dk_fig_bezier_point *,points, size_t,nelem) { size_t i; dk_fig_bezier_point *ptr; i = nelem; ptr = points; while(i--) { null_bezier_point(ptr++); } } /* }}} */ /* {{{ spline_iteration_t Used for Newton iteration scheme. */ typedef struct { dk_fig_object *o; dk_fig_drawing*d; dk_fig_spline *s; unsigned long min; unsigned long max; int end; /* in */ double t; /* in,out */ double value; /* out */ double dvdt; /* out */ double dist; /* in */ double ox; /* in */ double oy; /* in */ /* internals */ double xl; /* in,out */ double xr; /* in,out */ double xlp; /* in,out */ double xrm; /* in,out */ double yl; /* in,out */ double yr; /* in,out */ double ylp; /* in,out */ double yrm; /* in,out */ double tcur; /* in,out */ unsigned long currentstep; /* in,out */ size_t lindex; /* in */ size_t rindex; /* in */ double xcurrent; /* in, out */ double ycurrent; /* in, out */ double dxdt; /* in */ double dydt; /* in */ } spline_iteration_t; /* }}} */ /* {{{ do_calculate For a current value t calculate f(t), df/dt at t and t_next for Newton iteration scheme. */ static int do_calculate DK_P1(spline_iteration_t *,si) { int back = 0; int me = 0; dk_bspline_t bsp; double x, y, dxdt, dydt, sqrv, dx, dy; $? "+ do_calculate" if(dkbsp_for_t(&bsp,si->xl,si->xlp,si->xr,si->xrm,si->tcur)) { x = si->xcurrent = bsp.xvalue; dxdt = si->dxdt = bsp.dxdt; if(dkbsp_for_t(&bsp,si->yl,si->ylp,si->yr,si->yrm,si->tcur)) { y = si->ycurrent = bsp.xvalue; dydt = si->dydt = bsp.dxdt; back = 1; dx = dkma_sub_double_ok(x, si->ox, &me); dy = dkma_sub_double_ok(y, si->oy, &me); $? ". me=%d", me sqrv = sqrt( dkma_add_double_ok( dkma_mul_double_ok(dx, dx, &me), dkma_mul_double_ok(dy, dy, &me), &me ) ); $? ". me=%d", me si->value = dkma_sub_double_ok(sqrv, si->dist, &me); si->dvdt = dkma_div_double_ok( dkma_add_double_ok( dkma_mul_double_ok(dx, dxdt, &me), dkma_mul_double_ok(dy, dydt, &me), &me ), sqrv, &me ); $? ". me=%d", me } } if(me) { back = 0; } $? "- do_caclulate %d value=%lg dvdt=%lg", back, si->value, si->dvdt return back; } /* }}} */ /* {{{ do_iteration Run an iteration to shorten a spline for arrowheads. The Newton iteration scheme is used. */ static int do_iteration DK_P1(spline_iteration_t *,si) { int back = 0; int cc = 0; int me = 0; /* math error */ double oldt, oldvalue; $? "+ do_iteration" oldt = oldvalue = 0.0; si->currentstep = 0UL; cc = 1; while(cc && (!back)) { $? ". loop start currentstep=%lu t=%lg", si->currentstep, si->t /* set lindex, rindex */ if(si->t <= dkma_l_to_double((long)((si->s)->nbpoints) - 1L)) { if(si->t >= 0.0) { si->lindex = (size_t)dkma_double_to_l_ok(floor(si->t), &me); si->rindex = si->lindex + 1; if(si->rindex >= (si->s)->nbpoints) { si->rindex = (si->s)->nbpoints - 1; si->lindex = si->rindex - 1; } } else { cc = 0; $? "! t out of range" } } else { cc = 0; $? "! t out of range" } if(me) { cc = 0; } if(cc) { si->xl = ((si->s)->bpoints)[si->lindex].value.x; si->yl = ((si->s)->bpoints)[si->lindex].value.y; si->xr = ((si->s)->bpoints)[si->rindex].value.x; si->yr = ((si->s)->bpoints)[si->rindex].value.y; si->xlp = ((si->s)->bpoints)[si->lindex].rcontrol.x; si->ylp = ((si->s)->bpoints)[si->lindex].rcontrol.y; si->xrm = ((si->s)->bpoints)[si->rindex].lcontrol.x; si->yrm = ((si->s)->bpoints)[si->rindex].lcontrol.y; si->tcur = si->t - dkma_l_to_double((long)(si->lindex)); $? ". xl=%lg xl+=%lg xr-=%lg xr=%lg", si->xl, si->xlp, si->xrm, si->xr $? ". yl=%lg yl+=%lg yr-=%lg yr=%lg", si->yl, si->ylp, si->yrm, si->yr $? ". t=%lg ( %lu <= %lg <= %lu)", si->tcur, (unsigned long)(si->lindex), si->t, (unsigned long)(si->rindex) if(do_calculate(si)) { $? ". calculation ok, t=%lg f=%lg", si->t, si->value $? ". steps: min=%lu current=%lu max=%lu", si->min, si->currentstep, si->max if(si->currentstep) { $? ". not the first step" if(si->currentstep >= si->min) { $? ". enough steps done" if(fabs(si->value) < DKFIG_EPSILON) { $? ". value in range" if(fabs(dkma_sub_double_ok(si->t, oldt, &me)) < DKFIG_EPSILON) { if(!me) { $? ". t change in range" back = 1; $? ". done! finished! fine!" } } } } } if(!back) { $? ". need to continue, saving current values" oldvalue = si->value; oldt = si->t; } } else { $? "! calculation failed, math error" cc = 0; } } if(si->currentstep >= si->max) { cc = 0; $? "! too many steps, giving up" } if((cc) && (!back)) { si->currentstep += 1UL; si->t = dkma_sub_double_ok( si->t, dkma_div_double_ok(si->value, si->dvdt, &me), &me ); if(me) { cc = 0; } } $? ". loop end" } if(me) { back = 0; } $? "- do_iteration %d", back return back; } /* }}} */ /* {{{ distance Calculate distance between two points. */ static double distance DK_P5(double,x0, double,x1, double,y0, double,y1, int *,me) { double back; double dx, dy; dx = dkma_sub_double_ok(x1,x0,me); dy = dkma_sub_double_ok(y1,y0,me); back = dkma_add_double_ok( dkma_mul_double_ok(dx,dx,me), dkma_mul_double_ok(dy,dy,me), me ); back = sqrt(back); return back; } /* }}} */ /* {{{ correct_bezier_point Setup partial bezier segments on the ends for arrowheads. */ static void correct_bezier_point DK_P4(dk_fig_bezier_point *,bp,\ double,width, int,side, int *,me) { $? "+ correct_bezier_point %s w=%lg, s=%d", TR_PTR(bp), width, side $!trace-code trace_bezier_point(bp); if(side) { $? ". right side in segment, correct left control point" (bp->lcontrol).x = dkma_sub_double_ok( (bp->value).x, dkma_mul_double_ok( width, dkma_sub_double_ok( (bp->value).x, (bp->lcontrol).x, me ), me ), me ); (bp->lcontrol).y = dkma_sub_double_ok( (bp->value).y, dkma_mul_double_ok( width, dkma_sub_double_ok( (bp->value).y, (bp->lcontrol).y, me ), me ), me ); } else { $? ". left side in segment, correct right control point" (bp->rcontrol).x = dkma_add_double_ok( (bp->value).x, dkma_mul_double_ok( width, dkma_sub_double_ok( (bp->rcontrol).x, (bp->value).x, me ), me ), me ); (bp->rcontrol).y = dkma_add_double_ok( (bp->value).y, dkma_mul_double_ok( width, dkma_sub_double_ok( (bp->rcontrol).y, (bp->value).y, me ), me ), me ); } $!trace-code trace_bezier_point(bp); $? "- correct_bezier_point" } /* }}} */ /* {{{ setup_forward_partial Correct Bezier spline segment at the and to apply forward arrowhead. */ static int setup_forward_partial DK_P3(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_spline *,sptr) { int back = 1; int me = 0; double width; $? "+ setup_forward_partial" width = dkma_sub_double_ok( sptr->te, dkma_l_to_double((long)(sptr->normale)), &me ); $? ". width=%lg", width DK_MEMCPY(&(sptr->pe2),&((sptr->bpoints)[sptr->normale]),sizeof(dk_fig_bezier_point)); correct_bezier_point(&(sptr->pe2), width, 0, &me); correct_bezier_point(&(sptr->pe), width, 1, &me); if(me) { back = 0; } $? "- setup_forward_partial %d", back return back; } /* }}} */ /* {{{ setup_backward_partial Correct Bezier spline at beginning to apply arrowhead. */ static int setup_backward_partial DK_P3(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_spline *,sptr) { int back = 1; int me = 0; double width; $? "+ setup_backward_partial" width = dkma_sub_double_ok( dkma_l_to_double((long)(sptr->normals)), sptr->ta, &me ); $? ". width=%lg", width DK_MEMCPY(&(sptr->pa2),&((sptr->bpoints)[sptr->normals]),sizeof(dk_fig_bezier_point)); correct_bezier_point(&(sptr->pa), width, 0, &me); correct_bezier_point(&(sptr->pa2), width, 1, &me); if(me) { back = 0; } $? "- setup_backward_partial %d", back return back; } /* }}} */ /* {{{ setup_one_partial Correct Bezier spline element. This is the very unlikely case that we have only one Bezier spline element which needs correction on both ends. */ static int setup_one_partial DK_P3(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_spline *,sptr) { int back = 1; int me = 0; double width; $? "+ setup_one_partial" width = dkma_sub_double_ok(sptr->te, sptr->ta, &me); DK_MEMCPY(&(sptr->pe2),&(sptr->pa),sizeof(dk_fig_bezier_point)); DK_MEMCPY(&(sptr->pa2),&(sptr->pe),sizeof(dk_fig_bezier_point)); correct_bezier_point(&(sptr->pe2), width, 0, &me); correct_bezier_point(&(sptr->pe), width, 1, &me); correct_bezier_point(&(sptr->pa), width, 0, &me); correct_bezier_point(&(sptr->pa2), width, 1, &me); sptr->flags = sptr->flags | DKFIG_SPLINE_FLAG_ONE_PARTIAL; $? ". width=%lg", width if(me) { back = 0; } $? "- setup_one_partial %d", back return back; } /* }}} */ /* {{{ null_si Initialize data structure for spline end shortening interpolation. */ static void null_si DK_P1(spline_iteration_t *,si) { $? "+ null_si" si->xl = 0.0; si->xr = 0.0; si->xlp = 0.0; si->xrm = 0.0; si->yl = 0.0; si->yr = 0.0; si->ylp = 0.0; si->yrm = 0.0; si->tcur = 0.0; si->currentstep = 0UL; si->lindex = 0; si->rindex = 0; si->xcurrent = 0.0; si->ycurrent = 0.0; $? "- null_si" } /* }}} */ /* {{{ shorten_spline_for_arrowheads Shorten spline ends for arrowheads. */ static int shorten_spline_for_arrowheads DK_P4(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_spline *,sptr, dk_fig_conversion *,c) { int back = 1; int me = 0; int rm = 0; int suc = 0; double dist; spline_iteration_t si; $? "+ shorten_spline_for_arrowheads" si.o = o; si.d = d; si.s = sptr; si.min = d->minitsteps; si.max = d->maxitsteps; if(((o->fpd).ar) & 1) { /* forward arrow */ rm = suc = 0; if((sptr->segs > 0) && (sptr->nbpoints > (sptr->segs + 1))) { null_si(&si); si.end = 1; si.t = dkma_l_to_double(((long)(sptr->nbpoints)) - 1L); si.dist = (o->fpd).ahf.decrease; si.ox = (sptr->bpoints)[sptr->nbpoints - 1].value.x; si.oy = (sptr->bpoints)[sptr->nbpoints - 1].value.y; me = 0; dist = distance( (sptr->bpoints)[sptr->nbpoints - 1 - sptr->segs].value.x, (sptr->bpoints)[sptr->nbpoints - 1].value.x, (sptr->bpoints)[sptr->nbpoints - 1 - sptr->segs].value.y, (sptr->bpoints)[sptr->nbpoints - 1].value.y, &me ); si.t = si.t - dkma_mul_double_ok( dkma_l_to_double((long)(sptr->segs)), dkma_div_double_ok(si.dist, dist, &me), &me ); $? ". attempt 1" if(do_iteration(&si)) { $? ". attempt 1 ok" suc = 1; sptr->te = si.t; (sptr->pe).value.x = si.xcurrent; (sptr->pe).value.y = si.ycurrent; (sptr->pe).lcontrol.x = dkma_sub_double_ok(si.xcurrent, (si.dxdt / 3.0), &me); (sptr->pe).lcontrol.y = dkma_sub_double_ok(si.ycurrent, (si.dydt / 3.0), &me); sptr->normale = (size_t)dkma_double_to_l(floor(si.t)); $? ". pe" $!trace-code trace_bezier_point(&(sptr->pe)); if(sptr->normale >= sptr->nbpoints) { rm = 1; } if(me) { rm = 1; } } else { $? "! attempt 1 failed" /* rm = 1; */ } } if(!suc) { null_si(&si); si.end = 1; si.t = dkma_l_to_double(((long)(sptr->nbpoints)) - 1L); si.dist = (o->fpd).ahf.decrease; si.ox = (sptr->bpoints)[sptr->nbpoints - 1].value.x; si.oy = (sptr->bpoints)[sptr->nbpoints - 1].value.y; me = 0; dist = distance( (sptr->bpoints)[sptr->nbpoints - 2].value.x, (sptr->bpoints)[sptr->nbpoints - 1].value.x, (sptr->bpoints)[sptr->nbpoints - 2].value.y, (sptr->bpoints)[sptr->nbpoints - 1].value.y, &me ); si.t = si.t - dkma_div_double_ok(si.dist, dist, &me); $? ". attempt 2" if(do_iteration(&si)) { suc = 1; $? ". attempt 2 ok" sptr->te = si.t; (sptr->pe).value.x = si.xcurrent; (sptr->pe).value.y = si.ycurrent; (sptr->pe).lcontrol.x = dkma_sub_double_ok(si.xcurrent, (si.dxdt / 3.0), &me); (sptr->pe).lcontrol.y = dkma_sub_double_ok(si.ycurrent, (si.dydt / 3.0), &me); sptr->normale = (size_t)dkma_double_to_l(floor(si.t)); $? ". pe" $!trace-code trace_bezier_point(&(sptr->pe)); if(sptr->normale >= sptr->nbpoints) { rm = 1; } if(me) { rm = 1; } } else { $? "! attempt 2 failed" rm = 1; } } if(rm || (!suc)) { (o->fpd).ar = ((o->fpd).ar & (~1)); $? "! iteration failed, remove forward arrow" /* Warning: forward arrow removed */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 51); } } } if(((o->fpd).ar) & 2) { /* backward arrow */ rm = suc = 0; if((sptr->segs > 0) && (sptr->nbpoints > sptr->segs)) { null_si(&si); si.end = 2; si.t = 0.0; si.dist = (o->fpd).ahb.decrease; si.ox = (sptr->bpoints)[0].value.x; si.oy = (sptr->bpoints)[0].value.y; me = 0; dist = distance( (sptr->bpoints)[0].value.x, (sptr->bpoints)[sptr->segs].value.x, (sptr->bpoints)[0].value.y, (sptr->bpoints)[sptr->segs].value.y, &me ); si.t = dkma_mul_double_ok( dkma_l_to_double((long)(sptr->segs)), dkma_div_double_ok(si.dist, dist, &me), &me ); $? ". attempt 1" if(do_iteration(&si)) { suc = 1; $? ". attempt 1 ok" sptr->ta = si.t; (sptr->pa).value.x = si.xcurrent; (sptr->pa).value.y = si.ycurrent; (sptr->pa).rcontrol.x = dkma_add_double_ok(si.xcurrent, (si.dxdt / 3.0), &me); (sptr->pa).rcontrol.y = dkma_add_double_ok(si.ycurrent, (si.dydt / 3.0), &me); $? ". pa" $!trace-code trace_bezier_point(&(sptr->pa)); sptr->normals = (size_t)dkma_double_to_l(floor(si.t)) + 1; if(me) { rm = 1; } if(((o->fpd).ar) & 1) { $? ". arrows on both ends" if(sptr->te <= sptr->ta) { rm = 1; } } } else { $? "! attempt 1 failed" /* rm = 1; */ } } if(!suc) { null_si(&si); si.end = 2; si.t = 0.0; si.dist = (o->fpd).ahb.decrease; si.ox = (sptr->bpoints)[0].value.x; si.oy = (sptr->bpoints)[0].value.y; me = 0; dist = distance( (sptr->bpoints)[0].value.x, (sptr->bpoints)[1].value.x, (sptr->bpoints)[0].value.y, (sptr->bpoints)[1].value.y, &me ); si.t = dkma_div_double_ok(si.dist, dist, &me); $? ". attempt 2" if(do_iteration(&si)) { suc = 1; $? ". attempt 2 ok" sptr->ta = si.t; (sptr->pa).value.x = si.xcurrent; (sptr->pa).value.y = si.ycurrent; (sptr->pa).rcontrol.x = dkma_add_double_ok(si.xcurrent, (si.dxdt / 3.0), &me); (sptr->pa).rcontrol.y = dkma_add_double_ok(si.ycurrent, (si.dydt / 3.0), &me); $? ". pa" $!trace-code trace_bezier_point(&(sptr->pa)); sptr->normals = (size_t)dkma_double_to_l(floor(si.t)) + 1; if(me) { rm = 1; } if(((o->fpd).ar) & 1) { $? ". arrows on both ends" if(sptr->te <= sptr->ta) { rm = 1; } } } else { rm = 1; $? "! attempt 2 failed" } } if(rm || (!suc)) { (o->fpd).ar = ((o->fpd).ar & (~2)); $? "! iteration failed, remove backward arrow" /* Warning: backward arrow removed */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 52); } } } /* 2004/05/19 end of new code */ switch(((o->fpd).ar) & 3) { case 1: { if(!setup_forward_partial(o,d,sptr)) { back = 0; } } break; case 2: { if(!setup_backward_partial(o,d,sptr)) { back = 0; } } break; case 3: { if(sptr->normals > sptr->normale) { if(!setup_one_partial(o,d,sptr)) { back = 0; } } else { if(!setup_forward_partial(o,d,sptr)) { back = 0; } if(!setup_backward_partial(o,d,sptr)) { back = 0; } } } break; } $? "- shorten_spline_for_arrowheads %d", back return back; } /* }}} */ /* {{{ ddxdtt Get the second derivative for a Bezier segment at t=0 (fl=0). The intention was t=1 for fl!=0 but this does not work. */ static double ddxdtt DK_P6(double,x0, double,xp, double,xm, double,x1, int,fl, int *,me) { double back = 0.0; $? "+ ddxdtt x0=%lg xp=%lg xm=%lg x1=%lg fl=%d", x0, xp, xm, x1, fl #if NO_MATH_CHECK back = xm + x0 - 2.0 * xp; if(fl) { back = back + x1 - x0 + 3.0 * (xp - xm); } back = 6.0 * back; #else back = dkma_sub_double_ok( dkma_add_double_ok(xm, x0, me), dkma_mul_double_ok(2.0, xp, me), me ); if(fl) { back = dkma_add_double_ok( back, dkma_add_double_ok( dkma_sub_double_ok(x1, x0, me), dkma_mul_double_ok( 3.0, dkma_sub_double_ok(xp, xm, me), me ), me ), me ); } back = dkma_mul_double_ok(6.0, back, me); #endif $? "- ddxdtt %lg", back return back; } /* }}} */ /* {{{ dkfig_tool_build_one_spline Final processing for a spline. Shorten spline if necessary for arrowheads. */ int dkfig_tool_build_one_spline DK_P3(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_conversion *,c) { int back = 0; int matherr = 0; /* mathematical error */ size_t noxs; /* number of bezier segments */ size_t cxseg; /* current X-spline segment */ size_t subsegs; /* number of bezier segments per X-spline segment */ size_t lxindex, rxindex, j; /* X-spline point indices */ size_t lbindex, rbindex; /* Bezier point indices */ double deltat; /* scale factor for derivations */ dk_xspline_t xs; /* X-spline calculation structure */ dk_fig_spline *sptr; $? "+ dkfig_tool_build_one_spline" if(o) { $? ". object ok" if(o->data) { $? ". data ok" back = 1; sptr = (dk_fig_spline *)(o->data); sptr->ta = 0.0; sptr->te = dkma_l_to_double((long)(sptr->nbpoints) - 1L); null_bezier_point(&(sptr->pa)); null_bezier_point(&(sptr->pe)); null_bezier_point(&(sptr->pa2)); null_bezier_point(&(sptr->pe2)); null_all_bezier_points(sptr->bpoints, sptr->nbpoints); deltat = 1.0; subsegs = sptr->segs; if(subsegs < 1) { subsegs = 1; } if(subsegs > 1) { deltat = 1.0 / dkma_l_to_double((long)subsegs); } noxs = sptr->npoints; if(!((o->fpd).cl)) { noxs--; } for(cxseg = 0; cxseg < noxs; cxseg++) { /* for all X-spline segments */ lxindex = cxseg; rxindex = lxindex + 1; lbindex = lxindex * subsegs; rbindex = rxindex * subsegs; if(rxindex >= (size_t)(sptr->npoints)) { rxindex = rxindex - (size_t)(sptr->npoints); } if(rbindex >= (size_t)(sptr->nbpoints)) { rbindex = rbindex - (size_t)(sptr->nbpoints); } /* initialize structures */ dkxsp_reset(&xs); dkxsp_set_pos(&xs, cxseg, sptr->npoints, (o->fpd).cl); /* set A */ if((cxseg > 0) || (o->fpd).cl) { if(cxseg > 0) { j = cxseg - 1; } else { j = sptr->npoints - 1; } dkxsp_setA( &xs, (sptr->svalues)[j], dkma_l_to_double((sptr->xvalues)[j]), dkma_l_to_double((sptr->yvalues)[j]) ); } /* set B */ dkxsp_setB( &xs, (sptr->svalues)[cxseg], dkma_l_to_double((sptr->xvalues)[cxseg]), dkma_l_to_double((sptr->yvalues)[cxseg]) ); /* set C */ j = cxseg + 1; if((j < (size_t)(sptr->npoints)) || (o->fpd).cl) { if(j >= (size_t)(sptr->npoints)) { j = j - (size_t)(sptr->npoints); } dkxsp_setC( &xs, (sptr->svalues)[j], dkma_l_to_double((sptr->xvalues)[j]), dkma_l_to_double((sptr->yvalues)[j]) ); } /* set D */ j = cxseg + 2; if((j < (size_t)(sptr->npoints)) || (o->fpd).cl) { if(j >= (size_t)(sptr->npoints)) { j = j - (size_t)(sptr->npoints); } dkxsp_setD( &xs, (sptr->svalues)[j], dkma_l_to_double((sptr->xvalues)[j]), dkma_l_to_double((sptr->yvalues)[j]) ); } /* prepare calculation */ dkxsp_step1(&xs); /* calculate "left" point */ if(dkxsp_step2(&xs, 0.0)) { ((sptr->bpoints)[lbindex]).value.x = xs.x; ((sptr->bpoints)[lbindex]).value.y = xs.y; ((sptr->bpoints)[lbindex]).rcontrol.x = dkma_add_double_ok(xs.x, (deltat * xs.ddtx / 3.0), &matherr); ((sptr->bpoints)[lbindex]).rcontrol.y = dkma_add_double_ok(xs.y, (deltat * xs.ddty / 3.0), &matherr); $? ". %lu value", (unsigned long)lbindex $? ". %lu right", (unsigned long)lbindex } else { matherr = 1; } /* calculate "right" point */ if(dkxsp_step2(&xs, 1.0)) { ((sptr->bpoints)[rbindex]).value.x = xs.x; ((sptr->bpoints)[rbindex]).value.y = xs.y; ((sptr->bpoints)[rbindex]).lcontrol.x = dkma_sub_double_ok(xs.x, (deltat * xs.ddtx / 3.0), &matherr); ((sptr->bpoints)[rbindex]).lcontrol.y = dkma_sub_double_ok(xs.y, (deltat * xs.ddty / 3.0), &matherr); $? ". %lu value", (unsigned long)rbindex $? ". %lu left ", (unsigned long)rbindex } else { matherr = 1; } /* caluculate intermediate points */ for(j = 1; j < subsegs; j++) { if(dkxsp_step2(&xs, (deltat*dkma_l_to_double((long)j)))) { ((sptr->bpoints)[lbindex+j]).value.x = xs.x; ((sptr->bpoints)[lbindex+j]).value.y = xs.y; ((sptr->bpoints)[lbindex+j]).lcontrol.x = dkma_sub_double_ok(xs.x, (deltat * xs.ddtx / 3.0), &matherr); ((sptr->bpoints)[lbindex+j]).lcontrol.y = dkma_sub_double_ok(xs.y, (deltat * xs.ddty / 3.0), &matherr); ((sptr->bpoints)[lbindex+j]).rcontrol.x = dkma_add_double_ok(xs.x, (deltat * xs.ddtx / 3.0), &matherr); ((sptr->bpoints)[lbindex+j]).rcontrol.y = dkma_add_double_ok(xs.y, (deltat * xs.ddty / 3.0), &matherr); $? ". %lu value", (unsigned long)(lbindex+j) $? ". %lu left ", (unsigned long)(lbindex+j) $? ". %lu right", (unsigned long)(lbindex+j) } else { matherr = 1; } } } if((!((o->fpd).cl)) && ((sptr->nbpoints) >= 2)) { double phi, deltax, deltay; if(((o->fpd).ar) & 1) { $? ". for forward arrow" deltay = ((sptr->bpoints)[sptr->nbpoints - 1]).value.y - ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.y; deltax = ((sptr->bpoints)[sptr->nbpoints - 1]).value.x - ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.x; phi = dkma_atan2(deltay, deltax); $? ". (1) deltax=%lg deltay=%lg phi=%lg", deltax, deltay, phi if((fabs(deltay) < DKFIG_EPSILON) && (fabs(deltax) < DKFIG_EPSILON)) { /* deltay = ddxdtt( ((sptr->bpoints)[sptr->nbpoints - 2]).value.y, ((sptr->bpoints)[sptr->nbpoints - 2]).rcontrol.y, ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.y, ((sptr->bpoints)[sptr->nbpoints - 1]).value.y, 1, &matherr ); deltax = ddxdtt( ((sptr->bpoints)[sptr->nbpoints - 2]).value.x, ((sptr->bpoints)[sptr->nbpoints - 2]).rcontrol.x, ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.x, ((sptr->bpoints)[sptr->nbpoints - 1]).value.x, 1, &matherr ); */ deltay = ddxdtt( ((sptr->bpoints)[sptr->nbpoints - 1]).value.y, ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.y, ((sptr->bpoints)[sptr->nbpoints - 2]).rcontrol.y, ((sptr->bpoints)[sptr->nbpoints - 2]).value.y, 0, &matherr ); deltay = 0.0 - deltay; deltax = ddxdtt( ((sptr->bpoints)[sptr->nbpoints - 1]).value.x, ((sptr->bpoints)[sptr->nbpoints - 1]).lcontrol.x, ((sptr->bpoints)[sptr->nbpoints - 2]).rcontrol.x, ((sptr->bpoints)[sptr->nbpoints - 2]).value.x, 0, &matherr ); deltax = 0.0 - deltax; phi = dkma_atan2(deltay, deltax); $? ". (2) deltax=%lg deltay=%lg phi=%lg", deltax, deltay, phi } if(dkfig_tool_invert_y(d)) { phi = 0.0 - phi; } if(!dkfig_tool_calc_arrow( (&(o->fpd).ahf), &(((sptr->bpoints)[sptr->nbpoints - 1]).value), phi, &(o->fpd), d, c ) ) { back = 0; } } if(((o->fpd).ar) & 2) { $? ". for backward arrow" deltay = ((sptr->bpoints)[0]).value.y - ((sptr->bpoints)[0]).rcontrol.y; deltax = ((sptr->bpoints)[0]).value.x - ((sptr->bpoints)[0]).rcontrol.x; phi = dkma_atan2(deltay, deltax); $? ". (1) deltax=%lg deltay=%lg phi=%lg", deltax, deltay, phi if((fabs(deltay) < DKFIG_EPSILON) && (fabs(deltax) < DKFIG_EPSILON)) { deltay = ddxdtt( ((sptr->bpoints)[0]).value.y, ((sptr->bpoints)[0]).rcontrol.y, ((sptr->bpoints)[1]).lcontrol.y, ((sptr->bpoints)[1]).value.y, 0, &matherr ); deltax = ddxdtt( ((sptr->bpoints)[0]).value.x, ((sptr->bpoints)[0]).rcontrol.x, ((sptr->bpoints)[1]).lcontrol.x, ((sptr->bpoints)[1]).value.x, 0, &matherr ); phi = dkma_atan2(deltay, deltax); $? ". (2) deltax=%lg deltay=%lg phi=%lg", deltax, deltay, phi } if(dkfig_tool_invert_y(d)) { phi = 0.0 - phi; } phi = phi + M_PI; if(phi > (2.0 * M_PI)) { phi = phi - 2.0 * M_PI; } if(!dkfig_tool_calc_arrow( (&(o->fpd).ahb), &(((sptr->bpoints)[0]).value), phi, &(o->fpd), d, c ) ) { back = 0; } } } if((o->fpd).ar & 3) { if(!shorten_spline_for_arrowheads(o,d,sptr,c)) { back = 0; } } } } if(matherr) { back = 0; $? "! math problem" } $? "- dkfig_tool_build_one_spline %d", back return back; } /* }}} */ /* {{{ dkfig_tool_null_arc_calc Initialize data structure for arc calculation. */ void dkfig_tool_null_arc_calc DK_P1(dk_fig_arc_calc *,c) { if(c) { DK_MEMRES(c,sizeof(dk_fig_arc_calc)); c->xa = c->ya = c->xb = c->yb = c->xc = c->yc = 0.0; c->xm = c->ym = c->ra = 0.0; c->aa = c->ab = c->ac = 0.0; c->xleft = c->xright = c->ybottom = c->ytop = 0.0; c->astart = c->alength = 0.0; c->revert = 0; c->mathok = 0; } } /* }}} */ /* {{{ dkfig_tool_invert_arc_calc If the Fig co-ordinates system is not swapped (positive y-values downward) we need to apply changes. */ void dkfig_tool_invert_arc_calc DK_P1(dk_fig_arc_calc *,c) { if(c) { c->ya = 0.0 - c->ya; c->yb = 0.0 - c->yb; c->yc = 0.0 - c->yc; c->ym = 0.0 - c->ym; c->ybottom = 0.0 - c->ybottom; c->ytop = 0.0 - c->ytop; } } /* }}} */ /* {{{ dkfig_tool_swap_arrows Swap forward an backward arrow. MetaPost forces us to draw arcs in pos. direction. For arcs specified in clockwise direction in the Fig file we need to swap the arrows to use "fill arrowhead p withcolor..." */ void dkfig_tool_swap_arrows DK_P1(dk_fig_fpd *,fpd) { dk_fig_arrow arrow; int newar; if(fpd) { if((fpd->ar) & 3) { newar = 0; if((fpd->ar) & 1) { newar |= 2; } if((fpd->ar) & 2) { newar |= 1; } DK_MEMCPY(&arrow, &(fpd->ahf), sizeof(dk_fig_arrow)); DK_MEMCPY(&(fpd->ahf), &(fpd->ahb), sizeof(dk_fig_arrow)); DK_MEMCPY(&(fpd->ahb), &arrow, sizeof(dk_fig_arrow)); fpd->ar = newar; } } } /* }}} */ /* {{{ dkfig_tool_arc_complete Final processing for an arc. Corrections for arrowhead if necessary. */ int dkfig_tool_arc_complete DK_P3(dk_fig_object *,o, dk_fig_drawing *,d,\ dk_fig_conversion *,c) { int back = 0; int me = 0; int rm = 0; dk_fig_arc *a; double buf, v; dk_fig_point pnt; $? "+ dkfig_tool_arc_complete" if(o && d) { a = (dk_fig_arc *)(o->data); if(a) { a->lba = a->rba = 0.0; (a->calc).xa = dkma_l_to_double(a->x1); (a->calc).ya = dkma_l_to_double(a->y1); (a->calc).xb = dkma_l_to_double(a->x2); (a->calc).yb = dkma_l_to_double(a->y2); (a->calc).xc = dkma_l_to_double(a->x3); (a->calc).yc = dkma_l_to_double(a->y3); if(dkfig_tool_invert_y(d)) { $? ". invert input" dkfig_tool_invert_arc_calc(&(a->calc)); } dkfig_tool_arc_calc(&(a->calc)); if(dkfig_tool_invert_y(d)) { $? ". invert results" dkfig_tool_invert_arc_calc(&(a->calc)); } if((a->calc).revert) { $? ". swap arrows" dkfig_tool_swap_arrows(&(o->fpd)); buf = (a->calc).xa; (a->calc).xa = (a->calc).xc; (a->calc).xc = buf; buf = (a->calc).ya; (a->calc).ya = (a->calc).yc; (a->calc).yc = buf; buf = (a->calc).aa; (a->calc).aa = (a->calc).ac; (a->calc).ac = buf; } if(!((a->calc).mathok)) { $? ". no math problems" back = 1; pnt.x = (a->calc).xc; pnt.y = (a->calc).yc; if(((o->fpd).ar) & 1) { if(dkfig_tool_calc_arrow(&((o->fpd).ahf),&pnt,((a->calc).ac + M_PI_2),&(o->fpd),d,c)) { rm = 0; v = dkma_sub_double_ok( 1.0, dkma_div_double_ok( dkma_mul_double_ok((o->fpd).ahf.decrease,(o->fpd).ahf.decrease,&rm), dkma_mul_double_ok( 2.0, dkma_mul_double_ok((a->calc).ra,(a->calc).ra,&rm), &rm ), &rm ), &rm ); if(fabs(v) <= 1.0) { a->rba = acos(v); a->rba = fabs(a->rba); } else { rm = 1; } if(rm) { (o->fpd).ar = ((o->fpd).ar & (~1)); /* WARNING: FORWARD ARROWHEAD REMOVED */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 51); } } } else { back = 0; } } pnt.x = (a->calc).xa; pnt.y = (a->calc).ya; if(((o->fpd).ar) & 2) { if(dkfig_tool_calc_arrow(&((o->fpd).ahb),&pnt,((a->calc).aa - M_PI_2),&(o->fpd),d,c)) { rm = 0; v = dkma_sub_double_ok( 1.0, dkma_div_double_ok( dkma_mul_double_ok((o->fpd).ahb.decrease,(o->fpd).ahb.decrease,&rm), dkma_mul_double_ok( 2.0, dkma_mul_double_ok((a->calc).ra,(a->calc).ra,&rm), &rm ), &rm ), &rm ); if(fabs(v) <= 1.0) { a->lba = acos(v); a->lba = fabs(a->lba); } else { rm = 1; } if(rm) { (o->fpd).ar = ((o->fpd).ar & (~2)); /* WARNING: ARROWHEAD BACKWARD REMOVED */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 52); } } } else { back = 0; } } } } } if(me) { back = 0; } $? "- dkfig_tool_arc_complete %d", back return back; } /* }}} */ /* {{{ dkfig_tool_polyline_complete Final processing for a polyline. Line end correction for arrowheads if necessary. */ int dkfig_tool_polyline_complete DK_P3(dk_fig_object *,o,\ dk_fig_drawing *,d, dk_fig_conversion *,c) { int back = 0; int matherr = 0; int rm = 0; double phi = 0.0; double seglength; dk_fig_polyline *p; dk_fig_point pnt; $? "+ dkfig_tool_polyline_complete" if(o && d) { p = (dk_fig_polyline *)(o->data); if(p) { back = 1; null_point(&(p->pa)); null_point(&(p->pe)); if((!((o->fpd).cl)) && ((p->npoints) >= 2)) { if((p->xvalues) && (p->yvalues)) { if(((o->fpd).ar) & 1) { $? ". forward arrow" pnt.x = dkma_l_to_double((p->xvalues)[p->npoints - 1]); pnt.y = dkma_l_to_double((p->yvalues)[p->npoints - 1]); phi = dkma_atan2( dkma_sub_double_ok( dkma_l_to_double((p->yvalues)[p->npoints - 1]), dkma_l_to_double((p->yvalues)[p->npoints - 2]), &matherr ), dkma_sub_double_ok( dkma_l_to_double((p->xvalues)[p->npoints - 1]), dkma_l_to_double((p->xvalues)[p->npoints - 2]), &matherr ) ); if(dkfig_tool_invert_y(d)) { phi = 0.0 - phi; } $? ". phi = %lg", phi if(dkfig_tool_calc_arrow(&((o->fpd).ahf),&pnt,phi,&(o->fpd),d,c)) { rm = 0; seglength = distance( dkma_l_to_double((p->xvalues)[p->npoints - 2]), dkma_l_to_double((p->xvalues)[p->npoints - 1]), dkma_l_to_double((p->yvalues)[p->npoints - 2]), dkma_l_to_double((p->yvalues)[p->npoints - 1]), &matherr ); (p->pe).x = dkma_l_to_double((p->xvalues)[p->npoints - 1]); (p->pe).y = dkma_l_to_double((p->yvalues)[p->npoints - 1]); if(seglength >= (o->fpd).ahf.decrease) { (p->pe).x = dkma_add_double_ok( dkma_l_to_double((p->xvalues)[p->npoints - 2]), dkma_mul_double_ok( dkma_sub_double_ok( dkma_l_to_double((p->xvalues)[p->npoints - 1]), dkma_l_to_double((p->xvalues)[p->npoints - 2]), &matherr ), dkma_sub_double_ok( 1.0, dkma_div_double_ok( (o->fpd).ahf.decrease, seglength, &matherr ), &matherr ), &matherr ), &matherr ); (p->pe).y = dkma_add_double_ok( dkma_l_to_double((p->yvalues)[p->npoints - 2]), dkma_mul_double_ok( dkma_sub_double_ok( dkma_l_to_double((p->yvalues)[p->npoints - 1]), dkma_l_to_double((p->yvalues)[p->npoints - 2]), &matherr ), dkma_sub_double_ok( 1.0, dkma_div_double_ok( (o->fpd).ahf.decrease, seglength, &matherr ), &matherr ), &matherr ), &matherr ); $? ". arrowhead correction" $? ". old end point x=%lg y=%lg", dkma_l_to_double((p->xvalues)[p->npoints - 1]), dkma_l_to_double((p->yvalues)[p->npoints - 1]) $? ". new end point x=%lg y=%lg", (p->pe).x, (p->pe).y } else { rm = 1; } if(rm) { (o->fpd).ar = ((o->fpd).ar & (~1)); /* WARNING: ARROWHEAD FORWARD REMOVED */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 51); } } } else { back = 0; } } if(((o->fpd).ar) & 2) { $? ". backward arrow" pnt.x = dkma_l_to_double((p->xvalues)[0]); pnt.y = dkma_l_to_double((p->yvalues)[0]); phi = dkma_atan2( dkma_sub_double_ok( dkma_l_to_double((p->yvalues)[0]), dkma_l_to_double((p->yvalues)[1]), &matherr ), dkma_sub_double_ok( dkma_l_to_double((p->xvalues)[0]), dkma_l_to_double((p->xvalues)[1]), &matherr ) ); if(dkfig_tool_invert_y(d)) { phi = 0.0 - phi; } $? ". phi = %lg", phi if(dkfig_tool_calc_arrow(&((o->fpd).ahb),&pnt,phi,&(o->fpd),d,c)) { rm = 0; seglength = distance( dkma_l_to_double((p->xvalues)[0]), dkma_l_to_double((p->xvalues)[1]), dkma_l_to_double((p->yvalues)[0]), dkma_l_to_double((p->yvalues)[1]), &matherr ); (p->pa).x = dkma_l_to_double((p->xvalues)[0]); (p->pa).y = dkma_l_to_double((p->yvalues)[0]); if(seglength > (o->fpd).ahb.decrease) { (p->pa).x = dkma_add_double_ok( dkma_l_to_double((p->xvalues)[0]), dkma_mul_double_ok( dkma_sub_double_ok( dkma_l_to_double((p->xvalues)[1]), dkma_l_to_double((p->xvalues)[0]), &matherr ), dkma_div_double_ok( (o->fpd).ahb.decrease, seglength, &matherr ), &matherr ), &matherr ); (p->pa).y = dkma_add_double_ok( dkma_l_to_double((p->yvalues)[0]), dkma_mul_double_ok( dkma_sub_double_ok( dkma_l_to_double((p->yvalues)[1]), dkma_l_to_double((p->yvalues)[0]), &matherr ), dkma_div_double_ok( (o->fpd).ahb.decrease, seglength, &matherr ), &matherr ), &matherr ); $? ". arrowhead correction" $? ". new point x=%lg y=%lg", dkma_l_to_double((p->xvalues)[0]), dkma_l_to_double((p->yvalues)[0]) $? ". new end point x=%lg y=%lg", (p->pa).x, (p->pa).y } else { rm = 1; } if(rm) { (o->fpd).ar = ((o->fpd).ar & (~2)); /* WARNING: ARROWHEAD BACKWARD REMOVED */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 52); } } } else { back = 0; } } } else { back = 0; $? "! internal error, should not happen" } } } } if(matherr) { back = 0; } $? "- dkfig_tool_polyline_complete %d", back return back; } /* }}} */ /* {{{ dkfig_tool_fill_dcc Fill a dcc data by searching the color cell information in the drawing data. */ void dkfig_tool_fill_dcc DK_P3(dk_fig_drawing *,d, dk_fig_dcc *,dcc, int,n) { dk_fig_colorcell *cc; if(dcc) { dcc->red = dcc->green = dcc->blue = 0.0; dcc->ired = dcc->igreen = dcc->iblue = 0; } if(d && dcc) { if(d->ccit) { cc = (dk_fig_colorcell *)dksto_it_find_like(d->ccit, &n, 1); if(cc) { dcc->red = dkma_l_to_double(((long)(cc->r)) & 255L) / 255.0; dcc->green = dkma_l_to_double(((long)(cc->g)) & 255L) / 255.0; dcc->blue = dkma_l_to_double(((long)(cc->b)) & 255L) / 255.0; dcc->ired = (int)((cc->r) & 255L); dcc->igreen = (int)((cc->g) & 255L); dcc->iblue = (int)((cc->b) & 255L); } } } } /* }}} */ /* {{{ dkfig_tool_correct_dcc Correct a dcc color data set using the color number and the area fill. */ void dkfig_tool_correct_dcc DK_P3(dk_fig_dcc *,dcc, int,colno, int,af) { double r, g, b, d; if(dcc) { r = dcc->red; g = dcc->green; b = dcc->blue; if(colno >= 1) { if(af > 0) { if(af <= 19) { d = dkma_l_to_double((long)af); dcc->red = (d * r)/20.0; dcc->green = (d * g)/20.0; dcc->blue = (d * b)/20.0; } else { if(af > 20) { if(af < 40) { d = dkma_l_to_double((long)af) - 20.0; dcc->red = r + ((1.0 - r) * d)/20.0; dcc->green = g + ((1.0 - g) * d)/20.0; dcc->blue = b + ((1.0 - b) * d)/20.0; } else { if(af == 40) { dcc->red = dcc->green = dcc->blue = 1.0; } } } } } else { dcc->red = dcc->green = dcc->blue = 0.0; } } else { if((af>= 0) && (af <= 19)) { d = dkma_l_to_double((long)af); dcc->red = dcc->green = dcc->blue = 1.0 - d/20.0; } else { dcc->red = dcc->green = dcc->blue = 0.0; } } if(dcc->red > 1.0) dcc->red = 1.0; if(dcc->red < 0.0) dcc->red = 0.0; if(dcc->green > 1.0) dcc->green = 1.0; if(dcc->green < 0.0) dcc->green = 0.0; if(dcc->blue > 1.0) dcc->blue = 1.0; if(dcc->blue < 0.0) dcc->blue = 0.0; dcc->ired = (int)dkma_double_to_l(255.0 * dcc->red); dcc->igreen = (int)dkma_double_to_l(255.0 * dcc->green); dcc->iblue = (int)dkma_double_to_l(255.0 * dcc->blue); } } /* }}} */ /* {{{ dkfig_tool_must_fill Check whether or not an object is filled. */ int dkfig_tool_must_fill DK_P2(int, area_fill, unsigned long,opt) { int back = 0; $? "+ dkfig_tool_must_fill %d %lu", area_fill, opt if(area_fill >= 0) { if((area_fill < 41) || (area_fill > 56)) { back = 1; } else { if((area_fill >= 41) && (area_fill <= 62)) { if(!(opt & DKFIG_OPT_FILL_PATTERNS)) { back = 1; } } } } $? "- dkfig_tool_must_fill %d", back return back; } /* }}} */ /* {{{ dkfig_tool_must_pattern Check whether or not we need to draw fill patterns. */ int dkfig_tool_must_pattern DK_P2(int, area_fill, unsigned long,opt) { int back = 0; $? "+ dkfig_tool_must_pattern %d", area_fill if((area_fill >= 41) && (area_fill <= 62)) { if(opt & DKFIG_OPT_FILL_PATTERNS) { back = 1; } } $? "- dkfig_tool_must_pattern %d", back return back; } /* }}} */ /* {{{ dkfig_tool_num_as_string Encode one number as string and write it to output stream. The lgt parameter is the number of characters to produce. */ int dkfig_tool_num_as_string DK_P3(dk_stream_t *,os, unsigned long,no, size_t,lgt) { int back = 0; char buffer[128]; unsigned long num, rest; size_t i, r; $? "+ dkfig_tool_num_as_string %s %lu %lu", TR_PTR(os), no, (unsigned long)lgt if((os) && lgt) { if((lgt < sizeof(buffer)) && (lgt > 0)) { back = 1; DK_MEMRES(buffer,sizeof(buffer)) ; num = no; for(i = 0; i < lgt; i++) { $? ". i = %lu", (unsigned long)i rest = num % 26UL; $? ". num=%lu rest=%lu",num,rest num = num / 26UL; $? ". num=%lu", num r = (size_t)rest; $? ". r=%lu", (unsigned long)r buffer[lgt - 1 - i] = alphabet[r]; } buffer[lgt] = '\0'; back = dkstream_puts(os, buffer); } } $? "- dkfig_tool_num_as_string %d", back return back; } /* }}} */ /* {{{ dkfig_tool_delete_tex_files Remove files used for special text processing. */ void dkfig_tool_delete_tex_files DK_P1(dk_fig_conversion *,c) { if(c) { if(c->texn) { dksf_remove_file(c->texn); } if(c->dvin) { dksf_remove_file(c->dvin); } if(c->psn) { dksf_remove_file(c->psn); } if(c->logn) { dksf_remove_file(c->logn); } if(c->auxn) { dksf_remove_file(c->auxn); } } } /* }}} */ /* {{{ dkfig_tool_init_netpbm Initialize NetPBM library. */ static char program_name[] = { DKFIG_PROGRAM_NAME }; void dkfig_tool_init_netpbm DK_P1(dk_fig_conversion *,c) { #if HAVE_PNM_H int argc; char *argv[2]; $? "+ dkfig_tool_init_netpbm" if(!((c->opt1) & DKFIG_OPT_NETPBM_INITIALIZED)) { $? ". initializing" c->opt1 |= DKFIG_OPT_NETPBM_INITIALIZED; argc = 1; argv[0] = program_name; argv[1] = NULL; pnm_init(&argc, argv); } $? "- dkfig_tool_init_netpbm" #endif } /* }}} */ /* {{{ SCCS ID */ #ifndef LINT static char sccs_id[] = { "@(#)dkfigtoo.ctr 1.94 02/19/08\t(krause) - fig2vect" }; #endif /* }}} */