惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
Cyberwarzone
Cyberwarzone
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
T
Troy Hunt's Blog
Help Net Security
Help Net Security
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
M
MIT News - Artificial intelligence
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V2EX - 技术
V2EX - 技术
Y
Y Combinator Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
T
Threatpost
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
SegmentFault 最新的问题
I
InfoQ
H
Hacker News: Front Page
D
Docker
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
Netflix TechBlog - Medium
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
博客园 - 【当耐特】
T
Tor Project blog
U
Unit 42
H
Heimdal Security Blog
Microsoft Azure Blog
Microsoft Azure Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy & Cybersecurity Law Blog
PCI Perspectives
PCI Perspectives
美团技术团队
O
OpenAI News
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
GbyAI
GbyAI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
MyScale Blog
MyScale Blog

Hacker News

Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Unexpected €54k billing spike in 13 hours: Firebase browser key without API restrictions used for Gemini requests Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
Hengefinder: Finding When the Sun Aligns With Your Street
evakhoury · 2026-05-22 · via Hacker News

Next week in Manhattan, the sunset will align perfectly with the east-west streets of the city grid. It’s beautiful, and people know it. Twice a year, crowds gather to see the brief moment when the sun sits perfectly on the horizon, framed by skyscrapers on either side. It’s called Manhattanhenge, after Stonehenge.

I wanted to know how astronomers figure out when Manhattanhenge happens. And if I could figure that out, why limit it to Manhattan?

A shot of Manhattanhenge, when the setting sun lines up exactly with the city grid
A shot of crowds taking photos of Manhattanhenge at 42nd St in NYC.

This was one of my first projects at the Recurse Center: Hengefinder, a tool that lets you find a henge pretty much anywhere the sun sets.

The basic steps (and some terminology I would soon learn):

  1. find the angle of a road (its bearing, relative to true north)
  2. find the angle of the sun at sunset each day (its azimuth)
  3. find the dates when those angles match.

It was appealing to me that this was mostly made up of many sub problems I could either think through thoroughly, or choose to mostly skip (by handing off to a library, a brute-force solution, an approximation, etc.). It’s like a bunch of closed boxes. I left plenty of those boxes closed — I didn’t build my own astronomical model, for instance. Other boxes I opened. And then I found many things I thought would be straightforward that turned out to be somewhat less trivial in practice as my assumptions broke; Like, in reality, you can’t treat roads like flat lines, latitude and longitude don’t behave like a Cartesian grid, and the word “sunset” is more ambiguous than I initially thought. I’ve enjoyed closing the gap between my assumptions and reality.

So, rather than just talking about the project as a whole, I’m going to walk through a couple challenges I ran into in building this, and how I went about solving them. One challenge for each of those supposedly “simple” steps above.

Challenge #1: Finding the road bearing (and rediscovering the Earth is not flat)

The first challenge was calculating the bearing of a street (its angle relative to true north). If you take the latitude and longitude of one address, and the latitude and longitude of another address down the street, you end up with the coordinates of two points on Earth. We can then use some trig to get the angle. My initial (incorrect) guess for getting the road bearing was to take the difference in latitude and the difference in longitude, then just get the angle with atan2 (the inverse tangent).

The problem is, that would only work if the Earth were flat.

A schematic of the orientation of latitude and longitude. Degrees of longitude represent smaller distances as you move away from the equator.

Latitude and longitude lines aren’t arranged the same way on the Earth. Latitude lines (which run east-west) are evenly spaced: one degree of latitude is basically the same distance everywhere on Earth. Longitude lines (which run north-south) aren’t. They converge as you move toward the poles. For example, one degree of longitude spans roughly 52 miles (84 km) in New York City, but way less at higher latitudes (about 33 miles / 53 km in Anchorage).

How do you manage that?

TL;DR, if you just want the practical takeaway

Scale longitude by cos(latitude), which puts longitude and latitude in the same “units.” Only then do atan2.

”Ok, but why?”

(And if you don’t really care about the math, feel free to skip to the “corrected approach” section below.)

When you do tan = opposite / adjacent, you’re assuming the dimensions of the triangle are in consistent units. They aren’t here. Like I said, degrees of longitude shrink as you move toward the poles, while latitude stays consistent. That means the horizontal and vertical sides of the triangle are in different units.

The same east-west distance maps on to different changes in longitude depending on latitude.

To fix this, we need a little spherical geometry.

