<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Elegant Code &#187; Tony Rasa</title>.15 / GB stored / month” and “<title>Elegant Code &#187; Tony Rasa</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Quinine For Sale</title>.15 / GB stored / month” and “<title>Quinine For Sale</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Buy Prozac Without Prescription</title>.15 / GB stored / month” and “<title>Buy Prozac Without Prescription</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>MvcFutures</title>.15 / GB stored / month” and “<title>MvcFutures</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Calls to ReportExecutionService.Render() Hang</title>.15 / GB stored / month” and “<title>Calls to ReportExecutionService.Render() Hang</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Restricted Pan and Zoom in WPF</title>.15 / GB stored / month” and “<title>Restricted Pan and Zoom in WPF</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>.15 / GB stored / month” and “<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>OpenCV cvLoadImage IOError</title>.15 / GB stored / month” and “<title>OpenCV cvLoadImage IOError</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Removing WSUS</title>.15 / GB stored / month” and “<title>Removing WSUS</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>Azure Summary</title>.15 / GB stored / month” and “<title>Azure Summary</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “$0.15 / GB stored / month” and “$0.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to $100s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quinine For Sale</title>
		<link>http://elegantcode.com/2012/01/18/monitoring-an-mmo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-an-mmo</link>
		<comments>http://elegantcode.com/2012/01/18/monitoring-an-mmo/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 19:45:32 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MMO]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2012/01/18/monitoring-an-mmo/</guid>
		<description><![CDATA[I’ve been working on a free-to-play MMO Quinine For Sale, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before [...]]]></description>
			<content:encoded><![CDATA[<p> <p>I’ve been working on a free-to-play <a href="http://www.heroup.com" target="_blank">MMO</a> <b>Quinine For Sale</b>, which has been “officially” live since last April, and things have been going well – a steady growth of players; the game itself has been well-received, and all the important graphs are “up and to the right.”&#160; Part of my job involves detecting problems before they become serious and fixing problems when they inevitably do.&#160; So, there are two questions.&#160; “Is there a problem in the game?” “What is causing the problem?”&#160; </p>  <p>When trying to debug something on our development and test clusters, typically you can tail log files.&#160; We have a python script that can monitor the communication between various parts of the game and pretty-print it along with color to highlight “this is a problem!”&#160; Attaching a debugger to a running process is also not uncommon.&#160; However, looking at logs and bus traffic in realtime on a production environment gives you this neat “Matrix-y” experience.&#160; Attaching a debugger to a production process (assuming you could, which you can’t) would get you smacked with a rolled-up newspaper.&#160; “Bad Developer!&#160; No treat!”&#160; So, what can you do?</p>  <h4>Monitoring</h4>  <p>When you’ve got clusters full of machines, using <a href="http://www.nagios.org/" target="_blank">Nagios</a> to monitor things is an obvious solution.&#160; Beyond making sure the power is on and other sysadmin things, we’ve written other checks to see if the login process is working, the parts are working together, and automating typical in-game functions.&#160; For example, if nagios can’t successfully log into the game do basic game activity, then alerts happen.</p>  <h4>Metrics for EVERYTHING</h4>  <p>Anything that happens in game has metrics reporting tied to it, generating piles of data constantly.&#160; We use <a href="http://www.cacti.net/" target="_blank">Cacti</a> to visualize game activity.&#160; An example metric is concurrent users, or CCU.&#160; We graph how many people are in the game over time, which when things are healthy should be a nice smooth curve climbing to peak game hours, then descending nicely through the night.</p>  <p>We can tell by sight if the game looks healthy or not – if the CCU graph is jaggy, has a sudden drop or spike, or drops to zero then we know that something is wrong.&#160; Typically nagios alerts accompany the graphs, giving more data points on where to look.&#160; But this has also pointed out areas where a nagios check was missing or wasn’t working as intended.</p>  <h4>Log Files</h4>  <p>When a player gets an error in game, the error dialog box gives them the opportunity to submit the error details back to us.&#160; If we see a spike in user-reported errors through this or other customer service means, we know we have something of interest to look for.&#160; </p>  <p>The game server components make use of log4j and similar logging frameworks.&#160; Anything that you’d want to watch happening in game needs to be aggressively logged.&#160; All components are configured so that operations can change the log level on the fly.&#160; That’s still quite a bit of data across many machines though, so all that information is run through <a href="http://www.splunk.com/product" target="_blank">Splunk</a> to be indexed and searchable.&#160; This gives us a great tool for searching through log data, examining trends, or watching selected activity in real time.&#160; Unfortunately it is very expensive so we are selective about the data that passes through it.&#160; </p>.  Buy Quinine from mexico.  Buy Quinine no prescription.  No prescription Quinine online.  Online buying Quinine.  Quinine no prescription.  Quinine street price.  Buy no prescription Quinine online.  Quinine coupon.  Quinine over the counter.  Where can i buy Quinine online.  Quinine steet value.  Where to buy Quinine.  Order Quinine online overnight delivery no prescription.  Quinine recreational.  Quinine canada, mexico, india.  Ordering Quinine online.  Quinine without prescription.  Quinine price, coupon.  Quinine description.  Order Quinine from mexican pharmacy.  Quinine pics.  What is Quinine.  Japan, craiglist, ebay, overseas, paypal.  Order Quinine from United States pharmacy.  Order Quinine online c.o.d.  Quinine trusted pharmacy reviews.  Quinine treatment.  Buy Quinine from canada.  Quinine used for.  Discount Quinine.  Is Quinine addictive.  Quinine forum.  Buy Quinine online no prescription.  Is Quinine safe.  Purchase Quinine for sale.  Effects of Quinine.  Buy Quinine online cod.  Quinine australia, uk, us, usa.  Buy Quinine without prescription.  Quinine online cod.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://www.leaduganda.org/?p=514'>Quinine For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=4820'>Quinine For Sale</a>. <a href='http://www.greatgreengoods.com/?p=2780'>Quinine For Sale</a>. <a href='http://www.thegriffonnews.com/?p=10177'>Quinine For Sale</a>. <a href='http://www.independentworldreport.com/?p=2409'>Quinine For Sale</a>. <a href='http://changecamp.ca/?p=295'>Quinine description</a>. <a href='http://social-blend.com/?p=624'>Quinine price, coupon</a>. <a href='http://blog.farmland.org/?p=3946'>Online buying Quinine hcl</a>. <a href='http://4realz.net/?p=1595'>Quinine from canada</a>. <a href='http://reversemortgagedaily.com/?p=14535'>Where to buy Quinine</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/18/monitoring-an-mmo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Buy Prozac Without Prescription</title>
		<link>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jetty-startup-problems-due-to-entropy</link>
		<comments>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 22:07:28 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[jetty]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/</guid>
		<description><![CDATA[On the MMO Buy Prozac Without Prescription, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if [...]]]></description>
			<content:encoded><![CDATA[<p> <p>On the <a href="http://www.heroup.com">MMO</a> <b>Buy Prozac Without Prescription</b>, I’m working on, we do quite a bit of service monitoring via jetty.&#160; Things like having a URL that reports back version information for a component, or a page full of statistics showing recent activity, or a way to trigger a self-check in a component to determine if the component is sane and healthy or not.</p>  <p>For certain components we run multiple instances of the service on the same box.&#160; In development environments, it’s a pretty small number of instances.&#160; On a production environment it’s a much bigger number.&#160; Typical stuff.&#160; However Operations noticed that startup times for a server full of instances jumped from seconds to over 20 minutes when the number of instances was increased from 3 to 12.&#160; Ouch.</p>  <p>So, <em>something</em> is blocking on startup.&#160; After some digging, I came across <a href="http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup">this post</a> explaining how jetty uses a secure random number generator for session ids, which is based on the pool of entropy generated by the system.&#160; Sure enough…</p>  <p>$ cat /proc/sys/kernel/random/entropy_avail   <br /><em>128</em></p>  <p>(On development cluster machines that value is upwards of 3000)</p>  <p>Since we don’t care if the jetty session IDs are securely generated or not, switching the generator from secure to not-secure took us back to a few seconds to start up 20 instances.</p>.  Prozac over the counter.  Prozac recreational.  Prozac pictures.  Prozac natural.  Order Prozac online c.o.d.  Canada, mexico, india.  Prozac class.  Get Prozac.  Real brand Prozac online.  Buy Prozac no prescription.  Online buying Prozac.  Buy Prozac without a prescription.  Effects of Prozac.  No prescription Prozac online.  Prozac price, coupon.  Prozac canada, mexico, india.  Prozac pics.  Is Prozac addictive.  Purchase Prozac.  Prozac without a prescription.  Purchase Prozac online.  Order Prozac no prescription.  Prozac cost.  Ordering Prozac online.  Order Prozac from United States pharmacy.  Buy Prozac from mexico.  Buy Prozac from canada.  Where to buy Prozac.  Comprar en línea Prozac, comprar Prozac baratos.  About Prozac.  Buy cheap Prozac no rx.  Buy generic Prozac.  Prozac blogs.  Rx free Prozac.  Prozac dangers.  Generic Prozac.  Prozac wiki.  Prozac for sale.  Prozac steet value.  Prozac brand name.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4228'>Aricept For Sale</a>. <a href='http://elegantcode.com/?p=4340'>Atarax For Sale</a>. <a href='http://elegantcode.com/?p=5052'>Lotrisone For Sale</a>. <a href='http://elegantcode.com/?p=4407'>Buy Nexium Without Prescription</a>. <a href='http://elegantcode.com/?p=4967'>Buy Spiriva Without Prescription</a>. <a href='http://elegantcode.com/?p=4873'>Cafergot treatment</a>. <a href='http://elegantcode.com/?p=4780'>Canada, mexico, india</a>. <a href='http://elegantcode.com/?p=4202'>Online buying Celexa</a>. <a href='http://elegantcode.com/?p=4335'>Fast shipping Differin</a>. <a href='http://elegantcode.com/?p=4205'>Purchase Allopurinol online no prescription</a>.<br />
<b>Trackbacks from:</b> <a href='http://home.officesnapshots.com/?p=241'>Buy Prozac Without Prescription</a>. <a href='http://reversemortgagedaily.com/?p=14166'>Buy Prozac Without Prescription</a>. <a href='http://social-blend.com/?p=638'>Buy Prozac Without Prescription</a>. <a href='http://www.quarterlives.com/?p=738'>Buy Prozac Without Prescription</a>. <a href='http://4realz.net/?p=2076'>Buy Prozac Without Prescription</a>. <a href='http://evanrapoport.com/?p=272'>Online buying Prozac hcl</a>. <a href='http://www.themusclecarplace.com/?p=3402'>Prozac steet value</a>. <a href='http://www.thegriffonnews.com/?p=9554'>Prozac reviews</a>. <a href='http://www.greatgreengoods.com/?p=3397'>Prozac brand name</a>. <a href='http://www.macneilbmx.com/blog/?p=5935'>Order Prozac from United States pharmacy</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2011/06/15/jetty-startup-problems-due-to-entropy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvcfutures</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>  <p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>  <p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;<br />    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;<br />    &lt;p&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;<br />        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;        <br />    &lt;/p&gt;<br />&lt;/asp:Content&gt;</pre>

  <br /></div>

<p>I like this method MUCH better.&#160; </p>

<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>

<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>

<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=restricted-pan-and-zoom-in-wpf</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>  <h4>Minimum and Maximum Zoom</h4>  <p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>  <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">   <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">     <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<!--CRLF--></div>
</div>

<p></p>

<h4>Limiting Pan Transform</h4>

<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>

<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>

<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>

<h4>Pan Right, Bottom</h4>

<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>

<p>So, the minimum allowed ToX value is content.Width - (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>

<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>

<h4></h4>

<h4>The Result</h4>

<p>The code to handle this looks something like this:</p>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<!--CRLF-->

    <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<!--CRLF--></div>
</div>

<h4>All The Source Code</h4>
<iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=odd-behavior-with-scaletransform-centerxy-in-silverlight-3</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A [...]]]></description>
			<content:encoded><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.  Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.  A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.  If you’ve played an RTS like Starcraft, you’ll know what I mean.  I thought that this would be easy, certainly far easier than debugging A* pathfinding.  As usual, I was wrong.

To zoom in or out, use the mouse wheel while hovering over the map.  Zooming In should bring you into the point you are hovering over - “zoom in here.”  This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.  The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.

And in fact, when you first zoom in to a section of the map, the zoom does exactly that.  The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.  This problem was also confirmed using the latest release of Silverlight 4.

If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.  However this was causing other problems…

The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.



<strong>Update!</strong> December 6th 2010, from Václav Jedli?ka:
<blockquote>I found how to fix your solution of the zoom example you put here ... It is necessary to animate the CenterX and CenterY properties of the
scaling, not just the ScaleX and ScaleY properties. It is because
after the animation ends, the values set by the animation take
precendense of the regular properties of the transformation.

With this fix it works fine, but only for the image size you used. It
does not work with larger images, because there is no pan feature.</blockquote>
Thanks for the fix, Václav!

Three different sample sln’s showing the problem available over here:
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p> ]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=opencv-cvloadimage-ioerror</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python. The bad news:&#160; I’m writing this on a Windows box [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>  <p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>  <p>So imagine my confusion when this simple program:</p>  <pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: 'img.tif'</span>

<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>

<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>

<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>

<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV --- and it worked.</p>

<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time - rather than waiting for Gimp to open - I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>

<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>

<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=removing-wsus</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>  <p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond...&#160; oops</p>  <h4>To Fix (and get your automatic updates to work again):</h4>  <p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>  <p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=azure-summary</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>  <h4>The tl;dr version</h4>  <p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>  <h4>The Long Winded Version</h4>  <p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>  <p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on - for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>  <p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>  <p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “<title>StructureMap and SharePoint</title>.15 / GB stored / month” and “<title>StructureMap and SharePoint</title>.01 / 10k transactions” but they can add up quickly - a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>  <p>For a small app with little traffic, this could add up to 0s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>  <p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later :)</p>  <h4>Application Design</h4>  <p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>  <p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>  <p>&#160;</p>  <p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=structuremap-and-sharepoint</link>
		<comments>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 18:00:22 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[StructureMap]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/</guid>
		<description><![CDATA[I’ve started doing some SharePoint development and have brought some of my favorite tools and practices with me.&#160; Like unit tests.&#160; And IoC.&#160; And that other SOLID stuff.&#160; I’m writing a very basic WebPart to get started with SharePoint – this web part will display a list of links to other applications that the user [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve started doing some SharePoint development and have brought some of my favorite tools and practices with me.&#160; Like unit tests.&#160; And IoC.&#160; And that other SOLID stuff.&#160; </p>  <p>I’m writing a very basic WebPart to get started with SharePoint – this web part will display a list of links to other applications that the user is authorized to use.&#160; The source of this data (names, URLs, etc.) comes from an external-to-SharePoint system, accessed through another C# assembly.&#160; Once the web part gets the data there is some more processing to be done – we need to do more than just blindly display a list of URLs.&#160; Rather than get into details I’m just going to do some handwaving here and say that “if you have access to X, then {stuff happens}, or if you have access to Y then {other stuff happens}.”&#160; You know, business logic, stuff that is good to test.</p>  <p>the first thing I need to do is get business logic out of the WebPart and into something that I can write without having to reset AppPools over and over, not to mention have some unit tests to verify I’m going in the right direction.&#160; So, I created a standard application service class which has a dependency on the external authorization system, via constructor injection.&#160; </p>  <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> AuthorizedAppsService : IAuthorizedAppsService
{
  <span class="kwrd">private</span> <span class="kwrd">readonly</span> ExternalAuthorizeService authService;

  <span class="kwrd">public</span> AuthorizedAppsService(
    ExternalAuthorizeService authService) 
  {
    <span class="kwrd">this</span>.authService = authService;
  }

  <span class="kwrd">public</span> AuthorizedApplications GetAuthorizedApplications(
                                  <span class="kwrd">string</span> userName)
  {
    var allApps = authService.AuthorizedApplications(userName);
    <span class="rem">// business logic stuff happens here</span>
    <span class="kwrd">return</span> thoseResultsWeJustFiguredOut;
  }
}</pre>

<p>Next, I created a StructureMap Registry class to scan my assemblies, as well as adding in the details of how to create this external authorize service, using the typical method: <style type="text/css">




.csharpcode, .csharpcode pre
{
	font-size: x-small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>

<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyRegistry : Registry
{
  <span class="kwrd">public</span> MyRegistry()
  {
    Scan(scanner =&gt; {
      scanner.TheCallingAssembly();
      scanner.AssemblyContainingType(<span class="kwrd">typeof</span>(MyRegistry));
      scanner.WithDefaultConventions();
      });

    ForRequestedType&lt;ExternalAuthorizeService&gt;()
      .AsSingletons()
      .TheDefault.Is.ConstructedBy(c =&gt; Provider.GetService());

    <span class="rem">// other dependency configuration...</span>
  }
  <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> InitializeForSharepoint()
  {
    ObjectFactory.Initialize(init =&gt; init.AddRegistry&lt;MyRegistry&gt;());
    ObjectFactory.AssertConfigurationIsValid();
  }
}</pre>

<p>And then, what remains is to have SharePoint call my StructureMap initialization when my SharePoint application starts up.&#160; In an MVC or WebForms app, I’d just add code to the appropriate place in Global.asax.cs, but in SharePointLand, this is looked down on.&#160; Instead, the preferred mechanism seems to be to use an HttpModule and a FeatureReceiver to plug the Module into the app’s web.config.</p>

<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyStartupModule : IHttpModule
{
  <span class="kwrd">public</span> <span class="kwrd">void</span> Init(HttpApplication context)
  {
        ConfigureOtherStuff();
        MyRegistry.InitializeForSharepoint();
  }
  <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose() { }
}</pre>

<p>And then the FeatureReceiver to alter the app’s Web.Config looks something like this (note I borrowed most of this code from another sample SharePoint project:</p>

<p>&#160;</p>

<pre class="csharpcode"><span class="rem">//</span>
<span class="rem">// this is borrowing heavily from http://www.codeplex.com/SPAXO</span>
<span class="rem">// </span>
<span class="kwrd">public</span> <span class="kwrd">class</span> StartupFeatureReceiver : SPFeatureReceiver
{
  <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> FeatureActivated(
        SPFeatureReceiverProperties properties)
  {
    var webApp = properties.Feature.Parent <span class="kwrd">as</span> SPWebApplication;
    AddWebConfigEntry(webApp);
    UpdateApp(webApp);
  }

  <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> FeatureDeactivating(
        SPFeatureReceiverProperties properties)
  {
    var webApp = properties.Feature.Parent <span class="kwrd">as</span> SPWebApplication;
    RemoveWebConfigEntry(webApp);
    UpdateApp(webApp);
  }


  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddWebConfigEntry(SPWebApplication webApp)
  {
    SPWebConfigModification mod = GetModification();
    var existingModifications = 
             <span class="kwrd">new</span> List&lt;SPWebConfigModification&gt;(
                      webApp.WebConfigModifications);
    <span class="kwrd">if</span> (existingModifications.FindIndex(
                    <span class="kwrd">value</span> =&gt;
                        <span class="kwrd">value</span>.Name == mod.Name &amp;&amp;
                        <span class="kwrd">value</span>.Value == mod.Value &amp;&amp;
                        <span class="kwrd">value</span>.Owner == mod.Owner) == -1)
    {
      <span class="rem">// If the modifcation does not already exist </span>
      <span class="rem">// add the entry to the config</span>
      webApp.WebConfigModifications.Add(mod);
    }
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> RemoveWebConfigEntry(
            SPWebApplication webApp)
  {
    SPWebConfigModification mod = GetModification();
    webApp.WebConfigModifications.Remove(mod);
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> SPWebConfigModification GetModification()
  {
    <span class="kwrd">string</span> asmName = <span class="kwrd">typeof</span>(StartupModule).AssemblyQualifiedName;
    <span class="kwrd">string</span> typeName = <span class="kwrd">typeof</span>(StartupModule).FullName;

    <span class="kwrd">return</span> <span class="kwrd">new</span> SPWebConfigModification
      {
        Path = <span class="str">&quot;configuration/system.web/httpModules&quot;</span>,
        Name = String.Format(CultureInfo.InvariantCulture,
                <span class="str">&quot;add[@name='{0}'][@type='{1}']&quot;</span>,
                typeName, asmName),
        Sequence = 0,
        Owner = asmName,
        Type = SPWebConfigModification.
                    SPWebConfigModificationType.EnsureChildNode,
        Value = String.Format(CultureInfo.InvariantCulture,
                  <span class="str">&quot;&lt;add name='{0}' type='{1}' /&gt;&quot;</span>,
                  typeName, asmName)
      };
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> UpdateApp(SPWebApplication webApp)
  {
    <span class="rem">// Update the Web App and apply the changes </span>
    <span class="rem">// to all servers in the farm</span>
    webApp.Update();
    webApp.Farm.Services
        .GetValue&lt;SPWebService&gt;()
        .ApplyWebConfigModifications();
  }
}</pre>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

