%% options
copyright owner = Dirk Krause
copyright year = 2017-xxxx
SPDX-License-Identifier: BSD-3-Clause
%% header
#ifdef __cplusplus
extern "C" {
#endif
/** Calculate kappa value for angle to use instead of 1/3 for Bezier curves.
@param alpha Arc angle.
@return Kappa value.
*/
double
dk4gratool_kappa_for_angle(double alpha);
/** Initialize points to draw a circle.
@param ptr Address of result array of points.
@param sz Number of elements in array (12 or 24).
@param r Radius.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if ptr is NULL, r is negative or the number of points
is neither 12 nor 24.
*/
int
dk4gratool_points_for_circle(
dk4_gra_point_t *ptr,
size_t sz,
double r,
dk4_er_t *erp
);
/** Initialize points to draw an ellipse.
@param ptr Address of result array of points.
@param sz Number of elements in array (12 or 24).
@param xc Center point x.
@param yc Center point y.
@param rx X radius.
@param ry Y radius.
@param alpha Rotation counterclockwise in radians.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if ptr is NULL, r is negative or the number of points
is neither 12 nor 24.
*/
int
dk4gratool_points_for_ellipse(
dk4_gra_point_t *ptr,
size_t sz,
double xc,
double yc,
double rx,
double ry,
double alpha,
dk4_er_t *erp
);
/** Rotate a point relatively to origin.
@param pt Point whose coordinates must be changed (in/out),
must not be NULL (not checked in function).
@param rot Rotation counterclockwise in radians.
*/
void
dk4gratool_rotate_point(
dk4_gra_point_t *pt,
double rot
);
/** Calculate distance between two points.
@param a Point A.
@param b Point B.
@param erp Error report, may be NULL.
@return Distance between the points.
*/
double
dk4gratool_dist_point_point(
dk4_gra_point_t const *a,
dk4_gra_point_t const *b,
dk4_er_t *erp
);
/** Calculate distance between a track specified by points
A and B and an external point P.
@param a Track endpoint A.
@param b Track endpoint B.
@param p External point P.
@param erp Error report, may be NULL.
@return Distance from point P to track specified by endpoint A, B.
*/
double
dk4gratool_dist_point_track(
dk4_gra_point_t const *a,
dk4_gra_point_t const *b,
dk4_gra_point_t const *p,
dk4_er_t *erp
);
/** Calculate distance between a simple ellipse (in origin, not rotated)
and a point.
This is a poor approximation working best if rx and ry do not
differ too much.
@param rx Ellipse x radius.
@param ry Ellipse y radius.
@param p Point.
@return Non-negative value on success, negative value on error.
*/
double
dk4gratool_dist_point_ellipse_simple(
double rx,
double ry,
dk4_gra_point_t const *p
);
/** Calculate distance between a rotated ellipse and a point.
This is a poor approximation working best if rx and ry do not
differ too much.
@param c Ellipse center point.
@param rx Ellipse x radius.
@param ry Ellipse y radius.
@param rot Ellipse rotation.
@param p Point to calculate distance to.
@param erp Error report, may be NULL.
@return Distance value.
*/
double
dk4gratool_dist_point_ellipse(
dk4_gra_point_t const *c,
double rx,
double ry,
double rot,
dk4_gra_point_t const *p,
dk4_er_t *erp
);
#ifdef __cplusplus
}
#endif
/* vim: set ai sw=4 ts=4 : */
%% module
#include "dk4conf.h"
#if DK4_HAVE_MATH_H
#ifndef MATH_H_INCLUDED
#if DK4_ON_WINDOWS
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES 1
#endif
#endif
#include
#define MATH_H_INCLUDED 1
#endif
#endif
#ifndef DK4MEM_H_INCLUDED
#include "dk4mem.h"
#endif
#ifndef DK4STR8_H_INCLUDED
#include "dk4str8.h"
#endif
#ifndef DK4STRD_H_INCLUDED
#include "dk4strd.h"
#endif
#ifndef DK4GRA_H_INCLUDED
#include "dk4gra.h"
#endif
#ifndef DK4GRAT_H_INCLUDED
#include "dk4grat.h"
#endif
#ifndef GRA_H_INCLUDED
#include "gra.h"
#endif
#ifndef DK4STRM_H_INCLUDED
#include "dk4strm.h"
#endif
#ifndef DK4MAO8D_H_INCLUDED
#include "dk4mao8d.h"
#endif
#ifndef DK4MAO8DNS_H_INCLUDED
#include "dk4mao8dns.h"
#endif
#ifndef DK4MATH_H_INCLUDED
#include "dk4math.h"
#endif
#ifndef DK4ITER_H_INCLUDED
#include "dk4iter.h"
#endif
#ifndef DK4BITSH_H_INCLUDED
#include "dk4bitsh.h"
#endif
#ifndef DK4EDSTM_H_INCLUDED
#include "dk4edstm.h"
#endif
#ifndef DK4FONTC_H_INCLUDED
#include "dk4fontc.h"
#endif
#ifndef DK4UNUSED_H_INCLUDED
#include "dk4unused.h"
#endif
#if DK4_HAVE_ASSERT_H
#ifndef ASSERT_H_INCLUDED
#include
#define ASSERT_H_INCLUDED 1
#endif
#endif
$!trace-include
/** Masks to request a single bit from a dk4_px_t value.
*/
static const dk4_px_t dk4gratool_bit_values[] = {
0x0001, 0x0002, 0x0004, 0x0008,
0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800
};
/** Start of standalone document, part 1.
*/
static const char * const dk4gratool_text1[] = {
$!string-table
% PPPT_FONT_SETUP_BEGIN\n
\\usepackage[T1]{fontenc}\n
\\usepackage{mathptmx}\n
\\usepackage[scaled=.92]{helvet}\n
\\usepackage{courier}\n
% PPPT_FONT_SETUP_END\n
$!end
};
/** Start of standalone document, part 1.
*/
static const char * const dk4gratool_text3[] = {
$!string-table
% PPPT_PACKAGES_BEGIN\n
\\usepackage{textcomp}\n
\\usepackage[intlimits]{amsmath}\n
\\usepackage{fancybox}\n
\\usepackage{graphicx}\n
\\usepackage{xcolor}\n
% PPPT_PACKAGES_END\n
$!end
};
/** Start of standalone document, part 1.
*/
static const char * const dk4gratool_text4[] = {
$!string-table
% PPPT_PDF_INFO_BEGIN\n
% \\usepackage{hyperref}\n
% \\hypersetup{\n
% pdfauthor={Anonymous author},\n
% pdftitle={Document title},\n
% pdfsubject={Document subject},\n
% pdfkeywords={Key,word,another}\n
% }\n
% PPPT_PDF_INFO_END\n
$!end
};
/** Start of standalone document, part 2.
*/
static const char * const dk4gratool_text2[] = {
$!string-table
\\pagestyle{empty}\n
\\setlength{\\voffset}{-1in}\n
\\setlength{\\topmargin}{0bp}\n
\\setlength{\\headheight}{0bp}\n
\\setlength{\\headsep}{0bp}\n
\\setlength{\\topskip}{0bp}\n
\\setlength{\\hoffset}{-1in}\n
\\setlength{\\oddsidemargin}{0bp}\n
\\setlength{\\evensidemargin}{0bp}\n
\\setlength{\\marginparwidth}{0bp}\n
\\setlength{\\marginparsep}{0bp}\n
\\setlength{\\textwidth}{\\paperwidth}\n
\\setlength{\\textheight}{\\paperheight}\n
\\setlength{\\parskip}{0bp}\n
\\setlength{\\parindent}{0bp}\n
\\setlength{\\pdfpagewidth}{\\paperwidth}\n
\\setlength{\\pdfpageheight}{\\paperheight}\n
$!end
};
/** Constant text fragments.
*/
static const char * const dk4gratool_kw[] = {
/* 0 */ "\n",
/* 1 */ "\\setlength{\\paperwidth}{",
/* 2 */ "\\setlength{\\paperheight}{",
/* 3 */ "bp}\n",
/* 4 */ "\\end{document}\n",
/* 5 */ "\\usepackage{pgfcore}\n",
/* 6 */ "\\color[cmyk]{",
/* 7 */ "\\color[gray]{",
/* 8 */ "\\color[rgb]{",
/* 9 */ "}",
/* 10 */ ",",
/* 11 */ "\\newfont{\\PPPTfo",
/* 12 */ "}{",
/* 13 */ "pt}%\n",
/* 14 */ " at ",
/* 15 */ "\\providecommand{\\PPPTfo",
/* 16 */ "}{}%\n",
/* 17 */ "\\renewcommand{\\PPPTfo",
/* 18 */ "}{\\normalfont",
/* 19 */ "\\selectfont}%\n",
/* 20 */ "\\fontfamily{",
/* 21 */ "}",
/* 22 */ "\\ttdefault",
/* 23 */ "\\sfdefault",
/* 24 */ "\\rmdefault",
/* 25 */ "\\fontseries{\\bfdefault}",
/* 26 */ "\\fontseries{\\mddefault}",
/* 27 */ "\\fontshape{\\itdefault}",
/* 28 */ "\\fontshape{\\updefault}",
/* 29 */ "\\fontsize{",
/* 30 */ "pt}{",
/* 31 */ "pt}",
/* 32 */ "\\begin{document}%\n",
/* 33 */ "\\documentclass[12pt]{article}\n",
/* 34 */ "\\documentclass[",
/* 35 */ "pt]{article}\n",
/* 36 */ "% PPPT_FONT_SETUP_BEGIN\n",
/* 37 */ "% PPPT_FONT_SETUP_END\n",
/* 38 */ "% PPPT_PACKAGES_BEGIN\n",
/* 39 */ "% PPPT_PACKAGES_END\n",
NULL
};
/** Alphabet used to translate numbers to uniqe names.
*/
static const char dk4gratool_alphabet[] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
};
dk4_gra_t *
dk4gratool_open(
const dkChar *fn,
size_t w,
size_t h,
int docfl,
dk4_er_t *erp
)
{
dk4_gra_t *back = NULL;
$? "+ dk4gratool_open \"%!ds\"", fn
#if DK4_USE_ASSERT
assert(NULL != fn);
assert(0 < w);
assert(0 < h);
#endif
back = dk4mem_new(dk4_gra_t,1,erp);
if (NULL != back) {
/*
Initialize all components to defaults
*/
dk4cs_context_init(&(back->cscctx), erp);
back->s_pages = NULL;
back->i_pages = NULL;
back->fn = NULL;
back->curpg = NULL;
back->pages = 0;
back->dr = DK4_GRA_DRIVER_PDF;
back->gscp = 0;
back->eor = 1;
back->w = w;
back->h = h;
back->cur_x = 0.0;
back->cur_y = 0.0;
back->patlw = 0.9;
back->le = 0;
back->lec = 0;
back->len = 0;
back->docfl = docfl;
/*
Allocate memory for data copies
*/
if (NULL != fn) {
back->fn = dk4str_dup(fn, erp);
if (NULL == back->fn) {
dk4mem_free(back);
back = NULL;
}
}
}
$? "- dk4gratool_open %d", TR_IPTR(back)
return back;
}
void
dk4gratool_close(
dk4_gra_t *gptr
)
{
$? "+ dk4gratool_close"
#if DK4_USE_ASSERT
assert(NULL != gptr);
#endif
if (NULL != gptr) { $? ". gptr"
if (NULL != gptr->fn) { $? ". fn \"%!ds\"", gptr->fn
dk4mem_free(gptr->fn);
gptr->fn = NULL;
}
dk4mem_free(gptr);
}
$? "- dk4gratool_close"
}
int
dk4gratool_points_for_circle(
dk4_gra_point_t *ptr,
size_t sz,
double r,
dk4_er_t *erp
)
{
double kr; /* Product of kappa and radius */
double krsq2; /* Product of kappa and radius divided by sqrt(2) */
int back = 0;
$? "+ dk4gratool_points_for_circle r=%g", r
#if DK4_USE_ASSERT
assert(NULL != ptr);
assert((24 == sz) || (12 == sz));
assert(0.0 < r);
#endif
if ((NULL == ptr) || ((24 != sz) && (12 != sz)) || (0.0 >= r)) {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
goto finished;
}
ptr[0].x = r;
ptr[0].y = 0.0;
if (24 == sz) {
kr = KAPPA_8 * r;
krsq2 = kr / M_SQRT2;
ptr[ 1].x = r;
ptr[ 1].y = kr;
ptr[ 3].x = r / M_SQRT2;
ptr[ 3].y = r / M_SQRT2;
ptr[ 2].x = ptr[3].x + krsq2;
ptr[ 2].y = ptr[3].y - krsq2;
ptr[ 4].x = ptr[3].x - krsq2;
ptr[ 4].y = ptr[3].y + krsq2;
ptr[ 5].x = kr;
ptr[ 5].y = r;
ptr[ 6].x = 0.0;
ptr[ 6].y = r;
ptr[ 7].x = 0.0 - kr;
ptr[ 7].y = r;
ptr[ 9].x = 0.0 - ptr[3].x;
ptr[ 9].y = ptr[3].y;
ptr[ 8].x = ptr[9].x + krsq2;
ptr[ 8].y = ptr[9].y + krsq2;
ptr[10].x = ptr[9].x - krsq2;
ptr[10].y = ptr[9].y - krsq2;
ptr[11].x = 0.0 - r;
ptr[11].y = kr;
ptr[12].x = 0.0 - r;
ptr[12].y = 0.0;
ptr[13].x = 0.0 - r;
ptr[13].y = 0.0 - kr;
ptr[15].x = ptr[9].x;
ptr[15].y = 0.0 - ptr[3].x;
ptr[14].x = ptr[15].x - krsq2;
ptr[14].y = ptr[15].y + krsq2;
ptr[16].x = ptr[15].x + krsq2;
ptr[16].y = ptr[15].y - krsq2;
ptr[17].x = 0.0 - kr;
ptr[17].y = 0.0 - r;
ptr[18].x = 0.0;
ptr[18].y = 0.0 - r;
ptr[19].x = kr;
ptr[19].y = 0.0 - r;
ptr[21].x = ptr[3].x;
ptr[21].y = 0.0 - ptr[3].y;
ptr[20].x = ptr[21].x - krsq2;
ptr[20].y = ptr[21].y - krsq2;
ptr[22].x = ptr[21].x + krsq2;
ptr[22].y = ptr[21].y + krsq2;
ptr[23].x = r;
ptr[23].y = 0.0 - kr;
}
else {
kr = KAPPA_4 * r;
ptr[ 1].x = r;
ptr[ 1].y = kr;
ptr[ 2].x = kr;
ptr[ 2].y = r;
ptr[ 3].x = 0.0;
ptr[ 3].y = r;
ptr[ 4].x = 0.0 - kr;
ptr[ 4].y = r;
ptr[ 5].x = 0.0 - r;
ptr[ 5].y = kr;
ptr[ 6].x = 0.0 - r;
ptr[ 6].y = 0.0;
ptr[ 7].x = 0.0 - r;
ptr[ 7].y = 0.0 - kr;
ptr[ 8].x = 0.0 - kr;
ptr[ 8].y = 0.0 - r;
ptr[ 9].x = 0.0;
ptr[ 9].y = 0.0 - r;
ptr[10].x = kr;
ptr[10].y = 0.0 - r;
ptr[11].x = r;
ptr[11].y = 0.0 - kr;
}
back = 1;
finished:
$? "- dk4gratool_points_for_circle %d", back
return back;
}
int
dk4gratool_points_for_ellipse(
dk4_gra_point_t *ptr,
size_t sz,
double xc,
double yc,
double rx,
double ry,
double alpha,
dk4_er_t *erp
)
{
double coeff; /* Coefficient ry/rx */
size_t i; /* Index to traverse all points */
int back = 0; /* Result */
#if DK4_USE_ASSERT
assert(NULL != ptr);
assert((24 == sz) || (12 == sz));
assert(0.0 < rx);
assert(0.0 < ry);
#endif
/*
Check arguments
*/
if (
(NULL == ptr) || ((24 != sz) && (12 != sz))
|| (0.0 >= rx) || (0.0 >= ry)
) {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
goto finished;
}
/*
Create circle data
*/
back = dk4gratool_points_for_circle(ptr, sz, rx, erp);
if (0 == back) { goto finished; }
/*
Scale y values for radius ry
*/
coeff = ry / rx;
for (i = 0; i < sz; i++) {
ptr[i].y *= coeff;
}
/* Rotate the points if necessary
*/
if (DK4_GRA_EPSILON_COORDINATES < fabs(alpha)) {
for (i = 0; i < sz; i++) {
dk4gratool_rotate_point(&(ptr[i]), alpha);
}
}
/* Shift to specified center point
*/
for (i = 0; i < sz; i++) {
ptr[i].x += xc;
ptr[i].y += yc;
}
/* Check all coordinates for finite values.
*/
for (i = 0; i < sz; i++) {
#if DK4_HAVE_ISFINITE
if ((!(isfinite(ptr[i].x))) || (!(isfinite(ptr[i].y)))) {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
back = 0;
}
#else
#if DK4_HAVE__FINITE
if ((!(_finite(ptr[i].x))) || (!(_finite(ptr[i].y)))) {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
back = 0;
}
#else
#endif
#endif
}
finished:
return back;
}
void
dk4gratool_rotate_point(dk4_gra_point_t *pt, double rot)
{
double r; /* Point radius */
double a; /* Point angle */
$? "+ dk4gratool_rotate_point %g %g rot=%g", pt->x, pt->y, rot
#if DK4_USE_ASSERT
assert(NULL != pt);
#endif
r = sqrt(pt->x * pt->x + pt->y * pt->y);
a = atan2(pt->y, pt->x);
a += rot;
pt->x = r * cos(a);
pt->y = r * sin(a);
$? "- dk4gratool_rotate_point %g %g", pt->x, pt->y
}
void
dk4gratool_initialize_attributes(
dk4gra_attributes_t *pattr
)
{
$? "+ dk4gratool_initialize_attributes"
#if DK4_USE_ASSERT
assert(NULL != pattr);
#endif
if (NULL != pattr) {
pattr->lc_active = -1;
pattr->lc_requested = DK4_GRA_LC_BUTTED;
pattr->lj_active = -1;
pattr->lj_requested = DK4_GRA_LJ_MITERED;
pattr->ls_active = -1;
pattr->ls_requested = DK4_GRA_LS_SOLID;
pattr->lw_active = -1.0;
pattr->lw_requested = 0.9;
pattr->sv_active = -1.0;
pattr->sv_requested = 4.0;
pattr->ml_active = 10.0;
pattr->ml_requested = 10.0;
pattr->eor_active = -1;
pattr->eor_requested = 0;
dk4mem_reset(&(pattr->col_stroke_active), sizeof(dk4gra_col_t), NULL);
pattr->col_stroke_active.what = DK4_GRA_COL_SPEC_NONE;
dk4mem_cpy(
&(pattr->col_fill_active), &(pattr->col_stroke_active),
sizeof(dk4gra_col_t), NULL
);
dk4mem_cpy(
&(pattr->col_stroke_requested), &(pattr->col_stroke_active),
sizeof(dk4gra_col_t), NULL
);
pattr->col_stroke_requested.what = DK4_GRA_COL_SPEC_GRAY;
pattr->col_stroke_requested.data.gray = 0.0;
dk4mem_cpy(
&(pattr->col_fill_requested), &(pattr->col_stroke_requested),
sizeof(dk4gra_col_t), NULL
);
}
$? "- dk4gratool_initialize_attributes"
}
void
dk4gratool_reset_active_attributes(
dk4gra_attributes_t *pattr
)
{
#if DK4_USE_ASSERT
assert(NULL != pattr);
#endif
pattr->col_stroke_active.what = DK4_GRA_COL_SPEC_NONE;
pattr->col_fill_active.what = DK4_GRA_COL_SPEC_NONE;
pattr->lw_active = -1.0;
pattr->sv_active = -1.0;
pattr->ml_active = -1.0;
pattr->lc_active = -1;
pattr->lj_active = -1;
pattr->ls_active = -1;
pattr->eor_active = -1;
}
void
dk4gratool_set_color_requested(
dk4gra_col_t *pcol,
int colsp,
double c1,
double c2,
double c3,
double c4
)
{
#if DK4_USE_ASSERT
assert(NULL != pcol);
#endif
pcol->what = colsp;
switch (colsp) {
case DK4_GRA_COL_SPEC_CMYK : {
pcol->data.cmyk.c = c1;
pcol->data.cmyk.m = c2;
pcol->data.cmyk.y = c3;
pcol->data.cmyk.k = c4;
} break;
case DK4_GRA_COL_SPEC_RGB : {
pcol->data.rgb.r = c1;
pcol->data.rgb.g = c2;
pcol->data.rgb.b = c3;
} break;
case DK4_GRA_COL_SPEC_GRAY : {
pcol->data.gray = c1;
} break;
}
}
int
dk4gratool_colors_differ(
dk4gra_col_t *p1,
dk4gra_col_t *p2
)
{
int back = 1;
#if DK4_USE_ASSERT
assert(NULL != p1);
assert(NULL != p2);
#endif
if (p1->what == p2->what) {
switch (p1->what) {
case DK4_GRA_COL_SPEC_CMYK : {
back = 0;
if (1.0e-3 < fabs(p1->data.cmyk.c - p2->data.cmyk.c)) {
back = 1;
}
if (1.0e-3 < fabs(p1->data.cmyk.m - p2->data.cmyk.m)) {
back = 1;
}
if (1.0e-3 < fabs(p1->data.cmyk.y - p2->data.cmyk.y)) {
back = 1;
}
if (1.0e-3 < fabs(p1->data.cmyk.k - p2->data.cmyk.k)) {
back = 1;
}
} break;
case DK4_GRA_COL_SPEC_RGB : {
back = 0;
if (1.0e-3 < fabs(p1->data.rgb.r - p2->data.rgb.r)) {
back = 1;
}
if (1.0e-3 < fabs(p1->data.rgb.g - p2->data.rgb.g)) {
back = 1;
}
if (1.0e-3 < fabs(p1->data.rgb.b - p2->data.rgb.b)) {
back = 1;
}
} break;
case DK4_GRA_COL_SPEC_GRAY : {
if (1.0e-3 >= fabs(p1->data.gray - p2->data.gray)) {
back = 0;
}
} break;
}
}
return back;
}
int
dk4gratool_line_style_differs(
int ls_a,
int ls_r,
double sv_a,
double sv_r,
int lwc
)
{
int back = 1;
$? "+ dk4gratool_line_style_differs %d/%g %d/%g %d",ls_a,sv_a,ls_r,sv_r,lwc
if (ls_a == ls_r) {
back = 0;
if (DK4_GRA_LS_SOLID != ls_a) {
if (0 != lwc) {
back = 1;
}
else {
if (1.0e-3 < fabs(sv_a - sv_r)) {
back = 1;
}
}
}
}
$? "- dk4gratool_line_style_differs %d", back
return back;
}
int
dk4gratool_calculate_transformations(
double *dst,
double xl,
double xr,
double yb,
double yt,
double w,
double h,
int kar,
int pos,
dk4_er_t *erp
)
{
double dx; /* Available X space */
double dy; /* Available Y space */
size_t i; /* Traverse transformation values */
int back = 0;
$? "+ dk4gratool_calculate_transformations"
#if DK4_USE_ASSERT
assert(NULL != dst);
assert(xr > xl);
assert(yt > yb);
assert(0.0 < w);
assert(0.0 < h);
#endif
if ((xr <= xl) || (yt <= yb) || (0.0 >= w) || (0.0 >= h)) {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
goto finished;
}
for (i = 0; i < 5; i++) { dst[i] = 0.0; }
dx = xr - xl;
dy = yt - yb;
switch (pos) {
case 1: {
dst[2] = 90.0;
if (0 != kar) {
if ((w * dx) > (h * dy)) { /* Y fully used, space in X */
dx = (h * dy) / w;
dst[0] = xr - (xr - xl - dx) / 2.0;
dst[1] = yb;
}
else { /* X fully used, space in Y */
dy = (w * dx) / h;
dst[0] = xr;
dst[1] = yb + (yt - yb - dy) / 2.0;
}
dst[3] = dy;
dst[4] = dx;
}
else {
dst[0] = xr;
dst[1] = yb;
dst[3] = yt - yb;
dst[4] = xr - xl;
}
} break;
case 2: {
dst[2] = 180.0;
if (0 != kar) {
if ((w * dy) > (h * dx)) { /* X fully used, space in Y */
dy = (h * dx) / w;
dst[0] = xr;
dst[1] = yt - (yt - yb - dy) / 2.0;
}
else {
dx = (w * dy) / h;
dst[0] = xr - (xr - xl - dx) / 2.0;
dst[1] = yt;
}
dst[3] = dx;
dst[4] = dy;
}
else {
dst[0] = xr;
dst[1] = yt;
dst[3] = xr - xl;
dst[4] = yt - yb;
}
} break;
case 3: {
dst[2] = 270.0;
if (0 != kar) {
if ((w * dx) > (h * dy)) { /* Y fully used, space in X */
dx = (h * dy) / w;
dst[0] = xl + (xr - xl - dx) / 2.0;
dst[1] = yt;
}
else { /* X fully used, space in Y */
dy = (w * dx) / h;
dst[0] = xl;
dst[1] = yt - (yt - yb - dy) / 2.0;
}
dst[3] = dy;
dst[4] = dx;
}
else {
dst[0] = xl;
dst[1] = yt;
dst[3] = yt - yb;
dst[4] = xr - xl;
}
} break;
case 4: {
dst[2] = 90.0;
if (0 != kar) {
if ((w * dx) > (h * dy)) { /* Y fully used, space in X */
dx = (h * dy) / w;
dst[0] = xr - (xr - xl - dx) / 2.0;
dst[1] = yt;
}
else { /* X fully used, space in Y */
dy = (w * dx) / h;
dst[0] = xr;
dst[1] = yt - (yt - yb - dy) / 2.0;
}
dst[3] = 0.0 - dy;
dst[4] = dx;
}
else {
dst[0] = xr;
dst[1] = yt;
dst[3] = yb - yt;
dst[4] = xr - xl;
}
} break;
case 5: {
if (0 != kar) {
if ((w * dy) > (h * dx)) { /* X fully used, space in Y */
dy = (h * dx) / w;
dst[0] = xr;
dst[1] = yb + (yt - yb - dy) / 2.0;
}
else { /* Y fully used, space in X */
dx = (w * dy) / h;
dst[0] = xr - (xr - xl - dx) / 2.0;
dst[1] = yb;
}
dst[3] = 0.0 - dx;
dst[4] = dy;
}
else {
dst[0] = xr;
dst[1] = yb;
dst[3] = xl - xr;
dst[4] = yt - yb;
}
} break;
case 6: {
dst[2] = 90.0;
if (0 != kar) {
if ((w * dx) > (h * dy)) { /* Y fully used, space in X */
dx = (h * dy) / w;
dst[0] = xl + (xr - xl - dx) / 2.0;
dst[1] = yb;
}
else { /* X fully used, space in Y */
dy = (w * dx) / h;
dst[0] = xl;
dst[1] = yb + (yt - yb - dy) / 2.0;
}
dst[3] = dy;
dst[4] = 0.0 - dx;
}
else {
dst[0] = xl;
dst[1] = yb;
dst[3] = yt - yb;
dst[4] = xl - xr;
}
} break;
case 7: {
if (0 != kar) {
if ((w * dy) > (h * dx)) { /* X fully used, space in Y */
dy = (h * dx) / w;
dst[0] = xl;
dst[1] = yt - (yt - yb - dy) / 2.0;
}
else { /* Y fully used, space in X */
dx = (w * dy) / h;
dst[0] = xl + (xr - xl - dx) / 2.0;
dst[1] = yt;
}
dst[3] = dx;
dst[4] = 0.0 - dy;
}
else {
dst[0] = xl;
dst[1] = yt;
dst[3] = xr - xl;
dst[4] = yb - yt;
}
} break;
default : { /* 0 */
if (0 != kar) {
if ((w * dy) > (h * dx)) { /* X fully used, space in Y */
dy = (h * dx) / w;
dst[0] = xl;
dst[1] = yb + (yt - yb - dy) / 2.0;
}
else { /* Y fully used, space in X */
dx = (w * dy) / h;
dst[0] = xl + (xr - xl - dx) / 2.0;
dst[1] = yb;
}
dst[3] = dx;
dst[4] = dy;
}
else {
dst[0] = xl;
dst[1] = yb;
dst[3] = (xr - xl);
dst[4] = (yt - yb);
}
} break;
}
back = 1;
for (i = 0; i < 5; i++) {
#if DK4_HAVE_ISFINITE
if (!(isfinite(dst[i]))) {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
back = 0;
}
#else
#if DK4_HAVE__FINITE
if (!(_finite(dst[i]))) {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
back = 0;
}
#endif
#endif
}
finished:
$? "- dk4gratool_calculate_transformations %d", back
return back;
}
void
dk4gratool_stream_string(
dk4_stream_t *os,
const char *str,
int *backptr,
dk4_er_t *erp
)
{
#if DK4_USE_ASSERT
assert(NULL != os);
assert(NULL != str);
#endif
if (0 == dk4stream_write_char_string(os, str, erp)) {
if (NULL != backptr) { *backptr = 0; }
}
}
void
dk4gratool_stream_double(
dk4_stream_t *os,
double val,
int *backptr,
dk4_er_t *erp
)
{
#if DK4_USE_ASSERT
assert(NULL != os);
#endif
if (0 == dk4ma_write_c8_double_no_sci_to_stream(os,val,1.0e-8,0,1,erp)) {
if (NULL != backptr) { *backptr = 0; }
}
}
void
dk4gratool_stream_uint(
dk4_stream_t *os,
dk4_um_t val,
size_t padsz,
int *backptr,
dk4_er_t *erp
)
{
char buf[16*sizeof(dk4_um_t)]; /* Buffer for val as text */
#if DK4_USE_ASSERT
assert(NULL != os);
#endif
if (0 != dk4ma_write_c8_decimal_unsigned(buf,sizeof(buf),val,padsz,erp)) {
dk4gratool_stream_string(os, buf, backptr, erp);
}
else {
if (NULL != backptr) { *backptr = 0; }
}
}
void
dk4gratool_stream_num_alpha(
dk4_stream_t *os,
size_t val,
int *backptr,
dk4_er_t *erp
)
{
size_t kwi; /* Index of number in alphabet */
#if DK4_USE_ASSERT
assert(NULL != os);
#endif
do {
kwi = val % (size_t)26U;
val = val / (size_t)26U;
if (0 == dk4stream_write_byte(os, dk4gratool_alphabet[kwi], erp)) {
if (NULL != backptr) { *backptr = 0; }
}
} while (0 < val);
}
void
dk4gratool_stream_color(
dk4_stream_t *os,
dk4gra_col_t const *col,
int *backptr,
dk4_er_t *erp
)
{
#if DK4_USE_ASSERT
assert(NULL != os);
assert(NULL != col);
#endif
switch (col->what) {
case DK4_GRA_COL_SPEC_CMYK : {
dk4gratool_stream_string(os, dk4gratool_kw[6], backptr, erp);
dk4gratool_stream_double(os, col->data.cmyk.c, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
dk4gratool_stream_double(os, col->data.cmyk.m, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
dk4gratool_stream_double(os, col->data.cmyk.y, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
dk4gratool_stream_double(os, col->data.cmyk.k, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
} break;
case DK4_GRA_COL_SPEC_GRAY : {
dk4gratool_stream_string(os, dk4gratool_kw[7], backptr, erp);
dk4gratool_stream_double(os, col->data.gray, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
} break;
default : { /* RGB */
dk4gratool_stream_string(os, dk4gratool_kw[8], backptr, erp);
dk4gratool_stream_double(os, col->data.rgb.r, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
dk4gratool_stream_double(os, col->data.rgb.g, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
dk4gratool_stream_double(os, col->data.rgb.b, backptr, erp);
dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
} break;
}
}
double
dk4gratool_kappa_for_angle(double alpha)
{
double back;
$? "+ kappa_for_angle %g", alpha
alpha = fabs(alpha);
back = (2.0 * sqrt(8.0 * (1.0 - cos(alpha))) - 4.0 * sin(alpha))
/ (3.0 * alpha * (1.0 - cos(alpha)));
$? "- kappa_for_angle %g", back
return back;
}
dk4_px_t
dk4gratool_bit(
size_t i
)
{
return (dk4gratool_bit_values[i]);
}
void
dk4gratool_put_pixel_value(
dk4_stream_t *strm,
dk4_bit_shift_t *bs,
dk4_px_t pixval,
dk4_px_bit_depth_t bpc,
int *backptr,
dk4_er_t *erp
)
{
int res;
dk4_px_bit_depth_t i;
$? "+ dk4gratool_put_pixel_value %u", (unsigned)pixval
#if DK4_USE_ASSERT
assert(NULL != strm);
assert(NULL != bs);
#endif
for (i = 0; i < bpc; i++) {
res = dk4bit_shift_add(
bs,
((0 != (pixval & (dk4gratool_bit(bpc-1-i)))) ? (1) : (0)),
NULL
);
if (DK4_EDSTM_FINISHED == res) {
res = dk4stream_write_byte(
strm, dk4bit_shift_output(bs, NULL), erp
);
if (0 == res) { $? "! dk4stream_write_byte"
if (NULL != backptr) { *backptr = 0; }
}
}
}
$? "- dk4gratool_put_pixel_value"
}
/** Write paragraph of text to output.
@param ostrm Output stream.
@param strar String array.
@param bptr Address of success variable to reset on error.
@param erp Error report, may be NULL.
*/
static
void
dk4gratool_paragraph_to_stream(
dk4_stream_t *ostrm,
const char * const *strar,
int *bptr,
dk4_er_t *erp
)
{
#if DK4_USE_ASSERT
assert(NULL != ostrm);
assert(NULL != strar);
#endif
if ((NULL != ostrm) && (NULL != strar)) {
while (NULL != *strar) {
dk4gratool_stream_string(ostrm, *(strar++), bptr, erp);
}
}
}
void
dk4gratool_start_standalone_document(
dk4_stream_t *ostrm,
dk4_gra_t *gra,
int pgf,
double dfs,
dk4_sto_t *s_f,
dk4_sto_it_t *i_f,
dk4_sto_t *s_p,
dk4_sto_it_t *i_p,
dk4_sto_t *s_o,
dk4_sto_it_t *i_o,
int *bptr,
dk4_er_t *erp
)
{
dk4_gra_preamble_line_t *pl;
int res;
$? "+ dk4gratool_start_standalone_document"
#if DK4_USE_ASSERT
assert(NULL != ostrm);
assert(NULL != gra);
assert(0.0 < dfs);
#endif
/*
Document class
*/
$? ". dfs = %lg", dfs
if (0.0 < dfs) {
dk4gratool_stream_string(ostrm, dk4gratool_kw[34], bptr, erp);
res = dk4ma_write_c8_double_no_sci_to_stream(
ostrm, dfs, 1.0e-1, 0, 0, erp
);
if (0 == res) { if (NULL != bptr) { *bptr = 0; } }
dk4gratool_stream_string(ostrm, dk4gratool_kw[35], bptr, erp);
}
else {
dk4gratool_stream_string(ostrm, dk4gratool_kw[33], bptr, erp);
}
/*
Font setup
*/
if ((NULL != s_f) && (NULL != i_f)) {
dk4gratool_stream_string(ostrm, dk4gratool_kw[36], bptr, erp);
dk4sto_it_reset(i_f);
do {
pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_f);
if (NULL != pl) {
dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
}
} while (NULL != pl);
dk4gratool_stream_string(ostrm, dk4gratool_kw[37], bptr, erp);
}
else {
dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text1, bptr, erp);
}
/*
Additional packages
*/
if ((NULL != s_p) && (NULL != i_p)) {
dk4gratool_stream_string(ostrm, dk4gratool_kw[38], bptr, erp);
dk4sto_it_reset(i_p);
do {
pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_p);
if (NULL != pl) {
dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
}
} while (NULL != pl);
dk4gratool_stream_string(ostrm, dk4gratool_kw[39], bptr, erp);
}
else {
dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text3, bptr, erp);
}
dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text4, bptr, erp);
/*
/setlength{/paperwidth{xxxbp}
*/
dk4gratool_stream_string(ostrm, dk4gratool_kw[1], bptr, erp);
dk4gratool_stream_uint(ostrm, gra->w, 0, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[3], bptr, erp);
/*
/setlength{/paperheight{xxxbp}
*/
dk4gratool_stream_string(ostrm, dk4gratool_kw[2], bptr, erp);
dk4gratool_stream_uint(ostrm, gra->h, 0, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[3], bptr, erp);
/*
/usepackage{pgfcore}
*/
if (0 != pgf) {
dk4gratool_stream_string(ostrm, dk4gratool_kw[5], bptr, erp);
}
/*
Instructions for setup
*/
dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text2, bptr, erp);
/*
Additional other setup lines
*/
if ((NULL != s_o) && (NULL != i_o)) {
dk4sto_it_reset(i_o);
do {
pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_o);
if (NULL != pl) {
dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
}
} while (NULL != pl);
}
/*
/begin{document}
*/
dk4gratool_stream_string(ostrm, dk4gratool_kw[32], bptr, erp);
$? "- dk4gratool_start_standalone_document"
}
void
dk4gratool_end_standalone_document(
dk4_stream_t *ostrm,
int *bptr,
dk4_er_t *erp
)
{
#if DK4_USE_ASSERT
assert(NULL != ostrm);
#endif
dk4gratool_stream_string(ostrm, dk4gratool_kw[4], bptr, erp);
}
/** Write definition for one font from collector to output stream.
@param ostrm Output stream.
@param foi Font item to write.
@param bptr Address of success variable to reset on error.
@param erp Error report, may be NULL.
*/
static
void
dk4gratool_font_one_definition(
dk4_stream_t *ostrm,
dk4_font_item_t const *foi,
int *bptr,
dk4_er_t *erp
)
{
const char *lfn = NULL; /* LaTeX font name */
int ffl = 0; /* Font number or font features */
int ff = 0; /* Font features mask */
#if DK4_USE_ASSERT
assert(NULL != ostrm);
assert(NULL != foi);
#endif
if (DK4_GRA_TF_EXACT_SIZE == foi->fex) {
lfn = dk4font_get_latex_font_name(dk4font_number_from_int(foi->fno));
dk4gratool_stream_string(ostrm, dk4gratool_kw[11], bptr, erp);
dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[12], bptr, erp);
dk4gratool_stream_string(ostrm, lfn, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[14], bptr, erp);
dk4gratool_stream_double(ostrm, foi->fsz, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[13], bptr, erp);
}
else {
/* providecommand */
dk4gratool_stream_string(ostrm, dk4gratool_kw[15], bptr, erp);
dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[16], bptr, erp);
/* renewcommand */
dk4gratool_stream_string(ostrm, dk4gratool_kw[17], bptr, erp);
dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[18], bptr, erp);
/* Font size */
switch (foi->fex) {
case DK4_GRA_TF_SIMILAR_SIZE : case DK4_GRA_TF_NONE_SIZE : {
dk4gratool_stream_string(ostrm, dk4gratool_kw[29], bptr, erp);
dk4gratool_stream_double(ostrm, foi->fsz, bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[30], bptr, erp);
dk4gratool_stream_double(ostrm, (1.2 * foi->fsz), bptr, erp);
dk4gratool_stream_string(ostrm, dk4gratool_kw[31], bptr, erp);
} break;
default : {
/* Intentionally empty to avoid compiler warnings. */
} break;
}
/* Font family, series and shape */
switch (foi->fex) {
case DK4_GRA_TF_EXACT_NONE :
case DK4_GRA_TF_SIMILAR_SIZE :
case DK4_GRA_TF_SIMILAR_NONE : {
dk4gratool_stream_string(ostrm, dk4gratool_kw[20], bptr, erp);
if (DK4_GRA_TF_EXACT_NONE == foi->fex) {
dk4gratool_stream_string(
ostrm,
dk4font_get_latex_family_name(
dk4font_number_from_int(foi->fno)
),
bptr,
erp
);
}
else {
switch (DK4_FONT_FEATURE_FT_MASK & (foi->fno)) {
case DK4_FONT_FEATURE_SYMBOL : {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[24], bptr, erp
);
} break;
case DK4_FONT_FEATURE_TTY : {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[22], bptr, erp
);
} break;
case DK4_FONT_FEATURE_SANS_SERIF : {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[23], bptr, erp
);
} break;
default : { /* roman */
dk4gratool_stream_string(
ostrm, dk4gratool_kw[24], bptr, erp
);
} break;
}
/* 2019-05-14 Bugfix
To find the type we must and-combine the font
features with the mask bit as above.
*/
#if 0
if (0 != (DK4_FONT_FEATURE_TTY & (foi->fno))) {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[22], bptr, erp
);
}
else {
if (0 != (DK4_FONT_FEATURE_SANS_SERIF & (foi->fno))) {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[23], bptr, erp
);
}
else {
dk4gratool_stream_string(
ostrm, dk4gratool_kw[24], bptr, erp
);
}
}
#endif
}
dk4gratool_stream_string(ostrm, dk4gratool_kw[21], bptr, erp);
ffl = foi->fno;
if (DK4_GRA_TF_EXACT_NONE == foi->fex) {
ffl = dk4font_get_features(
dk4font_number_from_int(foi->fno)
);
}
if (0 != (DK4_FONT_FEATURE_BOLD & ffl)) {
dk4gratool_stream_string(ostrm,dk4gratool_kw[25],bptr,erp);
}
else {
dk4gratool_stream_string(ostrm,dk4gratool_kw[26],bptr,erp);
}
ff = DK4_FONT_FEATURE_ITALIC | DK4_FONT_FEATURE_OBLIQUE;
if (0 != (ff & ffl)) {
dk4gratool_stream_string(ostrm,dk4gratool_kw[27],bptr,erp);
}
else {
dk4gratool_stream_string(ostrm,dk4gratool_kw[28],bptr,erp);
}
} break;
default : {
/* Intentionally empty to avoid compiler warnings. */
} break;
}
dk4gratool_stream_string(ostrm, dk4gratool_kw[19], bptr, erp);
}
}
void
dk4gratool_font_definitions(
dk4_stream_t *ostrm,
dk4_font_collector_t *fontc,
int *bptr,
dk4_er_t *erp
)
{
dk4_font_item_t *foi; /* Current font item to write */
#if DK4_USE_ASSERT
assert(NULL != ostrm);
assert(NULL != fontc);
#endif
dk4sto_it_reset(fontc->i_fn);
do {
foi = (dk4_font_item_t *)dk4sto_it_next(fontc->i_fn);
if (NULL != foi) {
dk4gratool_font_one_definition(ostrm, foi, bptr, erp);
}
} while (NULL != foi);
}
int
dk4gratool_compare_preamble_lines(
void const *l,
void const *r,
int DK4_ARG_UNUSED(cr)
)
{
dk4_gra_preamble_line_t const *pl;
dk4_gra_preamble_line_t const *pr;
int back = 0;
DK4_UNUSED_ARG(cr)
if (NULL != l) {
if (NULL != r) {
pl = (dk4_gra_preamble_line_t const *)l;
pr = (dk4_gra_preamble_line_t const *)r;
if (pl->lineno > pr->lineno) {
back = 1;
}
else {
if (pl->lineno < pr->lineno) {
back = -1;
}
}
}
else {
back = 1;
}
}
else {
if (NULL != r) {
back = -1;
}
}
return back;
}
void
dk4gratool_preamble_delete(
dk4_gra_preamble_line_t *ptr
)
{
$? "+ dk4gratool_preamble_delete"
#if DK4_USE_ASSERT
assert(NULL != ptr);
#endif
if (NULL != ptr) { $? ". ptr"
if (NULL != ptr->text) { $? ". text = \"%!8s\"", ptr->text
dk4mem_free(ptr->text);
}
dk4mem_free(ptr);
}
$? "- dk4gratool_preamble_delete"
}
dk4_gra_preamble_line_t *
dk4gratool_preamble_new(
char const *textline,
size_t lineno,
dk4_er_t *erp
)
{
dk4_gra_preamble_line_t *back = NULL;
$? "+ dk4gratool_preamble_new"
#if DK4_USE_ASSERT
assert(NULL != textline);
#endif
if (NULL != textline) { $? ". args ok"
back = dk4mem_new(dk4_gra_preamble_line_t,1,erp);
if (NULL != back) { $? ". allocation ok"
back->lineno = lineno;
back->text = dk4str8_dup(textline, erp);
if (NULL == back->text) { $? "! text allocation"
dk4mem_free(back);
back = NULL;
}
}
#if TRACE_DEBUG
else { $? "! allocation"
}
#endif
}
else { $? "! args"
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
$? "- dk4gratool_preamble_new %d", TR_IPTR(back)
return back;
}
double
dk4gratool_dist_point_point(
dk4_gra_point_t const *a,
dk4_gra_point_t const *b,
dk4_er_t *erp
)
{
double back = -1;
double dx;
double dy;
#if DK4_USE_ASSERT
assert(NULL != a);
assert(NULL != b);
#endif
if ((NULL != a) && (NULL != b)) {
dx = b->x - a->x;
dy = b->y - a->y;
back = sqrt(dx * dx + dy * dy);
}
else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
/** Calculate square value.
@param x Original value.
@return Square value.
*/
static
double
dbl_sq(double x)
{
return (x * x);
}
double
dk4gratool_dist_point_track(
dk4_gra_point_t const *a,
dk4_gra_point_t const *b,
dk4_gra_point_t const *p,
dk4_er_t *erp
)
{
dk4_gra_point_t q;
double back = -1.0;
double z;
double n;
double t;
#if DK4_USE_ASSERT
assert(NULL != a);
assert(NULL != b);
assert(NULL != p);
#endif
if ((NULL != a) && (NULL != b) && (NULL != p)) {
z = (b->y - a->y) * p->y - a->y * b->y + dbl_sq(a->y);
z += (b->x - a->x) * p->x - a->x * b->x + dbl_sq(a->x);
n = dbl_sq(b->y) - 2.0 * a->y * b->y + dbl_sq(a->y);
n += dbl_sq(b->x) - 2.0 * a->x * b->x + dbl_sq(a->x);
t = z / n;
if ((0 != dk4ma_is_finite(t)) && (0.0 <= t) && (1.0 >= t)) {
q.x = a->x + t * (b->x - a->x);
q.y = a->y + t * (b->y - a->y);
back = dk4gratool_dist_point_point(&q, p, erp);
}
else {
z = dk4gratool_dist_point_point(a, p, erp);
n = dk4gratool_dist_point_point(b, p, erp);
back = ((z <= n) ? (z) : (n));
}
}
else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
double
dk4gratool_dist_point_ellipse_simple(
double rx,
double ry,
dk4_gra_point_t const *p
)
{
double px;
double back = -1.0;
$? "+ dk4gratool_dist_point_ellipse_simple"
#if DK4_USE_ASSERT
assert(NULL != p);
assert(0.0 < rx);
assert(0.0 < ry);
#endif
px = (ry * p->x) / rx; $? ". px = %g", px
back = sqrt((px * px) + (p->y * p->y)); $? ". r = %g", back
back = fabs(back - ry); $? ". r = %g", back
back = (back * rx) / ry; $? ". r = %g", back
$? "- dk4gratool_dist_point_ellipse_simple %g", back
return back;
}
double
dk4gratool_dist_point_ellipse(
dk4_gra_point_t const *c,
double rx,
double ry,
double rot,
dk4_gra_point_t const *p,
dk4_er_t *erp
)
{
dk4_gra_point_t myp;
double back = -1.0;
#if DK4_USE_ASSERT
assert(NULL != c);
assert(NULL != p);
assert(0.0 < rx);
assert(0.0 < ry);
#endif
if ((NULL != c) && (NULL != p) && (0.0 < rx) && (0.0 < ry)) {
DK4_MEMCPY(&myp,p,sizeof(dk4_gra_point_t));
myp.x -= c->x;
myp.y -= c->y;
if (1.0e-8 <= fabs(rot)) {
dk4gratool_rotate_point(&myp, (0.0 - rot));
}
back = dk4gratool_dist_point_ellipse_simple(rx, ry, &myp);
}
else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
/* vim: set ai sw=4 ts=4 : */