Imagine the Earth as a unit sphere (radius = 1), and take a vertical cross-section through it. A point at latitude φ forms a right triangle:

  • the hypotenuse is the Earth’s radius (1)
  • the vertical leg is sin(φ)
  • the horizontal leg is cos(φ)
At latitude φ, east-west movement traces a smaller circle with radius cos(φ).

That horizontal leg is the distance from the Earth’s axis to the point of our “observer.” It’s also the radius of the circle you trace when you move east-west at latitude φ.

This means that at the equator (φ = 0°), the radius is cos(0) = 1, and at the poles (φ = 90°), the radius is effectively cos(90°) = 0 .

So, east-west distances shrink as you move away from the equator. You’re walking around smaller and smaller circles. To compare longitude meaningfully with latitude, you have to scale it by the radius of that circle, which is cos(latitude).

Once longitude is scaled this way, the two axes live in comparable units, and you can use the inverse tangent.

Corrected approach

# assuming lat/lon are in degrees
delta_y = lat_2 - lat_1

# scale longitude so it's in the same units as latitude
mean_lat = math.radians((lat_1 + lat_2) / 2) 
delta_x = (lon_2 - lon_1) * math.cos(mean_lat)  
    
# now we can safely use atan2
bearing_rad = math.atan2(delta_x, delta_y)
bearing_deg = math.degrees(bearing_rad)
    

(Note that this is still an approximation, but for short street segments, it’s accurate enough.)

Challenge #2: Finding the sun’s azimuth (or, what do we mean by sunset?)

For a perfect “henge” moment, the sun needs to be sitting directly on the horizon.

I used the Python library Astral to compute the timing, altitude, and azimuth (angle) of solar events at a given location. But Astral’s definition of a sunset is slightly different from what I want here. Astral uses the standard astronomical definition of sunset, i.e. when the sun has fully dipped below the horizon. For my purpose, that’s too late. I want to see when the sun is sitting right on top of the horizon. Astral’s version is still useful to me, however, since time-wise, it gets me in the ballpark on a given day.

For a moment to be a “henge,” I want the sun’s disk to be fully visible and just touching the horizon. I have a target “altitude” I want the sun to be at, above the horizon, based on the apparent size of the sun.

The technical definition of a sunset is too late for what is needed for a henge.

So I’m trying to find the last moment when the sun’s altitude is still above my target threshold altitude.

You could just do a linear search minute-by-minute in some time window before Astral’s sunset. It’d probably be fine, but each evaluation is an Astral API call. Plus, that’s less fun. This is one of the “boxes” I wanted to open. Because the sun’s altitude changes monotonically as sunset approaches, this indicates a binary search.

The textbook approach to binary search is this:

def basic_binary_search(arr, target):
    left = 0 
    right = len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    # Not found
    return -1 

But that formulation makes several assumptions that don’t really apply here. For one, we’re not searching for an exact target match. Because with minute-level resolution, we may never get the exact moment. Instead, in looking for a henge, I’m really evaluating a boolean each minute: “Is the sun still above the target altitude at this minute?” That gives a pattern like:

True, True, True, True, False, False, False

Rather than looking for a specific value, now we’re just looking for the last True before it flips.


So, I used a different approach to the binary search. Here’s the core loop, searching within a window of time before Astral’s sunset:

while left < right:
    mid = (left + right + 1) // 2  # upper-biased midpoint for a "last true" search
    if altitude > target: # still valid, keep it
        left = mid # this minute is valid, could be the last one
    else: # sun at or below horizon
        right = mid - 1 # this minute is invalid, look earlier

This turns it into a “last true” binary search, which lets me find the final minute when the sun is still above the target altitude.

(This mirrors the general binary search template in this great LeetCode article, which argues this is a less error-prone approach overall to binary search.)

Once I knew how to get (a) a road’s bearing and (b) the sun’s azimuth at sunset, I just had to find when the two matched to get a henge date.

I couldn’t do a binary search across the next 365 days, since the sun’s azimuth over the year is non-monotonic. I could just do the brute force approach and compute the sunset azimuth for every day of the year and check when (if ever) it matches the road bearing. That would have worked fine, it’s another box I could have left closed. But it felt like the wrong way to approach the problem. And again, it would make a lot of unnecessary API calls.

Relationship between sunset azimuth and date

If you plot the sun’s azimuth at a particular location, you get a smooth curve:

