<?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: Asad Waseem</title>
    <description>The latest articles on DEV Community by Asad Waseem (@rx290).</description>
    <link>https://dev.to/rx290</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%2F4074735%2Fc07bde31-3ed4-43b7-880a-40c4ca0642af.jpeg</url>
      <title>DEV Community: Asad Waseem</title>
      <link>https://dev.to/rx290</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rx290"/>
    <language>en</language>
    <item>
      <title>Cura doesn't have connector generation. I built a plugin, and a one-click installer, that does.</title>
      <dc:creator>Asad Waseem</dc:creator>
      <pubDate>Sat, 22 Aug 2026 08:23:55 +0000</pubDate>
      <link>https://dev.to/rx290/cura-doesnt-have-connector-generation-i-built-a-plugin-and-a-one-click-installer-that-does-2cjk</link>
      <guid>https://dev.to/rx290/cura-doesnt-have-connector-generation-i-built-a-plugin-and-a-one-click-installer-that-does-2cjk</guid>
      <description>&lt;p&gt;OrcaSlicer and PrusaSlicer both let you generate mechanical connectors, plugs, dowels, snaps, dovetails, when you split a model for multi-part printing. Cura doesn't, and it doesn't expose an official plugin API you can hook into to add this the right way either. That gap is why cura-connect exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;p&gt;Two phases, verified at each step rather than assumed to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phase 1: a headless geometry engine, so I could get the actual connector math (plug clearances, dovetail angles, snap-fit tolerances) right in isolation before touching Cura at all.&lt;/li&gt;
&lt;li&gt;Phase 2: the real interactive Cura Tool, wired into Cura's UI so you can place and adjust connectors directly on a split model. Verified live against my own Cura 5.13 install, not just unit tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The vase mode fix
&lt;/h2&gt;

&lt;p&gt;Connectors were originally sized from the seam's overall bounding box, fine for a solid part, but wrong for a hollow or thin-walled model like a vase. On a real wavy vase test, connectors either landed in empty space or came out chunkier than the wall they were attached to. I fixed it so connectors now size themselves from the model's actual printer profile settings, wall thickness and line width, and test candidate placements against the real geometry instead of guessing from a box.&lt;/p&gt;

&lt;h2&gt;
  
  
  The installer
&lt;/h2&gt;

&lt;p&gt;I didn't want the only path to be wait for Marketplace approval. So there's now a real cross-platform installer in the repo (installer/install.py, plus double-clickable wrappers for each OS) that finds your Cura installation and drops the plugin into the right, correctly-nested folder automatically. Building it caught a real bug: my first version flattened the plugin into a single folder, but Cura requires a double-nested plugins///plugin.json layout to actually load it. Caught that by testing against my own real Cura install, not by assuming it would work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The Marketplace submission is still in review, that'll bring true one-click install from inside Cura once it's approved. Until then, the repo installer does the same job.&lt;/p&gt;

&lt;p&gt;What's already happening: people in the 3D Printing Pakistan community, printing on Creality and Qalam machines, have started using it and sending back live feedback, which is shaping what I fix and add next.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/rx290/cura-connect" rel="noopener noreferrer"&gt;https://github.com/rx290/cura-connect&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cura</category>
      <category>3dprinting</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building an offline CAD tool that can also turn photos into 3D meshes</title>
      <dc:creator>Asad Waseem</dc:creator>
      <pubDate>Sun, 16 Aug 2026 16:02:12 +0000</pubDate>
      <link>https://dev.to/rx290/building-an-offline-cad-tool-that-can-also-turn-photos-into-3d-meshes-181p</link>
      <guid>https://dev.to/rx290/building-an-offline-cad-tool-that-can-also-turn-photos-into-3d-meshes-181p</guid>
      <description>&lt;p&gt;I originally put PolyForge together as a ChatGPT skill, just for OpenSCAD, so I could describe a bracket or an enclosure and get back something I could actually print on my modified Ender 3 V2 or my QALAM Pro 400, instead of hand modeling every mount and shelf myself. It worked fine, but it only worked in ChatGPT, and it needed an agent and an API bill in the loop even for a plain shelf bracket. That felt backwards. A shelf doesn't need a language model to exist.&lt;/p&gt;

