ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
From: Giuseppe Bilotta <gip.bilotta@iol.it>
Subject: Re: Re: Re[4]: MetaPost/Fun question
Date: Mon, 24 Mar 2003 14:49:44 +0100	[thread overview]
Message-ID: <1053548782.20030324144944@iol.it> (raw)
In-Reply-To: <u7kap2ael.fsf@multiline.com.au>

[-- Attachment #1: Type: text/plain, Size: 456 bytes --]

Monday, March 24, 2003 Guy Worthington wrote:

GW> Giuseppe Bilotta wrote
>> Emil Hedevang Lohse wrote:

>>> [an algorithm for finding the intersection points of two paths]

>> [a metapost implementation]

GW> Thanks Emil and Giuseppe, a nice example that was well worth the read.

You may want to have a look at the stuff in the attached MetaPost
macroset, which I'm preparing for a better support of the
Eukleides program.

-- 
Giuseppe "Oblomov" Bilotta

[-- Attachment #2: eukleides.mp --]
[-- Type: application/octet-stream, Size: 4613 bytes --]

%D This \MP\ source is supposed to help in the conversion of Eukleides
%D datafiles to \MP\ format.

%D The first macro is findallintersections ; given two paths,
%D it sets one global variable (intersectionsfound) containing the number of
%D found intersections, and two sets of global pairs:
%D \startitemize
%D \item intersections[0] \dots\ intersections[intersectionsfound-1] which
%D contain the times of the intersections point (xpart for ther first curve,
%D ypart for the second curve;
%D \item intersectionpointsp[0] \dots\ intersectionpoints[intersectionsfound-1]
%D which contain the actual points;
%D \stopitemize
%D the behaviour of this macro is controlled by the global parameter
%D intersectiontolerance: setting it too high will skip some intersections,
%D setting it too low will find too many, possibly entering an infinite loop;
%D this is especially the case for tangent, osculant or hyperosculant paths.

%D The macro works by finding an intersection point, removing the slice of the
%D first path upto the first intersection point (plus tolerance), and reiterate
%D until either no more intersection points are found or the first paths gets
%D exhausted (this check is necessary because of infinite loops that can
%D happen otherwise.

newinternal intersectiontolerance ; intersectiontolerance := eps ;

def findallintersections (expr p, q) = 
% we start by resetting the results
pair intersections[], intersectionpoints[] ; intersectionsfound := 0 
if (path p and path q):
begingroup ;
save j, tp ; path tp; tp := p ;
j:= 0 ;
intersections[j] = tp intersectiontimes q ;
forever:
exitif (xpart intersections[j] = -1) or (ypart intersections[j] = -1) or 
       (xpart intersections[j] + intersectiontolerance > length p) ;
intersectionpoints[j] = point ypart intersections[j] of q ;
j:=j+1 ;
tp := subpath (xpart intersections[j-1] + intersectiontolerance, length p) of p ;
intersections[j] := tp intersectiontimes q ;
% watch the trick to ensure the xpart will be the time on the real path
intersections[j] := (xpart (p intersectiontimes (point xpart intersections[j] of tp)),
                     ypart intersections[j]);
endfor ;
intersectionsfound := j ;
endgroup ;
fi ; 
enddef ;

%D We then create an auxiliary macro to determine the time of a point
%D on a curve; I'm not aware of any \MP\ primitives that do this, so \dots

primarydef p timedon q =
(xpart (q intersectiontimes p))
enddef ;

%D I hate the counter-intuitiveness of fullcircle not having radius 1, so:

path trigcircle ; trigcircle := fullcircle scaled 2 ;

%D A useful shorthand:

def point_at_angle (expr degrees) =
(cosd(degrees), sind(degrees))
enddef ;

%D The next macro returns a circular arc. It accepts two parameters
%D (starting angle, ending angle) in degrees. Angles are assumed to be
%D oriented.

def arc (expr starting, ending) =
begingroup 
save startingpoint, endingpoint, startingtime, endingtime ;
pair startingpoint, endingpoint ;
startingpoint := point_at_angle(starting) ;
endingpoint   := point_at_angle(ending) ;
startingtime  := startingpoint timedon trigcircle ;
endingtime    := endingpoint   timedon trigcircle ;
% watch the trick to ensure that arcs crossing the origin
% are drawn correctly
if startingtime > endingtime:
arc (starting+10, ending+10) rotated -10
else:
subpath (startingtime, endingtime) of trigcircle 
fi
endgroup
enddef ;

%D These are really not needed by Eukleides, but anyway \dots

def radiusat (expr degrees) =
(origin -- point_at_angle(degrees))
enddef ;

def circularsector (expr starting, ending) =
(origin -- arc(starting, ending) -- cycle)
enddef ;

%D Back to Eukleides; a dotmark with a plus shape

picture dot_mark_plus; dot_mark_plus := nullpicture ;
addto dot_mark_plus doublepath (-3,0)--(3,0) ;
addto dot_mark_plus doublepath (0,3)--(0,-3) ;

%D In Eukleides we can set labels centered at a given distance and angle
%D in proximity of a given point (aka psfig's \tex{uput})

color labelcolor ; labelcolor := black ;

def pslabel( expr t,  p,  d,  a) =
% t: text; p: point; d: distance; a: angle
begingroup
save thislabel, thispoint, drawingcolor ;
picture thislabel ; pair thispoint ; color drawingcolor ;
if picture t:  thislabel = t
else:    thislabel = t infont defaultfont scaled defaultscale
fi; 
xpart thispoint = d*cosd(a) - xpart center thislabel * cosd(a) ;
ypart thispoint = d*sind(a) - ypart center thislabel * sind(a) ;
drawingcolor := labelcolor ;
label(thislabel, p + thispoint) ;
endgroup
enddef ;


endinput ;

      reply	other threads:[~2003-03-24 13:49 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-03-22 20:59 Giuseppe Bilotta
2003-03-22 21:23 ` Hans Hagen
2003-03-22 21:32   ` Re[2]: " Giuseppe Bilotta
2003-03-22 23:35     ` Emil Hedevang Lohse
2003-03-23 13:34       ` Re[4]: " Giuseppe Bilotta
2003-03-24 12:53         ` Guy Worthington
2003-03-24 13:49           ` Giuseppe Bilotta [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1053548782.20030324144944@iol.it \
    --to=gip.bilotta@iol.it \
    --cc=ntg-context@ntg.nl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).