natevw proudly presents:

a glob of nerd­ish­ness

powered by work over time.

Thoughts on FDM

I take a long-term view of 3D printing.

Not the stupid journalist swoon line of Everyone Will Print Everything Soon. Everyone needs to print their own iPods in the future just about as badly as everyone needs to print their own grainy ABS miniatures in the present. I don't see a demand for it, I don't see a benefit, and I don't see it happening.

So I should say: I take a long-term view of owning a 3D printer.

Like a welder or a sewing machine, there's an enjoyment in keeping crafts alive. There is an eventual return on investment in the equipment itself as well — perhaps over more than one generation. And the mere fact that plastic printers, CNC mills and laser cutters are now being designed with affordability and openness as the first motivation is awesome. I think this means a lot of good in education and economic development (both in overbuilt or underbuilt economies).

Gridded globe print in progress

It's been interesting to see what people are sharing and printing on Thingiverse. A majority of "things" currently available there for 3D printing are either: limitless small printer kit modifications such that one wonders if the goal of assembling a 3D printer is to spend subsequent weekends assembling it better, or: dis-glorified Happy Meal® toys. Some of the models are terribly cool — who doesn't want to watch a scale B-17 bomber or a miniature London Bridge materialize hypnotically before their very own eyes! — but you know those machines at the zoo where you could put in a bunch of quarters and go home with a hollow elephant, freshly molded from pink plastic?

Gradually, the open source three-dimensional printing community is accreting a collection of replacement pieces, and of speciality parts, and of customizable components with applications beyond printing for its own sake or that of souvenirs. Artists are finding their way within the new medium, too, working wisely within its limitations to create things of real aesthetic value.

It's humbling to be a tiny part of this, to experience its realities firsthand at some level, and to dream about how (perhaps) to make it matter more.

In the meantime…it's fun. And that matters too.

comments

The three ways to remove a document from CouchDB

So you're using CouchDB because it has a great RESTful interface for managing data. PUT a JSON document in with various options, GET it back later through several means. Did you know that how you DELETE can also affect how your document is persisted?

Let me to explain.

Door number one: DELETE

You PUT a document {"_id":"mydoc", "some_data":42} into your database. You fetch this document directly via GET /whatever_db/mydoc, and the simplest way to "get rid of it" is to DELETE /whatever_db/mydoc. That's a bit oversimplified because you do also have to include the MVCC revision token, but modulo that, it's pretty much what you'd expect from a REST API.

Door number two: _deleted

The other way is to make a document stop showing up is to PUT/POST it with a special field: {"_id":"mydoc", "some_data":42, "_deleted":true}

Door number three: don't forget this

The third way is usually the wrong way, and it's not really "deletion" in the normal sense. You can POST document info to a database's _purge API to erase CouchDB's memory of it. The data is still on disk until after database/view compaction and similar disk storage caveats have been taken care of, but the data will cease to exist as far as the API is concerned.

Wait…deleted data doesn't normally cease to exist? To delete a document, its wrong for CouchDB to actually remove it?!

Right. The CouchDB wiki explains it this way:

Deleted documents remain in the database forever, even after compaction, to allow eventual consistency when replicating. If you delete using the DELETE method above, only the _id, _rev and a deleted flag are preserved. If you deleted a document by adding "_deleted":true then all the fields of the document are preserved. This is to allow, for example, recording the time you deleted a document, or the reason you deleted it.

Syncing _changes is foundational to CouchDB's data model; not forgetting deleted documents lets masterless replication bring each instance into a shared state.

Gone but not forgotten: newspaper left at an abandoned property

Which one should you use?

The choice depends (mostly) on how you're syncing between databases:

Simply DELETEing a document could break filtered replication. If a filter function only makes changes visible based on, say, an application-specific "type" or "user" field, these fields will not be present in the final {"id":"mydoc","_deleted":true} stub left behind by a simple DELETE. Consider this filter function, equivalent to the one in the filter function guide:

function(doc, req) {
  if (doc.name && doc.name == req.userCtx.name) {
    return true;
  } else {
    return false;
  }
}

This filter only exposes revisions if there is a "name" field and it matches the session's user information. Revisions resulting from a DELETE request will not have any "name" field. That change won't get passed along — so the document will be left in the target database as-is! In order to propagate deletes, either the document's other fields should be retained in its _deleted version (by using PUT/POST instead of DELETE) or the filter function would need to return true after checking if (doc._deleted), before assuming any other fields.

Consistency

Even if you're using filtered replication, leaving full documents of data which is no longer needed might be undesirable. Remember that the final form of a document will eventually propagate to all databases. Especially if your documents are large or the frequency of deletions is high, there's no sense wasting bandwidth and disk space just to work around a naïve filter function.

Note that simply propagating all deletions to avoid the filtering issue has its own drawbacks, though. If you're using filtered replication because the target has limited storage space, or to keep private data private, copying the last version of every deleted document to every replica is not a good solution. At best it would be a waste of resources, at worst it could leak sensitive data — especially if some parts of your app are simply flagging original contents as deleted, while some of your filters are assuming that any delete is safe to propagate!

A hybrid solution might be appropriate: if you know which fields are relied on, across all of your replication filters, you could store those in the final revision while omitting the others. This enables filter functions to remain picky about what they pass, while increasing space savings after compaction and slightly mitigating the risk of an inadvertently propagated delete.

When you're consistently aware of the implications, any method can be used to control the final state of a document — just make sure its last words are the most appropriate epitaph.

comments

Metakaolin: GeoJSON editor for Polymaps, now with multitouch support!