&lt;p&gt;So I pulled it apart and rebuilt it as PolyForge, a standalone Python package. No agent, no LLM required for the core. It runs the same whether you point Claude Code, ChatGPT, Gemini, or a local model at it, because the actual capability lives in the package itself, not in something only one vendor's assistant knows how to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does today
&lt;/h2&gt;

&lt;p&gt;A small library of parametric part templates (box, wall shelf, corner bracket, cable comb, standoff mount) gets filled in from plain text by keyword matching and regex extraction, then rendered to any of three CAD backends: OpenSCAD, FreeCAD, or Blender. All three produce the same geometry, dimension for dimension, for the same template and parameters, and every template is compile tested against the real binaries, not just unit tests.&lt;/p&gt;

&lt;p&gt;This week I added a fourth capability: offline photogrammetry. &lt;code&gt;polyforge reconstruct-from-photos&lt;/code&gt; takes a directory of overlapping photos of a real object and turns them into an STL, entirely offline, no cloud API involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  The COLMAP discovery
&lt;/h2&gt;

&lt;p&gt;The pipeline runs COLMAP for structure from motion. COLMAP also has its own dense reconstruction stage, the part that would normally take a sparse point cloud and turn it into something dense enough to mesh. I assumed it might need a GPU, but I didn't want to assume, so I ran it without one on purpose and watched what happened.&lt;/p&gt;

&lt;p&gt;It aborted immediately: "Dense stereo reconstruction requires CUDA, which is not available on your system." No CPU fallback anywhere in the mainline binary. That single test changed the whole architecture. Instead of one tool doing everything, the pipeline now uses COLMAP only for its CPU capable sparse reconstruction, then hands the result to OpenMVS, whose densify and mesh stages build CPU only by default, for the part COLMAP itself can't do without a GPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three patches to build OpenMVS
&lt;/h2&gt;

&lt;p&gt;Getting OpenMVS running on a rolling release system with a newer OpenCV than the package expected took three separate source patches. Its pinned vcpkg commit had a data schema too old for the installed vcpkg binary. Two OpenCV template specializations it defined itself collided with ones OpenCV now provides natively. And one constant, &lt;code&gt;cv::DIST_L1&lt;/code&gt;, had been removed from OpenCV's imgproc module entirely, so I inlined the literal value at the one call site that needed it. None of this is really about PolyForge, it's just what building against a system that moves faster than an AUR package's last update looks like in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually breaks a reconstruction
&lt;/h2&gt;

&lt;p&gt;Once the pipeline worked, I wanted to know where its real limits were, not the ones I assumed. So I ran an extensive test matrix: different photo counts, different camera coverage patterns, a more geometrically complex part, and timed every stage.&lt;/p&gt;

&lt;p&gt;The biggest finding surprised me. I expected photo count to matter most. It doesn't. A camera orbit at a single elevation fails outright no matter how many photos you take, even 24 of them. You need at least three elevation rings. Once you have that, thirty photos across three rings reconstructed cleanly, twenty seven did not.&lt;/p&gt;

&lt;p&gt;The second finding was about where the time actually goes. I assumed the matching stage, which compares every pair of photos, would be the bottleneck as photo count grew. It barely moved. The real cost is COLMAP's incremental bundle adjustment: about three seconds at sixteen photos, over two minutes at thirty six, a much steeper jump than the photo count alone would suggest. And it scales with the object's geometric complexity too, not just the count. A bracket with concave, non convex features took six times longer than a plain box at the same photo count, even though both reconstructed correctly in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;Four phases in, PolyForge can generate parts from text across three CAD backends and reconstruct a mesh from a folder of photos, all without a cloud API or a GPU. The reconstructed mesh is not perfect: it has no absolute scale until you measure something known on the real object and rescale it, and it usually isn't watertight since a camera orbit can't see a surface's underside. Both of those are honest limitations of photogrammetry itself, not bugs, and I'd rather say so plainly than pretend otherwise.&lt;/p&gt;

