<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: nongyi531415</title>
    <description>The latest articles on DEV Community by nongyi531415 (@nongyi531415).</description>
    <link>https://dev.to/nongyi531415</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4120789%2F69a88dd8-d1d3-468e-a18b-b86aeff461ad.png</url>
      <title>DEV Community: nongyi531415</title>
      <link>https://dev.to/nongyi531415</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nongyi531415"/>
    <language>en</language>
    <item>
      <title>Why nuke simulators show different numbers (and how to compare them)</title>
      <dc:creator>nongyi531415</dc:creator>
      <pubDate>Fri, 02 Oct 2026 14:37:02 +0000</pubDate>
      <link>https://dev.to/nongyi531415/why-nuke-simulators-show-different-numbers-and-how-to-compare-them-5a7h</link>
      <guid>https://dev.to/nongyi531415/why-nuke-simulators-show-different-numbers-and-how-to-compare-them-5a7h</guid>
      <description>&lt;p&gt;After I posted a short video of a simulated 15 kiloton airburst, a viewer commented that they had checked another calculator and got different numbers. That is a fair point, and the answer is not that one tool is broken. Blast simulators make different modelling choices, and those choices move the rings a lot.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://kaboomly.app/" rel="noopener noreferrer"&gt;Kaboomly&lt;/a&gt;, a free nuke map that runs in the browser, so here are the four choices that matter most.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Airburst or surface burst
&lt;/h2&gt;

&lt;p&gt;The same weapon behaves very differently depending on where it goes off. An airburst spreads the blast wave over a wider area, so the light-damage rings get bigger. A surface burst gives smaller blast rings but pulls soil into the fireball and creates local fallout. Some tools default to one, some to the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Burst height
&lt;/h2&gt;

&lt;p&gt;Even among airbursts, height matters. There is a height that maximizes the area of a given overpressure, and it is different for every pressure level. Kaboomly does not optimize this. It takes one documented historical example, Hiroshima at about 1,670 ft for roughly 12.5 kt, and scales it with the cube root of the yield. A tool that picks a different height will show different rings for the same yield.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Which threshold a ring represents
&lt;/h2&gt;

&lt;p&gt;A ring labelled "heavy damage" might be drawn at 5 psi in one tool and at 10 or 20 psi in another. Thermal rings can mean first, second or third-degree burns, and the distance changes a lot between them. Always check the legend before comparing two maps.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scaling law and source data
&lt;/h2&gt;

&lt;p&gt;Most public calculators, including NUKEMAP and Kaboomly, trace back to &lt;em&gt;The Effects of Nuclear Weapons&lt;/em&gt; by Glasstone and Dolan (1977). Blast distances scale with the cube root of yield, so ten times the yield gives only about 2.15 times the distance. The fireball has its own scaling, about W^0.4. Tools that use rounded rules of thumb instead of the published curves will drift, especially at very small or very large yields.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example
&lt;/h2&gt;

&lt;p&gt;For a 15 kt airburst Kaboomly shows the 5 psi ring at about 1.6 km (1.0 mi) and the 1 psi ring at about 4.5 km (2.8 mi). If another tool uses a surface burst or a different height, its numbers for the same yield can be noticeably smaller or larger, and both can be correct for their own assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did about it
&lt;/h2&gt;

&lt;p&gt;On Kaboomly every result shows the burst type and the thresholds, and there is a page explaining &lt;a href="https://kaboomly.app/how-it-works/" rel="noopener noreferrer"&gt;how the numbers are calculated&lt;/a&gt; with references. The site never shows casualty estimates, only the rings and the number of residents living inside an area.&lt;/p&gt;