I'm going mobile with Metakaolin.

Metakaolin open on MacBook Air and Nexus 7

This had always been the plan as I came up with its editor design, just ended up on the back burner for a while.

What got me off my duff was noticing that my Argyle Tiles preview map was fairly broken on SVG-supporting Android browsers. It showed up, and panning worked, but any pinch zoom caused the map to go blank until the page was refreshed. Some sort of bug in Polymaps' code, and since I was involved in getting its multitouch support landed I felt more than a tinge of responsibility.

Aaaaaand....also I'd been wanting to get a Nexus 7 anyway.

After the price dropped a few weeks ago, I picked up the 16GB model and got to work. (The Nexus 7 is an excellent piece of hardware, by the way, and I've been really impressed by how modern Android 4.1 feels.) Turns out that Chrome does provide W3C-standard touch events — and also includes pressure information! — but it does not add any additional scale/rotation gesture information as Safari does on iOS. So as soon as you tried to zoom, the code tried to adjust the map to zoom level undefined ± something which didst upset it surely.

Filling in for that has been a decent bit of work, especially since event handling on the Polymaps master branch was making some other incorrect touch tracking assumptions in addition to the gesture info. Chrome's remote debugging worked really well and fortunately everything carried over well to Firefox and iOS 5's Safari. I'm reasonably happy with this implementation; it's both somewhat simpler than my Magic Mouse gesture interpretation logic yet reacts to zooming with as many fingers as you've got.

Once that was working, it was time to hook in touch event tracking to my editing layer. It ended up being a fairly straightfoward process, the original logic stood up pretty well to some slight wrapping/refactoring. What didn't survive were some of the marginal hover-based affordances and the tiny control handles from desktop use! When you load it on a touch device, there's now generous finger room, at least on the node handles, and I've got some visual design ideas that should improve usability and discoverability for both direct and indirect (i.e. mouse) interaction once they're implemented.

Rotated map with line feature drawn over part of the Columbia River, screenshot from Android Chrome

So: now I have a completely non-modal vector graph editing interface that talks GeoJSON and can be used on a desktop, laptop, iPad, and even a $200 Android tablet.

I've posted a short demo video, you can fork the source code, or why not try the editor yourself and let me know what you think!

Coming up next? Well, Mozilla's Dev Derby theme for December is offline apps. Since I completely spaced on the geolocation one in September, I'm kind of determined to make up for it next month.

comments

Why build products?

My lame attempt to channel Calvin and Hobbes aside, @stevenf poses a question without an easy answer:

"@stevenf: License your patent and you become a millionaire. Build something and you grovel for reviews to keep another 99c (less 30%) rolling in. What's the incentive to make anything then?"

For about two years, I enjoyed making and supporting quality shareware with a good friend, feeling as if I were built for that very purpose. The company had just barely turned a profit — because we were not paying ourselves nada! — and so by then we'd run out of personal savings. Hrm. We found other ways to feed our families, which generally meant giving bigger businesses what they asked for, instead of what we thought independent individuals really needed.

I've been scared to risk much on my latest product because I can already see the same story playing out (quicker this round!) if I'm not careful. Had an amazing time announcing Argyle Tiles at SOTMUS and WhereCampPDX, meeting lots of mapping heroes as well as a bunch of encouragers who were excited to see the product. It's really hard though, looking back at just how little those two years of ware-sharing turned into when sold at $20 a pop.

Wondering how on earth I can afford to map all of it. And then offer it at people's preferred price point of "free". (Don't worry too much about the project though, I mentioned there were a lot of mapping heroes around Portland last weekend, right?)

How do you make shrink-wrapped software without it also being gift-wrapped, financially speaking? That I don't know yet. But there are incentives:

While Apple is weak on the "inspiring" these days, knowing that if I had skipped the tag-along business attempt, accepted my first day job, and instead invested all my savings directly into Apple's stock price… knowing that would have returned around 800% if sold today… and yet not really wishing I could trade that for what I've made…

That's inspiring.

Making your ideas happen is priceless. If all the pieces fall into place, you may even have a lot of users who feel the same way — it's sure worked out for Apple a few times.

If not, you should be able to find at least one customer who needs their ideas made; whose ideas are at least valuable enough that they already have the necessary financials available. It's not as glamorous, but it's not about you anyway.

Turning any good idea into an actual product — especially a digital product — is far more valuable than simply turning any old idea into income. You may not capture all that value but when you've done that work the value is there in the best form it could be shared. It's fair to expect enough value returned to keep the cycle sustainable; life isn't always fair, but often it can be a living.

That's inspiring enough, I hope.

comments

Whatever you do

Many months ago I started using a lovely web app called Habitualist to prod myself out of my routines (which tend to be reclusive) and into trying new things and meeting new people. It's too early to tell if it's working, but I'm glad for the reminder that at one point I decided to work on (and talk about!) my own research and development at least a little bit every week:

Habitualist dashboard

I've failed to do that, and more. The last few months have been a tumultuous time. Hospital bills started rolling in, I started getting drained both by cycling everywhere and reluctantly shopping for an affordable fossil-fueled alternative. Between August and September, as the days grew shorter, I careened from not quite enough playing around to not nearly enough breadearning.

Depression focuses you on the wrong things: why yesterday went wrong, how I'm working all wrong today, all that's going wrong with where I'd wanted to be tomorrow.

If I could focus on anything at all. Stupid ADD, stupid me. You keep sleeping in. And then you stop caring.


You know what's exciting? Every new day.

Don't stop caring, about the right things.

comments


All posts

Subscribe