HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
anvaka
peak-map
JavaScript2020–2020
anvaka / peak-map

peak-map

Make a ridge line chart from any region on Earth

2Distinct people
2Mentions
0Explicit recommenders
645GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Make a ridge line chart from any region on Earth

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by 3-hour interval2 dated mentions

Observed mentions: 2020-01-06 13:18:13 UTC to 2020-01-08 04:05:00 UTC.

012020-01-06 12:00:00 UTC to 2020-01-06 15:00:00 UTC (exclusive): 1 mentions; 1 submissions, 0 commentsJan 6, 12:002020-01-06 15:00:00 UTC to 2020-01-06 18:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-06 18:00:00 UTC to 2020-01-06 21:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-06 21:00:00 UTC to 2020-01-07 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 00:00:00 UTC to 2020-01-07 03:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 03:00:00 UTC to 2020-01-07 06:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 06:00:00 UTC to 2020-01-07 09:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 commentsJan 7, 06:002020-01-07 09:00:00 UTC to 2020-01-07 12:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 12:00:00 UTC to 2020-01-07 15:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 15:00:00 UTC to 2020-01-07 18:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 18:00:00 UTC to 2020-01-07 21:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-07 21:00:00 UTC to 2020-01-08 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-08 00:00:00 UTC to 2020-01-08 03:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-08 03:00:00 UTC to 2020-01-08 06:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 commentsJan 8, 03:00

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
Jan 6, 12:002020-01-06 12:00:00 UTC2020-01-06 15:00:00 UTC110
Jan 6, 15:002020-01-06 15:00:00 UTC2020-01-06 18:00:00 UTC000
Jan 6, 18:002020-01-06 18:00:00 UTC2020-01-06 21:00:00 UTC000
Jan 6, 21:002020-01-06 21:00:00 UTC2020-01-07 00:00:00 UTC000
Jan 7, 00:002020-01-07 00:00:00 UTC2020-01-07 03:00:00 UTC000
Jan 7, 03:002020-01-07 03:00:00 UTC2020-01-07 06:00:00 UTC000
Jan 7, 06:002020-01-07 06:00:00 UTC2020-01-07 09:00:00 UTC000
Jan 7, 09:002020-01-07 09:00:00 UTC2020-01-07 12:00:00 UTC000
Jan 7, 12:002020-01-07 12:00:00 UTC2020-01-07 15:00:00 UTC000
Jan 7, 15:002020-01-07 15:00:00 UTC2020-01-07 18:00:00 UTC000
Jan 7, 18:002020-01-07 18:00:00 UTC2020-01-07 21:00:00 UTC000
Jan 7, 21:002020-01-07 21:00:00 UTC2020-01-08 00:00:00 UTC000
Jan 8, 00:002020-01-08 00:00:00 UTC2020-01-08 03:00:00 UTC000
Jan 8, 03:002020-01-08 03:00:00 UTC2020-01-08 06:00:00 UTC101

What Hacker News says

