Thursday, November 30, 2017
Quiet Today
I've been rather quiet today, tied up with Day Job. But tomorrow is Friday. Hopefully that will give me a chance to come up with something. Until then, good night.
Wednesday, November 29, 2017
Digging Into the Past
The other day, I was trying to look up some information about an interurban trolley company in northwestern New Jersey. As is often the case, the internet was of only a little use in this regards. Popular interurbans, the well-known lines situated in metropolitan areas and were lucky enough to last past World War II, usually have a little bit about them online. This was not one of those.
Online, I found one brief thread on a discussion forum, and a paragraph in an online preview of a recent print book about Phillipsburg, NJ. Offline, I found a single paragraph in The Electric Interurban Railways in America by Hilton & Due. A few sentences are interspersed into Morris County Traction Company by Lowenthal and Greenberg, which also contained a map of unstated origin that covered the line's actual and project map (though not in detail). That exhausted the regular web searches and my printed secondary sources.
From all that I really gathered only a few facts. The line lasted a little over a quarter century. It operated between Phillipsburg, NJ on the west and Port Murray, NJ on the east. Most of the route followed the Morris Canal. The owners hoped to extend eastward to Netcong, NJ, to connect with the Morris County Traction Company, which never managed to build its extension to Netcong. They hoped to expand west to Easton, PA by crossing the Delaware River, but contentious relations with the company operating streetcar service there and in Phillipsburg prevented it. Ultimately, that company bought the interurban out. The company changed names a few times along the way.
I'm leaving out a few dates and proper names, but those are the bare facts a couple hours of research gave me - roughly the same information I started with from Hilton & Due, except for the marginally-useful map and the fact that the line followed the canal.
Sigh.
Next up, reading what primary sources are available from hundreds of miles away: decades of railway journals scanned by Google and made available online. Not so easily searchable as a simple web search, though, for a variety of reasons (poor OCR quality being one of them). When I have a chance, I'll see if I can ferret out anything more.
Anyhow, after Sarah Hoyt's recent "Facts are Facts" post, I thought I'd mention my own attempt to dig up some facts from the not-so-distant past. It hasn't been going so great.
Online, I found one brief thread on a discussion forum, and a paragraph in an online preview of a recent print book about Phillipsburg, NJ. Offline, I found a single paragraph in The Electric Interurban Railways in America by Hilton & Due. A few sentences are interspersed into Morris County Traction Company by Lowenthal and Greenberg, which also contained a map of unstated origin that covered the line's actual and project map (though not in detail). That exhausted the regular web searches and my printed secondary sources.
From all that I really gathered only a few facts. The line lasted a little over a quarter century. It operated between Phillipsburg, NJ on the west and Port Murray, NJ on the east. Most of the route followed the Morris Canal. The owners hoped to extend eastward to Netcong, NJ, to connect with the Morris County Traction Company, which never managed to build its extension to Netcong. They hoped to expand west to Easton, PA by crossing the Delaware River, but contentious relations with the company operating streetcar service there and in Phillipsburg prevented it. Ultimately, that company bought the interurban out. The company changed names a few times along the way.
I'm leaving out a few dates and proper names, but those are the bare facts a couple hours of research gave me - roughly the same information I started with from Hilton & Due, except for the marginally-useful map and the fact that the line followed the canal.
Sigh.
Next up, reading what primary sources are available from hundreds of miles away: decades of railway journals scanned by Google and made available online. Not so easily searchable as a simple web search, though, for a variety of reasons (poor OCR quality being one of them). When I have a chance, I'll see if I can ferret out anything more.
Anyhow, after Sarah Hoyt's recent "Facts are Facts" post, I thought I'd mention my own attempt to dig up some facts from the not-so-distant past. It hasn't been going so great.
Tuesday, November 28, 2017
Canvas Test
This post is a test to see if I can use the HTML5 Canvas and JavaScript within a Blogger post.
If you see a circle below, it worked. :)
It worked for me, in preview. I used some very simple examples from the w3schools.com HTML5 Canvas page. I'm going to have to consider doing the Shapes series I was working on as HTML5 Canvas + JavaScript rather than the C# I was originally working on, so people can play with it interactively.
If you see a circle below, it worked. :)
It worked for me, in preview. I used some very simple examples from the w3schools.com HTML5 Canvas page. I'm going to have to consider doing the Shapes series I was working on as HTML5 Canvas + JavaScript rather than the C# I was originally working on, so people can play with it interactively.
Link: Genetics and Extinction
Author and scientist Cedar Sanderson has an interesting blog post today about genetic paucity and extinction. I found it quite fascinating, and worth a look.
Monday, November 27, 2017
Terminal Moraines
This is just a brief musing on the impact of glaciers on terrain. I won't go getting into the science of it too much, but glaciers can create or alter terrain features in interesting ways - in addition to being terrain features in their own right. One of the features they leave behind after they retreat are terminal moraines.
Moraines are masses of rock that the glaciers convey to their edge. The rocks vary in size, all the way down to the size of gravel and sand, and they accumulate. When the glaciers retreat, the accumulation that is left behind forms a hill or ridge.
On an otherwise relatively flat landscape, such a hill or ridge could stand out. It need not be uniform, especially after erosion may have redistributed it. So you can get irregular or lumpy ridges. Or a collection of hills. Or, if moraine was left in what is now a lake or sea, islands. Many of the islands in Long Island Sound are the remnants of the terminal moraines from the last glacial maximum. Some are not though, the Thimble Islands for example being the remnants of rocky hills that were partially ground away by glaciers.
Moraines are masses of rock that the glaciers convey to their edge. The rocks vary in size, all the way down to the size of gravel and sand, and they accumulate. When the glaciers retreat, the accumulation that is left behind forms a hill or ridge.
On an otherwise relatively flat landscape, such a hill or ridge could stand out. It need not be uniform, especially after erosion may have redistributed it. So you can get irregular or lumpy ridges. Or a collection of hills. Or, if moraine was left in what is now a lake or sea, islands. Many of the islands in Long Island Sound are the remnants of the terminal moraines from the last glacial maximum. Some are not though, the Thimble Islands for example being the remnants of rocky hills that were partially ground away by glaciers.
Voting Can Make a Difference
I was talking with some of my family over the holiday, and they mentioned the recent elections in their town. The councilman for their district won by one vote. If my relatives had not gone to the polls, the councilman would have lost.
Sometimes it seems like who we vote for doesn't matter - the politicians get in anyway. But even when there aren't good candidates, when the choices are unpalatable, there are often reasons to pick one candidate over the other, if only to keep the worst candidate out of office.
Sometimes one candidate may have such overwhelming support a few people not showing up to the polls one way or the other. If enough people do that, though, it can start to make a difference. And sometimes that one vote, or two, or three, is enough to make the difference.
Sometimes it seems like who we vote for doesn't matter - the politicians get in anyway. But even when there aren't good candidates, when the choices are unpalatable, there are often reasons to pick one candidate over the other, if only to keep the worst candidate out of office.
Sometimes one candidate may have such overwhelming support a few people not showing up to the polls one way or the other. If enough people do that, though, it can start to make a difference. And sometimes that one vote, or two, or three, is enough to make the difference.
Bad Football, Good Holiday
The Thanksgiving holiday was a wonderful time spent with family and family friends. Food and fun were in abundance. A good, new hike was found. New foods were tried. And football.
Bad football. I watched the Giants-Redskins game on TV Thursday evening. It was a pitiful display by the Giants, but at least it was only on TV. We could just shut the TV down, and wander off to our beds.
I watched Michigan State-Rutgers game in person. Traffic enroute was tolerable. The weather was perfect. I got a nice intercampus walk from where I parked to the stadium. I saw some family friends I hadn't seen in ages at the tailgate. And that was all the positive that can be said. Rutgers looked even more pitiful than the Giants had two nights before. The stadium suffered a water pressure and was redirecting people to the portable toilets outside.
At least Ohio State beat Michigan, so random residents of the state of Michigan will not be making as many derisive remarks. Not that I went to The Ohio State University (note the definite article), nor am even a fan of Ohio State. But I do live in the Buckeye State, which seems to be a sufficient condition for obnoxious Michiganders to start talking trash in years Michigan won. Why? Maybe it dates back to the "war" for the Toledo Strip, maybe it is more recent. Anyway, another year I don't have to deal with it.
And now I'm home, and shall resume normal blogging again in the morning. While resuming ignoring football as much as possible. Not that I don't enjoy watching the occasional game, but its more fun watching with friends and family - and none of my family are local and none of my friends are football fans. Without that extra bit to it, I might as well read a book or take a walk. Thus ends the ranting and raving. Have a great morning, everybody!
Bad football. I watched the Giants-Redskins game on TV Thursday evening. It was a pitiful display by the Giants, but at least it was only on TV. We could just shut the TV down, and wander off to our beds.
I watched Michigan State-Rutgers game in person. Traffic enroute was tolerable. The weather was perfect. I got a nice intercampus walk from where I parked to the stadium. I saw some family friends I hadn't seen in ages at the tailgate. And that was all the positive that can be said. Rutgers looked even more pitiful than the Giants had two nights before. The stadium suffered a water pressure and was redirecting people to the portable toilets outside.
At least Ohio State beat Michigan, so random residents of the state of Michigan will not be making as many derisive remarks. Not that I went to The Ohio State University (note the definite article), nor am even a fan of Ohio State. But I do live in the Buckeye State, which seems to be a sufficient condition for obnoxious Michiganders to start talking trash in years Michigan won. Why? Maybe it dates back to the "war" for the Toledo Strip, maybe it is more recent. Anyway, another year I don't have to deal with it.
And now I'm home, and shall resume normal blogging again in the morning. While resuming ignoring football as much as possible. Not that I don't enjoy watching the occasional game, but its more fun watching with friends and family - and none of my family are local and none of my friends are football fans. Without that extra bit to it, I might as well read a book or take a walk. Thus ends the ranting and raving. Have a great morning, everybody!
Friday, November 24, 2017
Grasping for the Crowns
The latest book in Alma T.C. Boykin's The Power series, Grasping for the Crowns, has just been released. I haven't yet had a chance to purchase and read it yet, but I've waiting for this sequel since I finished reading the first book. I shall likely review this one at soon time.
Thursday, November 23, 2017
Happy Thanksgiving
Happy Thanksgiving! I hope anybody reading this is sharing a delicious meal with loved ones today, and that there's much to be thankful for.
Wednesday, November 22, 2017
NYPD: Not Your Polite Driver
We've all been there. Rolling down the highway in the left lane, stuck, unable to pass because the driver of the car ahead won't put the pedal to the metal and pass the huge truck in the right lane. Sometimes a whole line of cars forms in the left lane, waiting for that one darn driver to pass. What you don't expect is for the car beyond you, the one that decides to tailgate, to be an NYPD van.
Especially when you're not in New York state and are hundreds of miles from NYC. And if it is such a van, surely more than a half car length is called for at 70 mph. Or at least not swerving wildly out of control. Just saying.
Especially when you're not in New York state and are hundreds of miles from NYC. And if it is such a van, surely more than a half car length is called for at 70 mph. Or at least not swerving wildly out of control. Just saying.
Monday, November 20, 2017
Book Review: 1637: The Volga Rules
About a week ago, I posted a short note about the recently-released electronic Advanced Reader Copy (eARC) for 1637: The Volga Rules, a new novel in the Ring of Fire (1632) series. This one novel has as its authors Eric Flint, Paula Goodlett, and Gorg Huff, and it is a direct sequel to the earlier 1636: The Kremlin Games.
This most recent installment continues the tale shortly after it left off in The Kremlin Games. It focuses the continuation of the struggle between Czar Mikhail and Director-General Sheremetev for control of Russia and its future. Only two uptimers feature prominently in this tale, for it is mostly the tale of the Russians of the alternate universe and their struggles.
It is a story of compromise, determination, of striving for freedom, of accepting the necessary. There are politics, there are battles, there are betrayals. There is love, there is hate. There are surprises. And there is some of the expected.
If you enjoyed The Kremlin Games, I believe you'll enjoy The Volga Rules. If you were primarily hoping to see more of the "main cast" like Michael Stearns, Rebecca Abrabanel, Harry Lefferts, Ed Piazza, Gretchen Richter, Gustavus Adolphus, etc. or find out more about the events happening in vicinity of Vienna, you may be disappointed. As it was, taking the tale for what it was, I quite enjoyed it.
Unsurprisingly, the political situation in Russia and Eastern Europe remains very much in question at the end of the novel. We must await further stories to learn more about what awaits Russia, Poland, and their neighbors.
This most recent installment continues the tale shortly after it left off in The Kremlin Games. It focuses the continuation of the struggle between Czar Mikhail and Director-General Sheremetev for control of Russia and its future. Only two uptimers feature prominently in this tale, for it is mostly the tale of the Russians of the alternate universe and their struggles.
It is a story of compromise, determination, of striving for freedom, of accepting the necessary. There are politics, there are battles, there are betrayals. There is love, there is hate. There are surprises. And there is some of the expected.
If you enjoyed The Kremlin Games, I believe you'll enjoy The Volga Rules. If you were primarily hoping to see more of the "main cast" like Michael Stearns, Rebecca Abrabanel, Harry Lefferts, Ed Piazza, Gretchen Richter, Gustavus Adolphus, etc. or find out more about the events happening in vicinity of Vienna, you may be disappointed. As it was, taking the tale for what it was, I quite enjoyed it.
Unsurprisingly, the political situation in Russia and Eastern Europe remains very much in question at the end of the novel. We must await further stories to learn more about what awaits Russia, Poland, and their neighbors.
Genes for Longer Life?
Scientists recently published a paper about some interesting genes found among the Amish of Indiana. Those who possess the genes tend to live 10% longer than those without. Very interesting stuff, especially given the recent experiment with in vivo genetic engineering in humans.
Sunday, November 19, 2017
Book Review: Shikari
As I mentioned previously, I recently purchased and read Shikari, a new science fiction novel by Alma T. C. Boykin. As I mentioned at the time, I enjoyed the novel. It is set in the far future, on a distant colony world settled by humans before they realized their was an indigenous species of sophonts present. These sophonts, the Stare, had a relatively primitive civilization, and welcomed the humans. The story follows two human teenagers who begin to unlock secrets of the past that are a mystery to human and Stare alike, while dodging the ire of those who wish the past to remain buried.
The novel is a lot of fun. The mood and setting are reminiscent of tales set in the India of the Raj. Rudyard Kipling or Talbot Mundy (with aliens!) would not be a bad shorthand. There's a sense of wonder, of the exotic, and of danger, in the story.
Production values were good. It was virtually free of typos or formatting issues to distract from the words themselves. And in my opinion, the words, and story, flowed well.
I eagerly devoured the tale and was disappointed only in the fact that it came to an end. Thankfully, Ms. Boykin appears to have several more in this series planned. (Yay!) I look forward to more.
The novel is a lot of fun. The mood and setting are reminiscent of tales set in the India of the Raj. Rudyard Kipling or Talbot Mundy (with aliens!) would not be a bad shorthand. There's a sense of wonder, of the exotic, and of danger, in the story.
Production values were good. It was virtually free of typos or formatting issues to distract from the words themselves. And in my opinion, the words, and story, flowed well.
I eagerly devoured the tale and was disappointed only in the fact that it came to an end. Thankfully, Ms. Boykin appears to have several more in this series planned. (Yay!) I look forward to more.
Saturday, November 18, 2017
JavaScript fun for 3D
Yesterday I wrote about a few of the JavaScript libraries I found that would help solve some needs at Day Job (tm). Today I'll mention another one I played with yesterday evening that may be of some interest. I'd heard of three.js before, as it was used in the web-based planet generator I've mentioned in the past, but this was the first time I really looked at in depth.
three.js is a JavaScript library for loading, displaying, and interacting with 3D graphics inside a web browser. WebGL was introduced as a web version of the venerable OpenGL technology years ago, but OpenGL (and, by extension, WebGL) are very low level. three.js provides a higher-level interface, with support for loading models in various formats. The website offers a multitude of example web pages with working examples. It even has a few examples using fractal methods to generate a terrain that can be moved around in.
Alas, there aren't built-in loaders for the formats I need for Day Job (tm), but that's simply a matter of writing a compatible loader, or a separate converter program to take models in the formats we have them in and convert them to formats three.js can load.
Beyond work, though, it has the potential to be useful as the display end for some of the other things I've been experimenting with for fun. I wouldn't want to write the code to generate things in JavaScript, but a web page using three.js to display the results would be entirely feasible.
Surprisingly, three.js even offers a web-based 3D scene editor. It isn't Blender, SketchUp, 3D Max, or AutoCAD, and there's no real mesh modeling support, only primitives like box, sphere, cylinder, torus, etc. Nevertheless, it can be used to create a 3D scene relatively easily, and does have import capabilities so that models in other formats, like OBJ, can be imported. It can export to OBJ, STL, and its own JSON-based format. It can even publish scenes and a web page to view the scene. Pretty slick.
Anyhow, if you need 3D on your web page, this is worth checking out.
three.js is a JavaScript library for loading, displaying, and interacting with 3D graphics inside a web browser. WebGL was introduced as a web version of the venerable OpenGL technology years ago, but OpenGL (and, by extension, WebGL) are very low level. three.js provides a higher-level interface, with support for loading models in various formats. The website offers a multitude of example web pages with working examples. It even has a few examples using fractal methods to generate a terrain that can be moved around in.
Alas, there aren't built-in loaders for the formats I need for Day Job (tm), but that's simply a matter of writing a compatible loader, or a separate converter program to take models in the formats we have them in and convert them to formats three.js can load.
Beyond work, though, it has the potential to be useful as the display end for some of the other things I've been experimenting with for fun. I wouldn't want to write the code to generate things in JavaScript, but a web page using three.js to display the results would be entirely feasible.
Surprisingly, three.js even offers a web-based 3D scene editor. It isn't Blender, SketchUp, 3D Max, or AutoCAD, and there's no real mesh modeling support, only primitives like box, sphere, cylinder, torus, etc. Nevertheless, it can be used to create a 3D scene relatively easily, and does have import capabilities so that models in other formats, like OBJ, can be imported. It can export to OBJ, STL, and its own JSON-based format. It can even publish scenes and a web page to view the scene. Pretty slick.
Anyhow, if you need 3D on your web page, this is worth checking out.
Friday, November 17, 2017
Useful JavaScript and More
My Day Job has been keeping me rather busy the last few days, so I haven't had a chance to wrap up the series of Shapes posts I was working on. Instead, I'll give a quick shout out to a few useful bits of JavaScript I've done a little experimentation with for Day Job.
First off, there's jsTree. jsTree is JavaScript for a tree-like user control. It can be created and manipulated via script, or the script can be applied to a set of nested HTML lists or JSON data to "tree-ify" it. For what I was prototyping, it took less than ten minutes to read the jsTree documentation, mock something up in an HTML file, and then apply the jsTree script to turn it into an interactive tree. A stylesheet reference, two script references, and about eight lines of JavaScript was all it took. Pretty sweet.
Second, there's the svg-pan-zoom script. A single script reference and about six lines of JavaScript allowed me to take a large SVG diagram that was loaded onto a web page and make it possible to pan and zoom. It was a very large diagram with many fine details. Before the pan and zoom script was applied, the fine details were illegible. With the script, it was easy to zoom in and navigate in the diagram. It took me just a bit longer to get this working right, perhaps twenty minutes.
And third, we have ViewerJS. ViewerJS offers the ability to easily view PDF and LibreOffice/OpenOffice files on a website, without the need for plugins or any special executable code to be placed on the server - its all pure JavaScript. This took me about twenty minutes to figure out the basics. Since many of you have files in Microsoft Office format, I should mention that LibreOffice can be run at command line, and scripted, to convert one or many files to formats ViewerJS supports.
The developers of these components have done an excellent job development, packaging, and providing useful demos and examples. Nice work! All three are also open source software.
And finally, not JavaScript, but icons. Google has a source of 900+ icons as part of its Material Design effort. There initial Google icons plus a whole bunch more can also be found at the Material Design Icons web site. I'm using a good number of them with the experiment; I just wish more of them were a good fit for the domain the program relates to.
First off, there's jsTree. jsTree is JavaScript for a tree-like user control. It can be created and manipulated via script, or the script can be applied to a set of nested HTML lists or JSON data to "tree-ify" it. For what I was prototyping, it took less than ten minutes to read the jsTree documentation, mock something up in an HTML file, and then apply the jsTree script to turn it into an interactive tree. A stylesheet reference, two script references, and about eight lines of JavaScript was all it took. Pretty sweet.
Second, there's the svg-pan-zoom script. A single script reference and about six lines of JavaScript allowed me to take a large SVG diagram that was loaded onto a web page and make it possible to pan and zoom. It was a very large diagram with many fine details. Before the pan and zoom script was applied, the fine details were illegible. With the script, it was easy to zoom in and navigate in the diagram. It took me just a bit longer to get this working right, perhaps twenty minutes.
And third, we have ViewerJS. ViewerJS offers the ability to easily view PDF and LibreOffice/OpenOffice files on a website, without the need for plugins or any special executable code to be placed on the server - its all pure JavaScript. This took me about twenty minutes to figure out the basics. Since many of you have files in Microsoft Office format, I should mention that LibreOffice can be run at command line, and scripted, to convert one or many files to formats ViewerJS supports.
The developers of these components have done an excellent job development, packaging, and providing useful demos and examples. Nice work! All three are also open source software.
And finally, not JavaScript, but icons. Google has a source of 900+ icons as part of its Material Design effort. There initial Google icons plus a whole bunch more can also be found at the Material Design Icons web site. I'm using a good number of them with the experiment; I just wish more of them were a good fit for the domain the program relates to.
Thursday, November 16, 2017
Geology-related Travelogue
Over at Cat Rotator's Quarterly, Alma Boykin has a couple recent posts on a trip between Amarillo, TX and Albuquerque, NM. While the space in between is in many ways very boring, Ms. Boykin's post covers some of the interesting geology and terrain features of the region.
Wednesday, November 15, 2017
Real-life Genetic Engineering in a Live Human!
The Associated Press report that US scientists try 1st gene editing in the body. This pretty exciting news. They're actually trying to cure a disease called Hunter syndrome in a 44 year old through gene editing.
Tuesday, November 14, 2017
Thickening with Falloff
Yesterday I was looking for a way to generate decreasing intensity extending outward from initial shapes. It is something that may be useful for some other techniques going forward, though is of some limited use in and of itself, and the effect itself is somewhat interesting. It might look nicer with some smoothing, though.
Here's a more : Given a raster representation of some initial geometry, this program calculates distance of pixels from the initial geometry, then visually represents the distance as a gradient between white (initial geometry) and black (at and beyond threshold).
The program has two required command line arguments (input and output files) and an optional argument specifying the threshold in pixels. Here's an example of the arguments I was using:
In the input image, black is treated as no geometry, any other color counts as geometry.
I'm releasing the C# source code under the MIT license, with no warranty. Use at own risk. Since I used the Vector2 struct you'll need to add the System.Numerics.Vectors package (which can be done with Install-Package System.Numerics.Vectors -Version 4.4.0 from the Package Manager Console in Visual Studio) or substitute your own implementation of Vector2.
Here's a more : Given a raster representation of some initial geometry, this program calculates distance of pixels from the initial geometry, then visually represents the distance as a gradient between white (initial geometry) and black (at and beyond threshold).
The program has two required command line arguments (input and output files) and an optional argument specifying the threshold in pixels. Here's an example of the arguments I was using:
Thicken.exe -in C:\test\input.png -out C:\test\output.png -threshold 48
In the input image, black is treated as no geometry, any other color counts as geometry.
Input was a 512 x 512 PNG file |
Output image with a 48 pixel falloff threshold |
I'm releasing the C# source code under the MIT license, with no warranty. Use at own risk. Since I used the Vector2 struct you'll need to add the System.Numerics.Vectors package (which can be done with Install-Package System.Numerics.Vectors -Version 4.4.0 from the Package Manager Console in Visual Studio) or substitute your own implementation of Vector2.
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; namespace Thickening { class Program { private static void ReadImageAsMap(string fileName, out int[] map, out int width, out int height) { // Read input image into map array. Any non-black pixel is a starting point. Bitmap inputImage = (Bitmap)Bitmap.FromFile(fileName); width = inputImage.Width; height = inputImage.Height; map = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int i = y * width + x; Color c = inputImage.GetPixel(x, y); if (c.R > 0 || c.G > 0 || c.B > 0) { map[i] = 0; } else { map[i] = -1; } } } } private static void Thicken(int[] map, int width, int height) { // Find starting points (zero). List<Vector2> current = new List<Vector2>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int i = y * width + x; if (map[i] == 0) current.Add(new Vector2(x, y)); } } // Iterative set distance around starting points or points // where distance has already been calculated. while (current.Count > 0) { List<Vector2> next = new List<Vector2>(); foreach (var curr in current) { int cx = (int)curr.X; int cy = (int)curr.Y; int val = map[cy * width + cx]; // Look at neighbors. for (int y = cy - 1; y <= cy + 1; y++) { if (y < 0 || y >= height) continue; int ny = y; for (int x = cx - 1; x <= cx + 1; x++) { int nx = x; if (nx < 0) nx = width - 1; else if (nx >= width) nx = 0; int j = ny * width + nx; int nval = map[j]; if (nval < 0) { Vector2 neighbor = new Vector2(nx, ny); if (!current.Contains(neighbor) && !next.Contains(neighbor)) { map[j] = val + 1; next.Add(neighbor); } } } } } current = next; } } private static float Clamp(float min, float val, float max) { if (val < min) return min; if (val > max) return max; return val; } private static void WriteMapAsImage(string fileName, int[] map, int width, int height, float threshold) { Bitmap outputImage = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int i = y * width + x; int val = map[i]; Color c = Color.Black; if (val >= 0) { // Calculate percentage closeness to initial geometry. // Intensity is 100% at initial geometry, // 0 % at or beyond threshold. float closePercent = (threshold - val) / threshold; closePercent = Clamp(0, closePercent, 1.0f); int val2 = (int)(closePercent * 255.0); c = Color.FromArgb(val2, val2, val2); } outputImage.SetPixel(x, y, c); } } outputImage.Save(fileName); } private static string ParseForArgumentValue(string[] args, string argumentName, bool caseInsensitive = true, string defaultValue = null) { if (args == null || args.Length == 0) return defaultValue; string prevArg = ""; foreach (string arg in args) { bool isMatch = false; if (caseInsensitive) isMatch = (prevArg.ToLower() == argumentName.ToLower()); else isMatch = (prevArg == argumentName); if (isMatch) return arg; prevArg = arg; } return defaultValue; } static void Main(string[] args) { if (args == null || args.Length == 0) { string msg = "Thicken.exe -in input.png -out output.png [-threshold 32]"; Console.Error.WriteLine(msg); Environment.Exit(1); } string input = ParseForArgumentValue(args, "-in", true, null); string output = ParseForArgumentValue(args, "-out", true, null); string thresholdString = ParseForArgumentValue(args, "-threshold", true, "32"); int threshold = 32; bool thresholdOk = Int32.TryParse(thresholdString, out threshold); if (!thresholdOk) { string msg = "Invalid value for -threshold argument. " + "Omit -threshold argument or supply a valid positive integer " + "less than two billion."; Console.Error.WriteLine(msg); Environment.Exit(2); } try { int width, height; int[] map; ReadImageAsMap(input, out map, out width, out height); Thicken(map, width, height); WriteMapAsImage(output, map, width, height, threshold); } catch (Exception ex) { Console.Error.WriteLine("Unexpected error: {0}", ex.ToString()); Environment.Exit(3); } } } }
Monday, November 13, 2017
1637: The Volga Rules
This isn't really a full review of 1637: The Volga Rules, the latest installment in the 1632/Ring of Fire series. No, it's an explanation that reading the eARC of the new novel is gripping and has distracted me from the post I was planning to make today, about an algorithm I was playing with earlier today. So algorithm and pretty pictures tomorrow.
Coming Soon: Shapes!
Coming in the near future shall be Shapes! Shapes is a (possibly) exciting tutorial series on some programming techniques that do interesting things with shapes. However, I've still got some more example code to finish, text to write up, screenshots to take, etc. to give it some polish. Expect something sometime next week. Until then, I leave with you with a few simple, not-particularly-exciting images that emerged from parts 1 and 2. (Yes, parts 3 and later are some
Example output from part 1 |
Example output from part 2 |
Example output from part 3 |
Sunday, November 12, 2017
An Interesting Map
I was perusing DeviantArt looking at some of the maps, and map styles, that people have dreamed up. Some people are very creative in their cartographer. Some of them are truly works of art. I'm not sure this one fall into that category, but it sure is creative. It may be useful, too, if you want to know where the US, Canada, England, Russia, Japan, etc. lie in relation to Middle Earth, Westeros, and Tamriel.
What I've Read Lately
These aren't proper reviews, just a few quick shout-outs to some books I've recently read and enjoyed. Shikari by Alma Boykin features two teenagers having exciting adventures on an exotic colony world far from Earth. Pure Poison and Flying by Pam Uphoff are the latest installments in the Wine of the Gods series, and mostly focus on characters and events in the Presidential Directorate on One World.
Chain of Command by Frank Chadwick is an exciting space opera set in the same universe as his earlier books How Dark the World Becomes and Come the Revolution, but with a vastly different tone and set of characters. I have to go back and finish that one. I got to the end of the first part that was released and somehow forgot to go back and read the rest after it was released, something I just realized today - but the half I did read was great.
Chain of Command by Frank Chadwick is an exciting space opera set in the same universe as his earlier books How Dark the World Becomes and Come the Revolution, but with a vastly different tone and set of characters. I have to go back and finish that one. I got to the end of the first part that was released and somehow forgot to go back and read the rest after it was released, something I just realized today - but the half I did read was great.
Sanborn Maps of New Jersey
Apparently, in the time since I last wrote about map resources, the library at Princeton University has made available the Sanborn Fire Insurance Maps for New Jersey. They're a great resource for seeing town patterns, and the New Jersey patterns are so different than those of the typical Midwestern town.
The older portions of most Midwestern towns are laid out in a regular grid, often aligned with the cardinal directions (North-East-South-West), though topography sometimes alters that arrangement. In contrast, many of the older New Jersey towns are laid out in a less regular manner - there are fewer right-angle intersections for the major roads. Those that saw significant growth before the mid 20th century seem to have grid-like additions tying in. Jersey Shore towns seem to follow the regular grid more than many other Jersey towns.
The link is below for the interested.
http://library.princeton.edu/libraries/firestone/rbsc/aids/sanborn/
Saturday, November 11, 2017
Haven't Had Much To Say Lately
It's been about six months since I posted. (Actually, my last post was on May 11, so exactly six months.) Life has been rather busy but with events of note, little forward progress has been made on anything, and I was feeling rather down, so I wasn't posting much on what I was reading, even the new stuff. And there have been some new releases by some of my favorite authors, so I'm sorry to have missed plugging them here. More posts will likely be coming soon.
And a happy Veterans Day to any American veterans out there. Thank you for your service.
And a happy Veterans Day to any American veterans out there. Thank you for your service.
Subscribe to:
Posts (Atom)