&lt;p&gt;Repo's public if you want to look at the actual code: github.com/rx290/polyforge&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>computervision</category>
      <category>python</category>
    </item>
    <item>
      <title>How I built a Claude Code skill that finds funded scholarships without burning your token budget</title>
      <dc:creator>Asad Waseem</dc:creator>
      <pubDate>Wed, 12 Aug 2026 11:49:02 +0000</pubDate>
      <link>https://dev.to/rx290/how-i-built-a-claude-code-skill-that-finds-funded-scholarships-without-burning-your-token-budget-4mlh</link>
      <guid>https://dev.to/rx290/how-i-built-a-claude-code-skill-that-finds-funded-scholarships-without-burning-your-token-budget-4mlh</guid>
      <description>&lt;p&gt;I went looking for something that could find fully-funded PhD and Master's programs in Europe, matched to my own grades and field. What I found on GitHub was three small, disconnected projects, and none of them actually worked for what I needed.&lt;/p&gt;

&lt;p&gt;One only covers professors in the US, UK, Canada, and Australia. Another needs its own separate paid LLM API key and a Feishu account just to rank a list. A third has no idea what a funding scheme even is, and none of them cover anything below a PhD, even though there's just as much scholarship money for undergrads.&lt;/p&gt;

&lt;p&gt;So I read through all three, kept the ideas that were actually useful, and rebuilt the rest from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;GrantCompass is a Claude Code skill plus a standalone CLI. Point it at a field and a grade, and it finds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fully-funded scholarships and programs at any degree level (Bachelor's, Master's, PhD), any country, defaulting to Europe if you don't name one&lt;/li&gt;
&lt;li&gt;Professors doing relevant research if you're applying to a Master's or PhD, pulled from OpenReview and OpenAlex, both free public APIs&lt;/li&gt;
&lt;li&gt;A score for each result: whether your grade comfortably meets what a scheme typically expects, is borderline, or falls below it. It never silently drops a result over that, you make the call.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part I actually care about
&lt;/h2&gt;

&lt;p&gt;Most of these tools work by scraping a bunch of web pages and dumping the results into an LLM's context. That's slow and it burns a lot of tokens for something that's mostly just fetching and filtering, work a model doesn't need to do.&lt;/p&gt;

&lt;p&gt;So the fetching, parsing, and scoring here all happen in plain Python behind the CLI. The agent only steps in for two things: asking a couple of onboarding questions, and pulling current listings from sites that don't have a stable API. Even then, it reads back exactly one compact table, not the raw pages it fetched.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grantcompass init
grantcompass professors
grantcompass score
grantcompass report
&lt;span class="nb"&gt;cat &lt;/span&gt;output/report.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why not just scrape DAAD or FindAPhD directly
&lt;/h2&gt;

&lt;p&gt;None of them expose a real public API, and scraping risks breaking their terms of service, plus it breaks the moment they redesign the page. That's basically what happened to the projects I looked at before building this. The only script here that makes its own HTTP calls is the one doing professor discovery, and it only talks to OpenReview and OpenAlex, both built for this kind of programmatic access. Everything else gets fetched live, one page at a time, by Claude's own web search, closer to how a person would actually go look it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;No code came from the two prior-art repos with no license attached, only the ideas did. Full writeup on that, and everything else, is in the README.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/rx290/grant-compass" rel="noopener noreferrer"&gt;https://github.com/rx290/grant-compass&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're also hunting for funded programs, or just curious how a token-conscious Claude Code skill is put together, take a look. Feedback and PRs welcome.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>python</category>
    </item>
  </channel>
</rss>