2 sources
I also thank you for sharing! In reading your code to learn from your work, I noticed a little optimization you could use, that applies to other 2d canvas code in general: CanvasRenderingContext2D has save() and restore() methods you can call to re-use partial paths. So instead of making the path and closing it to fill, then making it again without closing it to stroke, you can make it once without closing, save the graphics state, close the path, then fill, restore the graphics state, then stroke! That is a classic idiom from PostScript (draw, gsave, fill, grestore, stroke). That should save a bunch of JavaScript looping and spooning points through the 2d context api. (It's the individual lineTo calls that are expensive, because of all the overhead of JavaScript<=>C bindings, not stroking or filling the actual lines. And there's no way t
Read the rest
o provide an array of points all at once, like with WebGL. (At least SVG made the right decision, inspired by VML, to put all the points of a path in one attribute string, instead of using individual XML elements for each point.) https://developer.mozilla.org/en-US/docs/Web/SVG/Element/pat... Once you get into native code, it's fast even if there's a lot to do (i.e. calling ctx.stroke once), but jumping in and out of native code a lot (i.e. calling ctx.lineTo a thousand times) is slow.) Thanks for sharing the code, it's inspired me! (I'm trying to figure out how to rotate and otherwise generally transform the direction that the lines scan across the depth map and screen, to get a Max Headroom effect! Maybe somebody with deep shader-fu could suggest an out-of-the-box way to render it in hardware with WebGL, to apply to live video!) Come to think of it, you could just draw the ridges directly as polygons with WebGL, and that would be quite flexible and performant! I haven't tested it yet, but here's the new drawPolyLine from createHeightMapRenderer.js: Original: https://github.com/anvaka/peak-map/blob/master/src/lib/creat... Optimized: /** * Draws filled polyline. */ function drawPolyLine(points) { if (points.length < 3) return; let smoothRange = getSmoothRange(points, smoothSteps); points = smoothRange.points; // Create the unclosed path. ctx.beginPath(); ctx.moveTo(points[0], points[1]); for (let i = 2; i < points.length; i += 2) { ctx.lineTo(points[i], points[i + 1]); } // If line's height is greater than 2 pixels, let's save // the graphics state, finish and close the path, fill it, // then restore the graphics state: if (smoothRange.max - smoothRange.min > 2) { ctx.save(); ctx.lineTo(points[points.length - 2], smoothRange.max); ctx.lineTo(points[0], smoothRange.max); ctx.closePath(); ctx.fillStyle = lineFill; ctx.fill(); ctx.restore(); } // Now finally stroke the unclosed path. ctx.strokeStyle = lineStroke; ctx.stroke(); } There was a classic "Grandfather Clock" posting from Glenn Reid at Adobe (author of the "Green Book" on PostScript language program design) to comp.lang.postscript that really opened my eyes about writing code in interpreted languages like PostScript (and JavaScript, while JIT'ed at runtime, still makes calling native code expensive), and balancing optimization with readability: Here's Glenn's "Green Book", which was like a bible to me, and still is quite relevant to canvas 2d context programming -- see especially page 9, section 1.5, Program Design Guidelines, page 72, section 4.6, Optimizing Translator Output, and page 99, chapter 7, The Mechanics of Setting Text: https://www-cdf.fnal.gov/offline/PostScript/GREENBK.PDF >page 9: 1.5 Program Design Guidelines >There are a few items that may be kept in mind while implementing a driver for a PostScript device. As with most software development, the most difficult part of writing programs in the PostScript language is the design of the program. If the design is good, implementing it is easy. If the design is poor, it may not even be possible to correctly implement it. Below are some helpful items to keep in mind when writing your software. All of them are explained more fully within the text of this book; this is only an attempt to prime the pump before you start reading: >• Use the operand stack efficiently. Pay particular attention to the order of the elements on the stack and how they are used. (Using the stack efficiently by designing fluent words that chain and dovetail together elegantly in pipelines (and systematically writing line-by-line stack comments) instead of using named variables in dictionaries is good idiomatic PostScript and Forth, aka tacit programming or point-free style, the stack-based equivalent of fluent interfaces.) https://en.wikipedia.org/wiki/Tacit_programming https://en.wikipedia.org/wiki/Fluent_interface >• Avoid unnecessary redundancy. When a program is produced, check for many repetitive steps that perhaps could be condensed. Keep identifiers short if they are to be transmitted many times. (Only create paths once!) >• Use the PostScript imaging model effectively. When printing, a document must be translated into the language of the printer. This includes a philosophical adjustment to the nature of the PostScript imaging model. (Use the graphics state stack!) >• It is better to translate into the PostScript imaging model than to maintain another set of graphics primitives using the PostScript language for emulation. (The hardest problem I ever tried (and failed) to solve properly with PostScript was making a printer driver for rendering user interfaces drawn with X11 using a combination of bitmaps and lines. Because of X11 "half open" pixel rounding rules versus PostScript's "stencil paint" model, they just don't line up right when you zoom into them, and there's no fudge or compromise that works in all cases. Here is my commented-out failed attempt:) https://github.com/mmontone/garnet/blob/1652af38f76b1c4efb19... line-color line-cap line-join dash-pattern thickness % dup -1 ne { .5 add } if % fudge outline width thicker StrokeShape Half Open: https://www.sciencedirect.com/science/article/pii/B978008050... Stencil Paint: http://www.chilton-computing.org.uk/inf/literature/books/wm/... >page 100: Note: There is one principle to keep in mind when deciding upon an algorithm for setting text. The longer the string presented to one of the show operators, the more efficient the system is likely to be. This is because the PostScript language built-in operators, such as show, widthshow, and ashow, operate essentially at compiled speed once they have been invoked. Each moveto or div operation performed must first be interpreted, which is significantly slower. Glenn's post in a comp.lang.postscript discussion about PostScript programming style and optimization: https://groups.google.com/forum/#!search/%22glenn$20reid%22$... From: Glenn Reid (Abode Systems) Newsgroup: comp.lang.postscript Subject: Re: An Idea to Help Make Postscript Easier to Read (and Write) Date: 10 Sep 88 17:26:24 GMT You people tend to forget that the PostScript language is interpreted. It is well and good to use tools to convert to and from PostScript, but it is not quite as "transparent" as we all might think. I like to think of a big grandfather clock, with the pendulum swinging. Each time pendulum swings, the PostScript interpreter gets to do one operation. The "granularity" of the clock is nowhere near the speed of a microprocessor instruction set, and any comparison with assembly languages doesn't make sense. The difference between: 0 0 moveto and 0 0 /arg2 exch def /arg1 exch def arg1 arg2 moveto can sort of be measured in "ticks" of the interpreter's clock. It's not quite this simple, since simply pushing a literal is faster than executing a real PostScript operator, but it is a rough rule of thumb. It will take about three times as long to execute the second of these in a tight loop, and about five times as long if it is transmitted and scanned each time. My rule of thumb is that if you have roughly the same number of tokens in your stack approach as you do with your 'exch def' approach, the 'exch def' is likely to be much more readable and better. Otherwise, I usually go with the stack approach. One other thing of note is that if you have too much stack manipulation going on, it may well be symptomatic of a problem in the original program design. Also, most procedures don't do any stack manipulation at all, they simply use their arguments directly from the stack. In this situation, it is especially wasteful (and confusing, I think) to declare intermediate variables. Compare: % sample procedure call: (Text) 100 100 12 /Times-Roman SETTEXT % approach 1: /SETTEXT { %def findfont exch scalefont setfont moveto show } def % approach 2: /SETTEXT { %def /arg5 exch def /arg4 exch def /arg3 exch def /arg2 exch def /arg1 exch def arg5 findfont arg4 scalefont setfont arg2 arg3 moveto arg1 show } def Which of these is easier for you to understand? Anyway, I think the discussion is a good one, but let's not forget that PostScript it is an interpreted language. And I don't think it is terribly hard to use and understand, if it is written well. Glenn Reid Adobe Systems
In Peak map: Visualize the elevation of any area using a ridgeline chart

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.