At a given location, the sun's sunset azimuth varies smoothly over the year and reverses direction around the solstices.

As a result, depending on the road’s bearing, there may be two alignment dates, one, or none at all. Streets closer to north-south alignment, for example, are just plainly out of reach at most latitudes.

You could model this function analytically and solve for the exact alignment dates. That’s how astronomers might approach it. But doing that correctly would mean committing to a pretty deep astronomical model, beyond the scope of what I wanted (the curve might look like a sine wave, but it isn’t quite). My goal wasn’t to do this perfectly, it was to build a tool that was easy to reason about and would reliably find me some henges.

I ended up using a compromise as a two-phase search.

I start by sampling at coarse intervals. Let’s say, once every 30 days.

If you sample in this coarse way, the goal is to identify a period in which we may have “missed” a henge, so that we can switch to a fine-grained search over that period. I do this by tracking not just the sun’s azimuth, but which side of the road bearing the sunset azimuth is on, and which direction it’s moving.

Here’s why. When sampling coarsely, a “missed” henge can happen in one of two ways.

The first way you might miss a henge in the coarse search is that the sun’s azimuth might move steadily toward the road bearing and cross it between samples, continuing in the same direction.

That is effectively the Intermediate Value Theorem:

If a continuous quantity changes sign over an interval, it must have crossed zero inside that interval.

If that happens, a henge definitely occurred.

The second way to miss a henge is if the sun’s azimuth reverses direction between samples. It’s possible a henge occurred during that reversal. It’s also possible that there was no henge, and that the road bearing is just “out of reach” of the sun’s maximum azimuth (for instance, there is no day in the year that the sunset azimuth in NYC would match a road with a bearing of 320˚). Either way, I’ve identified a finer window worth exploring.

Two ways coarse sampling can miss a henge, each shown as a pair of azimuth samples. The pink dots are on either side of the road bearing. A henge date is guaranteed to be in that window, which is flagged for fine-grained search. The blue pair sits entirely below the bearing but contains an azimuth direction reversal. This may or may not contain a henge, but is also flagged for the fine-grained search.

If a potential skip is identified, I switch to a fine-grained, day-by-day search within that window to pin down the exact henge date and time.

Bringing it all together

At this point, I had all the pieces working from the three steps I outlined at the start: 1) road bearings, 2) sun azimuths, and 3) a way to search for alignment dates. I wrapped it in a small website Hengefinder. You can enter the address of a spot you think would make a pretty view, and find its next henge. There’s also a “How Do Henges Work” explainer with interactive diagrams showing why henges happen at all, and why they’re rare. A third page, contributed by John Pribyl, lets you explore henges in your city more broadly.

A screenshot from Hengefinder for NYC for May 28 2026, with the cross-streets lighting up showing alignment with the sun during Manhattanhenge.

John has also taken this further and built a super cool Hengefinder mobile app. It extends the functionality to the moon, and lets you find “Sauron Henges,” where the sun (or moon) sits directly on top of a building (based on the Brooklyn Tower based event of this name, named after the Eye of Sauron in The Lord of the Rings).

”Ok, tell me about some fun henges.”

Having Hengefinder active means henges are now explorable outside of Manhattan, and I’ve been searching for them using the app. My favorite one so far, I haven’t actually seen. I’m intrigued by the Haarlemmertrekvaart, a canal which traces the southern edge of Westerpark in Amsterdam. Much of Europe turns out to be essentially un-hengeable, a consequence of medieval street design. But Amsterdam has a lot of many-century-old straight canals that were intended to be transportation routes between cities (horses needed paths without curves to pull large and heavy barges). Presumably, henges have been happening twice a year on the Haarlemmertrekvaart for the past four centuries, with the sun reflected in the water, perfectly lined up with the canal. As far as I know, there’s no announcement of a Haarlemmertrekvaart-henge. No one plans to see it.

John has been better than me at actually traveling to see never-announced henges. With his permission, here are some lovely photos of his henge explorations.

Some henges John has witnessed using Hengefinder. Clockwise from top left: 1) A "Sauron henge" at UT Austin Tower, a Sauron Henge at Taipei 101 (one of the tallest buildings in the world), A sunset henge on W 24th by UT Austin, and John's dog Luke enjoying a neighborly henge on a walk.

Henges are geometrically rare because the sun so rarely lines up. I think they feel even more rare because of how infrequently we find them. But these moments are happening all the time, all over the world, whether we watch them or not.