<> <> <> <> <> <<>> DIRECTORY Cubic USING [Bezier], Complex USING [VEC], LSPiece USING [Metrics, MetricsRec], PotentialKnots, FitJaM USING [RegisterInit, InitProc, defaultFitState], Highlight USING [ShowBezier, CleanUp, Context], JaM; PotentialKnotsJaM: CEDAR PROGRAM IMPORTS JaM, FitJaM, PotentialKnots, Highlight = { highlight: Highlight.Context _ NIL; --set this to FitJaM.defaultHighlight for debugging -- penalty lineLength maxAngle => . Finds nodes using DynFit DynPoly: PROC [state: JaM.State] = { maxAngle: REAL _ JaM.PopReal[state]; lineLength: REAL _ JaM.PopReal[state]; penalty: REAL _ JaM.PopReal[state]; PotentialKnots.DynPoly[state: FitJaM.defaultFitState, lineLength: lineLength, penalty: penalty, maxAngle: maxAngle]; }; QuickPoly: PROC [state: JaM.State] = { --finds "lines" in a bitmap PotentialKnots.QuickPoly[state: FitJaM.defaultFitState, highlight: highlight]; }; metrics: LSPiece.Metrics _ NEW[LSPiece.MetricsRec]; CubicTangents: PROC[state: JaM.State] = {-- range err maxit => . Sets tangents at nodes by locally fitting a cubic between neighboring nodes newTangent: PotentialKnots.Progress = { Highlight.ShowBezier[highlight, cubic]; RETURN[JaM.GetAbort[state]]; }; metrics.maxItr _ JaM.PopInt[state]; metrics.sumErr _ JaM.PopReal[state]; PotentialKnots.CubicTangents[FitJaM.defaultFitState, metrics, newTangent]; --calls newTangent in a loop Highlight.CleanUp[highlight]; }; QuickTangents: PROC[state: JaM.State] = {-- maxAngle setcorners => . computes tangents by differencing neighbors. sets one-sided corners if setcorners=true setCorners: BOOL _ JaM.PopBool[state]; maxAngle: REAL _ JaM.PopReal[state]; PotentialKnots.QuickTangents[FitJaM.defaultFitState, maxAngle, setCorners]; }; SquareTangents: PROC[state: JaM.State] = {-- maxAngle setcorners => . computes tangents, weighting the longer edges more. sets one-sided corners if setcorners=true setCorners: BOOL _ JaM.PopBool[state]; maxAngle: REAL _ JaM.PopReal[state]; PotentialKnots.SquareTangents[FitJaM.defaultFitState, maxAngle, setCorners]; }; CircleTangents: PROC[state: JaM.State] = {-- maxAngle setcorners => . computes tangents, weighting the longer edges more. sets one-sided corners if setcorners=true maxAngle: REAL _ JaM.PopReal[state]; PotentialKnots.CircleTangents[FitJaM.defaultFitState, maxAngle]; }; HVExtremes: PROC[state: JaM.State] = { --forceKnot => puts nodes on extremes PotentialKnots.HVExtremes[FitJaM.defaultFitState, JaM.PopBool[state]]; }; Find90: PROC[state: JaM.State] = { --long maxangle forceknots => puts nodes on extremes forceKnots: BOOL _ JaM.PopBool[state]; minFlat: REAL _ JaM.PopReal[state]; long: REAL _ JaM.PopReal[state]; PotentialKnots.Find90[FitJaM.defaultFitState, long, minFlat, forceKnots, highlight]; }; HVLines: PROC[state: JaM.State] = { --long maxangle forceknots => puts nodes on extremes forceKnots: BOOL _ JaM.PopBool[state]; maxAngle: REAL _ JaM.PopReal[state]; long: REAL _ JaM.PopReal[state]; PotentialKnots.HVLines[FitJaM.defaultFitState, long, maxAngle, forceKnots, highlight]; }; HVTangents: PROC[state: JaM.State] = { --maxangle forceknots => puts nodes on extremes forceKnots: BOOL _ JaM.PopBool[state]; maxAngle: REAL _ JaM.PopReal[state]; PotentialKnots.HVTangents[FitJaM.defaultFitState, maxAngle, forceKnots]; }; NearlyEqual: PROC[state: JaM.State] = { --maxangle => sets nearly equal left and right tangents the same. maxAngle: REAL _ JaM.PopReal[state]; PotentialKnots.NearlyEqual[FitJaM.defaultFitState, maxAngle]; }; ForceCorners: PROC[state: JaM.State] = { --minangle => forces corners if internal angle is < minangle. angle: REAL _ JaM.PopReal[state]; PotentialKnots.ForceCorners[FitJaM.defaultFitState, angle]; }; FindCorners: PROC[state: JaM.State] = { --minK, forceKnots => corners using curvature. force: BOOLEAN _ JaM.PopBool[state]; minK: REAL _ JaM.PopReal[state]; PotentialKnots.FindCorners[FitJaM.defaultFitState, minK, force]; }; FindInflections: PROC[state: JaM.State] = { --flat, forceKnots => inflections within flat using curvature. force: BOOLEAN _ JaM.PopBool[state]; flat: REAL _ JaM.PopReal[state]; PotentialKnots.FindInflections[FitJaM.defaultFitState, flat, force]; }; FindDeltaKs: PROC[state: JaM.State] = { --minDK, forceKnots => joints at points of high curvature force: BOOLEAN _ JaM.PopBool[state]; minDK: REAL _ JaM.PopReal[state]; PotentialKnots.FindDeltaKs[FitJaM.defaultFitState, minDK, force]; }; Init: FitJaM.InitProc = { JaM.Register[state, "PK.find90",Find90]; -- minL, minFlat, forceKnots => IF two flat lines of minL meet at a corner, mark it. Assume flat lines are horizontal or vertical (only cases that will in practice pass the flatness test for small values of minFlat) JaM.Register[state, "PK.findCorners",FindCorners]; -- minK, forceKnots => corners using curvature JaM.Register[state, "PK.findInflections",FindInflections]; -- flat, forceKnots => inflections within flat using curvature JaM.Register[state, "PK.findDeltaKs",FindDeltaKs]; -- minDK, forceKnots => joints at points of high curvature JaM.Register[state, "PK.dynpoly",DynPoly]; -- penalty lineLength maxAngle => . Finds nodes using DynFit. IF two adjacent lines are each longer than lineLength AND the turning angle is >= maxAngle THEN force a corner at the intersection JaM.Register[state, "PK.quickpoly",QuickPoly]; -- finds a polygon fit JaM.Register[state, "PK.cubictangents",CubicTangents]; -- err maxit => . Sets tangents at nodes by fitting between neighboring nodes. JaM.Register[state, "PK.quicktangents",QuickTangents]; -- maxangle setCorners => . computes tangents by differencing neighbors. setCorners=TRUE sets one-sided tangents on corners JaM.Register[state, "PK.squaretangents",SquareTangents]; -- maxangle setCorners => . computes tangents, weighting the longer edges more. setCorners=TRUE sets one-sided tangents on corners JaM.Register[state, "PK.circletangents",CircleTangents]; -- maxangle => . computes tangents, using circle through three adjacent joints. if angle > maxangle then leave tangents free JaM.Register[state, "PK.hvextremes",HVExtremes]; -- forceknots => Puts potential knots on xy extremes JaM.Register[state, "PK.hvlines",HVLines]; -- long maxangle forceknots => Puts potential knots around long horizontal and vertical lines. maxangle is the tolerance for the decision JaM.Register[state, "PK.hvtangents",HVTangents]; -- maxangle forceknots => sets nearly horizontal and vertical tangents to horizontal and vertical. JaM.Register[state, "PK.nearlyequal",NearlyEqual]; -- maxangle => sets nearly equal left and right tangents the same. JaM.Register[state, "PK.forcecorners",ForceCorners]; -- minangle => forces corners if internal angle between two tangents is < minangle }; FitJaM.RegisterInit[id: $PotentialKnotsJaM, proc: Init]; }.