Thursday, June 10, 2010

Radiology classes open new paths

Train for your Radiology Degree
To stop further mailing, visit here or write:
PinpointMediaServices, 4255 E. Charleston Blvd. Suite D-345, Las Vegas, NV 89104
Okay, very cool. Took me a minute to figure out what you were suggesting, but I got it; and am having all the forwarded emails published as drafts in my blog, so that works as an effective inbox. And I don't have to go sign into Gmail separately to see what mail i've gotten. Thanks much buddy. I still wish there was a built in feature for an email inbox; but this will do fine. On Sep 8, 2:16 pm, nitecruzr wrote: On Sep 8, 11:32 am, Blue Truck , Red State wrote: So there's no way to have an email inbox right there on the blog itself, is that what you're saying? Use Mail-to-Blogger. Have the email sent to a GMail account, and setup the GMail account to forward it to the MTB address to your blog. And have MTB publish immediately. ... Chuck [Blog*Star 2006 - 2008] Am Dienstag 20 Oktober 2009 19:04:20 schrieb Matthew Woehlke: Okay, I am too lazy to use blog comments ;-). I sympathize with you, esp. for such long texts. ;-) Please don't take the following long lists of gripes the wrong way. My overall impression was quite favorable. As long as the gripes are constructive (which yours definitely are), I'm fine. (Even if grapes would be more desirable... Hmm... grapes.) In particular, I am very pleased that you avoid the typical mistake that pieces snap to their final positions, rather than each other. Real life doesn't work this way, but many computer jigsaw games have absolute places that define a piece 's "final position", and will lock pieces into place if you can position them correctly. Hm, I never had the idea to _not_ make it behave in the way it does now, although I might add an "easy mode" in which a faint impression of the final image appears at the bottom of the puzzle table, with pieces snapping to their position in this preview. - The default background ;-). I could use something that's a similar color, but the geometric texture doesn't say "table" to me. The others are all very nice, though all could use a bit less contrast. I think in general the table should have very, very low contrast (though it's good that it does *have* texture!). In fact, you might want to consider plugging a multi-octave perlin noise generator on top of the ability to choose any color for the table. The default background is the default because it was the only one when I added background textures. Also, it is the only one created by a KDE artist: Eugene, who drew it at a time when Palapeli did not support background textures yet, so he had no chance of testing it. My friends and I usually call this texture the "80s wallpaper", and I consider it an integral part of the Palapeli experience. ;-) Apart from these explanations, my hands are tied when it comes to creating softer backgrounds, 'cause I'm not a graphics designer. - Creating puzzles by number of pieces in X,Y direction. Please just give us approximate number of pieces , and let the slicer decide based on that, and the input image's aspect ratio. I accidentally made a 10x10 puzzle out of a 16:5 image... and I think some slicers (see below) won't be well defined by such dimensions. Good idea. The X-Y selection is there because it's more straight-forward. - No smooth shading when zooming in... pixels become quite obvious. Has been selled for performance. I'm not sure whether QGraphicsView does smooth shading for QGraphicsPixmapItems at all. - Puzzle pieces are raster; vector would be prettier. (Something to maybe improve some time in the future...) Palapeli's puzzle files contain pre-rendered raster images. That's a design decision: I want puzzle files to be easy, portable and self-contained. - Puzzle author is mandatory. Am I the author because I picked an image, slicer, and number of pieces ? That doesn't seem right. And if I get an image off the internet, there is a very good chance I don't know who produced that image. It says "image author" on purpose. Putting the image into a Palapeli slicer is not really an action that deserves attribution (at least when compared to creating the image). Bugs? ===== - Changing the table size doesn't seem to work with a puzzle in progress. Yes, bug. This problem will disappear when I rewrite the zooming and arranging stuff. - Severely deformed pieces can have overlapping cutouts, leading to XOR effects. Try making a puzzle with a bad aspect ratio (e.g. 3x as many pieces horizontally as vertically on a square image) and you should be able to reproduce this. However, other than violating some laws of physics, this didn't seem to break anything. This can probably be avoided by creating puzzles by total number of pieces instead (as suggested above). Hm, this shouldn't happen, but I have an idea why the algorithm could fail. Could you please test whether the jigsaw slicer generates better results with the attached patch applied? (You will have to rebuild the puzzles. Puzzles that have already been built won't change anymore.) - There is still a small bit of artifacting on pieces that are put together. (It's not bad, though.) You mean the thin lines between them? I cannot reduce them more, and have started to think of them as a feature: It allows you to distinguish assembled pieces just as you can in real life, because normal piece edges are rounded. - Delete puzzle doesn't appear to be hooked up. Are you trying to delete one of the default puzzles? If no, how did you create the puzzle? And do you have write access to the puzzle file? Future ideas: ============= - One technique I've often seen for doing puzzles is to separate the table from one or more boxes of pieces . This helps to categorize; you can toss all pieces that are, for example, a similar color into one box. I think it would be helpful to have a feature that would configure one or more "boxes", or even just piece groups, and a way to quickly move pieces (e.g. just by clicking on them) to a group. Anything sent to that group should then be clustered in close proximity, but not overlapping. Already on the list: "baskets". Whenever you want to separate a bunch of pieces from the rest, you create a basket and throw the pieces into it. Then you can either continue with the rest, or look into the basket and put the pieces in there together. (As you see, "baskets" is a bad name. It's highly non-obvious to play a jigsaw puzzle in a basket.) - Better random slicer. First off, I hope slicers don't have to lay pieces out in a grid (I think no?). What would really make palapeli rock is ability to cut pieces like real puzzles where pieces can be three or five sided, slightly offset, etc. Studying real jigsaws would be a source of many good ideas. Grid: Of course not. More reality in slicing: I'm focussing on other things currently. The current slicing is good enough for the start, though more reality is desirable. - Get new images from . Seriously, a large percentage of wallpapers would make decent puzzles as well, and kde-look is a ready source of such. Palapeli has infrastructure for "puzzle feeds", which provide a similar (yet better integrated) functionality. Unfortunately, there will not be enough time left for an interface to these. This gives me time to think about how to generate puzzles from images on the fly. Lastly, I'm not particularly interested in building playground/games. Any objection to the following patch? Index: CMakeLists.txt [...] I'm afraid that some build-system guy would complain about this kind of stuff, because it's not how it is supposed to be done, so for now I kindly ask you to keep this in your working copy. Alternatively, you can use a setup similar to mine, which is described on my blog ( , then the link at the very top right). Greetings Stefan -- Die Zukunft wird nicht gemeistert von denen, die an der Vergangenheit kleben. Index: slicers/slicer-jigsaw.cpp =================================================================== --- slicers/slicer-jigsaw.cpp (Revision 1038041) +++ slicers/slicer-jigsaw.cpp (Arbeitskopie) @@ -170,22 +170,22 @@ if (y == 0) path.lineTo(maskBaseRect.topRight()); else - addPlugToPath(path, topSide(maskBaseRect), QPointF(0, verticalPlugDirections[x][y - 1]), verticalPlugParams[x][y - 1]); + addPlugToPath(path, maskBaseRect.height(), topSide(maskBaseRect), QPointF(0, verticalPlugDirections[x][y - 1]), verticalPlugParams[x][y - 1]); //right plug if (x == xCount - 1) path.lineTo(maskBaseRect.bottomRight()); else - addPlugToPath(path, rightSide(maskBaseRect), QPointF(horizontalPlugDirections[x][y], 0), horizontalPlugParams[x][y].mirrored()); + addPlugToPath(path, maskBaseRect.width(), rightSide(maskBaseRect), QPointF(horizontalPlugDirections[x][y], 0), horizontalPlugParams[x][y].mirrored()); //bottom plug if (y == yCount - 1) path.lineTo(maskBaseRect.bottomLeft()); else - addPlugToPath(path, bottomSide(maskBaseRect), QPointF(0, verticalPlugDirections[x][y]), verticalPlugParams[x][y].mirrored()); + addPlugToPath(path, maskBaseRect.height(), bottomSide(maskBaseRect), QPointF(0, verticalPlugDirections[x][y]), verticalPlugParams[x][y].mirrored()); //left plug if (x == 0) path.lineTo(maskBaseRect.topLeft()); else - addPlugToPath(path, leftSide(maskBaseRect), QPointF(horizontalPlugDirections[x - 1][y], 0), horizontalPlugParams[x - 1][y]); + addPlugToPath(path, maskBaseRect.width(), leftSide(maskBaseRect), QPointF(horizontalPlugDirections[x - 1][y], 0), horizontalPlugParams[x - 1][y]); //determine the required size of the mask path.closeSubpath(); const QRect newMaskRect = path.boundingRect().toAlignedRect(); @@ -236,7 +236,7 @@ return true; } -void JigsawSlicer::addPlugToPath(QPainterPath& path, const QLineF& line, const QPointF& plugDirection, const JigsawPlugParams& params) +void JigsawSlicer::addPlugToPath(QPainterPath& path, qreal plugNormLength, const QLineF& line, const QPointF& plugDirection, const JigsawPlugParams& params) { //Naming convention: The path runs through five points (p1 through p5). //pNbase is the projection of pN to the line between p1 and p5. @@ -247,7 +247,7 @@ const QPointF growthDirection = plugDirection / sqrt(plugDirection * plugDirection); const qreal sizeFactor = line.length(); const QPointF growthVector = growthDirection * sizeFactor; - const QPointF plugVector = params.plugLength * growthVector; + const QPointF plugVector = params.plugLength * plugNormLength * growthDirection; //calculate points p2, p3, p4 const qreal t3 = params.plugPosition; const QPointF p3base = (1.0 - t3) * p1 + t3 * p5; Index: slicers/slicer-jigsaw.h =================================================================== --- slicers/slicer-jigsaw.h (Revision 1034879) +++ slicers/slicer-jigsaw.h (Arbeitskopie) @@ -40,7 +40,7 @@ explicit JigsawSlicer(QObject* parent = 0, const QVariantList& args = QVariantList()); virtual bool run(Pala::SlicerJob* job); protected: - void addPlugToPath(QPainterPath& path, const QLineF& line, const QPointF& plugDirection, const JigsawPlugParams& parameters); + void addPlugToPath(QPainterPath& path, qreal plugNormLength, const QLineF& line, const QPointF& plugDirection, const JigsawPlugParams& parameters); };