-- FilterImpl.mesa
-- Last modified by Maureen Stone July 16, 1982 5:35 pm
-- Last modified by Michael Plass  August 20, 1982 2:55 pm

DIRECTORY
	Curve,
	DynFit,
	Vector,
	Seq,
	JaMFnsDefs;

FilterImpl: PROGRAM
	IMPORTS JaMFnsDefs, DynFit, Curve  = {

AveFilter: PROC = {
	samples: Seq.ComplexSequence ← Curve.CurrentSamples[Curve.defaultHandle];
	double: BOOLEAN;
	length: NAT;
	prev,current,next: Vector.Vec;
	IF samples=NIL THEN RETURN;
	double ← samples[0]=samples[samples.length-1];
	length ← samples.length;
	IF double THEN length ← length-1;
	prev ← samples[length-1];
	FOR i: NAT IN [0..length) DO
		current ← samples[i];
		next ← IF i=length-1 THEN samples[0] ELSE samples[i+1];
		samples[i].x ← (prev.x+2*current.x+next.x)/4;
		samples[i].y ← (prev.y+2*current.y+next.y)/4;
		prev ← current;
		ENDLOOP;
	Curve.StartSamples[Curve.defaultHandle, samples[0].x,samples[0].y];
	FOR i: NAT IN [1..length) DO Curve.AddSample[Curve.defaultHandle, samples[i].x,samples[i].y]; ENDLOOP;
	IF double THEN Curve.AddSample[Curve.defaultHandle, samples[0].x,samples[0].y];
	};

AveFilterLeavingCorners: PROC = {
	samples: Seq.ComplexSequence ← Curve.CurrentSamples[Curve.defaultHandle];
	node: Seq.NatSequence;
	tangent: Seq.ComplexSequence;
	double: BOOLEAN;
	length: NAT;
	nextNode: NAT ← 0;
	prev,current,next: Vector.Vec;
	[node, tangent] ← Curve.CurrentNodes[Curve.defaultHandle];
	IF samples=NIL THEN RETURN;
	double ← samples[0]=samples[samples.length-1];
	length ← samples.length;
	IF double THEN length ← length-1;
	prev ← samples[length-1];
	FOR i: NAT IN [0..length) DO
		current ← samples[i];
		next ← IF i=length-1 THEN samples[0] ELSE samples[i+1];
		IF NOT (i = node[nextNode] AND tangent[nextNode] = [0,0]) THEN { 
			samples[i].x ← (prev.x+2*current.x+next.x)/4;
			samples[i].y ← (prev.y+2*current.y+next.y)/4;
			};
		IF i = node[nextNode] THEN nextNode ← nextNode+1;
		prev ← current;
		ENDLOOP;
	Curve.StartSamples[Curve.defaultHandle, samples[0].x,samples[0].y];
	FOR i: NAT IN [1..length) DO Curve.AddSample[Curve.defaultHandle, samples[i].x,samples[i].y]; ENDLOOP;
	IF double THEN Curve.AddSample[Curve.defaultHandle, samples[0].x,samples[0].y];
	Curve.ResetNodes[Curve.defaultHandle];
	FOR i: NAT IN [0..node.length) DO Curve.AddNode[Curve.defaultHandle, node[i], tangent[i]] ENDLOOP;
	};

Dynfilter: PROCEDURE = {
	tolerance: REAL = JaMFnsDefs.GetReal[];
	totalBadness: REAL ← 0;
	segments: DynFit.Segments;
	newZ: Seq.ComplexSequence;
	len: NAT;
	sList: Seq.ComplexSequence ← Curve.CurrentSamples[Curve.defaultHandle];
	IF sList=NIL THEN RETURN;
	[segments,totalBadness] ← DynFit.FitSegments[sList,tolerance];
	[newZ,len] ← DynFit.SampleSegments[segments,sList];
	Curve.StartSamples[Curve.defaultHandle, newZ[0].x,newZ[0].y];
	FOR i:NAT IN [1..len) DO Curve.AddSample[Curve.defaultHandle, newZ[i].x,newZ[i].y] ENDLOOP;
	};

JaMFnsDefs.Register[".dfsa"L,Dynfilter];
JaMFnsDefs.Register[".afsa"L,AveFilter];
JaMFnsDefs.Register[".filterbetweencorners"L,AveFilterLeavingCorners];

}.