&lt;p&gt;If you compare simulators, compare like with like: same yield, same burst type, same threshold. The differences mostly disappear.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>maps</category>
      <category>history</category>
    </item>
    <item>
      <title>Splitting a large image across multiple printed pages without alignment marks</title>
      <dc:creator>nongyi531415</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:46:00 +0000</pubDate>
      <link>https://dev.to/nongyi531415/splitting-a-large-image-across-multiple-printed-pages-without-alignment-marks-115c</link>
      <guid>https://dev.to/nongyi531415/splitting-a-large-image-across-multiple-printed-pages-without-alignment-marks-115c</guid>
      <description>&lt;p&gt;I recently added tiled printing to a small static tool I run (&lt;a href="https://griddrawing.org" rel="noopener noreferrer"&gt;ArtGrid&lt;/a&gt;) — the kind of "print a big image across several A4 sheets and tape them together" feature you've probably seen in poster-printing tools. The naive version is easy: slice the enlarged image into a grid of page-sized rectangles, export each as a PDF page. The annoying version is making the pieces line back up on paper, where a fraction of a millimeter of printer scaling error compounds across every seam.&lt;/p&gt;

&lt;p&gt;Most tools solve this with &lt;strong&gt;alignment marks&lt;/strong&gt; — corner crosses or registration dots you have to trim to and match by eye. I skipped that entirely by changing where the cuts land.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick: cut on lines that are already there
&lt;/h2&gt;

&lt;p&gt;My tool overlays a grid on the reference image — rows and columns of equal square cells, used for the classic grid-method drawing technique. Once you're enlarging that grid to poster size, you already have a full set of straight lines running across the whole surface. If every page boundary is forced to land exactly on one of those grid lines, the seam &lt;em&gt;is&lt;/em&gt; the line. There's nothing to trim, because the join is a continuation of a mark you were going to draw anyway.&lt;/p&gt;

&lt;p&gt;The constraint this puts on the math: instead of dividing by fixed page dimensions, you divide by &lt;strong&gt;however many whole cells fit on a page&lt;/strong&gt;, and let the last row/column of pages be a partial page if it doesn't divide evenly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tileGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GridGeometry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;TileResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tileArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paper&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// printable area minus margins&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drawingCell&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`cell &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mm exceeds printable area`&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colsPerPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rowsPerPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pagesX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;colsPerPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pagesY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;rowsPerPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;colsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rowsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pagesX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pagesY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pageCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pagesX&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;pagesY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each page then covers a &lt;code&gt;[colStart, colEnd) × [rowStart, rowEnd)&lt;/code&gt; slice of cells, and the pixel crop for that page is just that slice's bounding box in the source image, scaled the same way the whole grid was scaled. Cutting on &lt;code&gt;floor(printable_area / cell_size)&lt;/code&gt; rather than on the raw page dimension is the entire trick — it's a one-line change from "divide by page size" that removes a whole category of physical-alignment UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this only works if the cells are square
&lt;/h2&gt;

&lt;p&gt;This only holds together because every cell is guaranteed to be the same width and height. If rows and columns are sized independently — which most grid tools do, because it lets you fill the page edge-to-edge — a "cell" isn't a fixed unit you can tile against, and you're back to needing marks. Forcing square cells (deriving whichever axis you didn't set, rather than letting both float to fill the sheet) was originally a decision about drawing accuracy — a square cell's diagonal is a clean 45°, useful for judging angles by eye — but it turned out to be the same property that makes tiling trivial later. One geometric constraint paid for two unrelated features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the seams
&lt;/h2&gt;

&lt;p&gt;The part I actually didn't trust until I checked it: does the printable rectangle reconstructed from all the tiles equal the original enlarged rectangle, to the millimeter? I wrote this as a standalone assertion rather than trusting the math by inspection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topRowWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rowStart&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tileRectMm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;topRowWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;drawingRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— summed the top row's page widths, summed the left column's page heights, compared both against the target enlargement size. It matched to a hundredth of a millimeter, which is the point where you stop worrying about floating point and start worrying about your actual printer's calibration instead (which is why there's still a 50mm ruler printed on the first page — measure it, and if your printer scaled the page, you'll catch it before taping together nine sheets).&lt;/p&gt;

&lt;p&gt;If you want to see the live version: &lt;a href="https://griddrawing.org/print-large-image-multiple-pages" rel="noopener noreferrer"&gt;griddrawing.org/print-large-image-multiple-pages&lt;/a&gt;. It's a static site, runs entirely client-side, source reference stays in the browser tab.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>canvas</category>
      <category>math</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
