New Wix-Based Installer for Linkage

May 10th, 2013

I finished the minimal work necessary to use the new installation package. I don’t have time to do more extensive work on it but I think that it is good enough to send out. The user cannot pick a destination for the install and the program is installed for all users without a choice. I create a desktop icon and a shortcut in the Start menu program list.

I had a bit of fun trying to make the graphics more interesting. I’m not sure if they are great or just cluttered but I like them.

image

The Welcome Page

image

The Progress Page

Other than a completion page that looks a lot like the Welcome page, there isn’t anything else to the installer.

Get it here.

My First Experience with Wix

May 10th, 2013

I will be using Visual Studio 2012 soon. I need it for Windows Phone 8 development and it is getting to be a bit annoying having multiple versions of Visual Studio installed. I already have VS 2008 for some of my day job projects and VS 2010 installed because it was newer and better when it came out.

The biggest problem with VS 2012 is that it lacks support for basic Windows installer functionality. In other words, the setup deployment project type is no longer supported and ClickOnce is not available for C++ projects; at least not in a simple way.

Wix to the Rescue

Wix is a tool for creating setup files from XML data. It is not well documented and it took me at least eight hours to get a basic working installer for the Linkage program. When I say that I have a basic working installer, what I mean is that I have a linkage.msi file that will install the linkage software and documentation and will create a desktop shortcut and a Programs menu shortcut. That’s it.

The Wix XML

I will present the XML data that I am using then describe some of the problems I had. I did have two requirements to fulfill before I considered this a working solution. The first to have some shortcuts and the second was to be able to install the software with no oddball errors. I’ll get back to that.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <?define PRODUCTVERSION="2.9.12"?>
    <?define UPGRADECODE="363E6270-4C3C-4022-80C5-32499430E4BE"?>

    <Product Id="*" Name="Linkage" Language="1033" Codepage="1252" Version="$(var.PRODUCTVERSION)" 
             Manufacturer="David Rector" UpgradeCode="$(var.UPGRADECODE)">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="*" SummaryCodepage="1252"/>

        <Upgrade Id="$(var.UPGRADECODE)">
            <UpgradeVersion OnlyDetect="yes"
                            Minimum="$(var.PRODUCTVERSION)"
                            Property="NEWERVERSIONDETECTED"
                            IncludeMinimum="no" />

            <!-- 
                The IncludeMaximum="yes" attribute will cause an ICE612 warning normally.
                My project supresses that warning. The end result is that my failure to
                increase the version number of this install doesn't stop the installer from
                removing the old version and installing this new one. Change the attribute
                to "no" and the user will see an error during install that the same version
                is already installed but is from a different build. That's a strange error
                for a user to see so I just let the install happen.

                A symptom of not detecting the alternate build with the same version is
                having multiple entries in the "Programs and Features" list in the Control
                Panel. If you see that then you have multiple different builds with the same
                version number!         
            -->

            <UpgradeVersion OnlyDetect="no"
                            Maximum="$(var.PRODUCTVERSION)"
                            Property="OLDERVERSIONBEINGUPGRADED"
                            IncludeMaximum="yes" />

        </Upgrade>

        <CustomAction Id="CA_BlockOlderVersionInstall" Error="A newer version of Linkage is already installed. You will need to remove it first if you want to install this older version." />
        <CustomAction Id="CA_BlockAnotherBuildInstall" Error="Another version of Linkage is already installed but it has the same version number as this version. Uninstall the other version or contact customer support to help resove this issue." />

        <InstallExecuteSequence>

            <Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
                <![CDATA[NEWERVERSIONDETECTED]]>
            </Custom>

            <Custom Action="CA_BlockAnotherBuildInstall" After="FindRelatedProducts">
                <![CDATA[ANOTHERBUILDINSTALLED]]>
            </Custom>
            
            <LaunchConditions After="AppSearch" />

            <RemoveExistingProducts After="InstallInitialize" />
        </InstallExecuteSequence>


        <InstallUISequence>
            <Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
                <![CDATA[NEWERVERSIONDETECTED]]>
            </Custom>

            <Custom Action="CA_BlockAnotherBuildInstall" After="FindRelatedProducts">
                <![CDATA[ANOTHERBUILDINSTALLED]]>
            </Custom>

            <LaunchConditions After="AppSearch" />
        </InstallUISequence>
        
        
        <MediaTemplate/>

        <Feature Id="ProductFeature" Title="Linkage" Level="1">
            <ComponentRef Id="LinkageExecutable"/>
            <ComponentRef Id="LinkageDocumentation"/>
            <ComponentRef Id="LinkageMisc"/>
        </Feature>

        <Icon Id="icon.exe" SourceFile="..\res\icon.exe" />
        <Property Id="ARPPRODUCTICON" Value="icon.exe" />
    </Product>

    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="DesktopFolder" Name="Desktop"/>
            <Directory Id="ProgramMenuFolder">
                <Directory Id="ApplicationProgramsFolder" Name="Linkage"/>
            </Directory>
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLFOLDER" Name="Linkage"/>
            </Directory>
        </Directory>
    </Fragment>

    <Fragment>
        <Component Id="LinkageExecutable" Directory="INSTALLFOLDER" Guid="7AF9110C-E88C-4BBE-A510-1933A0798D8A">
            <File Id="linkage.exe" Name="linkage.exe" DiskId="1" Vital="yes" Source="..\Release\linkage.exe" KeyPath="yes">
                <Shortcut Id="ApplicationStartMenuShortcut"
                          Advertise="yes"
                          Directory="ApplicationProgramsFolder"
                          Name="Linkage"
                          Icon="icon.exe"
                          Description="Linkage Mechanism Designer and Simulator"
                          WorkingDirectory="INSTALLFOLDER"/>
                <Shortcut Id="DesktopMenuShortcut"
                          Advertise="yes"
                          Directory="DesktopFolder"
                          Name="Linkage"
                          Icon="icon.exe"
                          Description="Linkage Mechanism Designer and Simulator"
                          WorkingDirectory="INSTALLFOLDER"/>
            </File>
            <RemoveFolder Id="ApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall" />
        </Component>

        <Component Id="LinkageDocumentation" Directory="INSTALLFOLDER" Guid="27D1D154-2197-4B00-9B1D-D97C57D2E96D">
            <File Id="linkage.pdf" Name="linkage.pdf" DiskId="1" Vital="yes" Source="..\linkage.pdf" />
        </Component>

        <Component Id="LinkageMisc" Directory="INSTALLFOLDER" Guid="ACE32A96-1D38-453D-9E22-671366577E46">
            <File Id="history.txt" Name="history.txt" DiskId="1" Vital="yes" Source="..\history.txt" />
        </Component>

    </Fragment>
</Wix>

The Wix XML was tough to create. Most examples that I found were weak; they either had XML that caused errors when I used it or they had example pieces of the XML file and other data was clearly needed to finish the example. Dang, if you’re going to tell someone to create XML tags in a file, please tell them where in the file that new XML will go; what is the enclosing tag?

Some examples were great but it took a while to find them. There was a lot of conflicting information when it came to the structure of the data in the file.

I present a complete XML file for an installer that works. Here were some issues:

I had trouble finding out how to remove old versions of the software. I ended up finding what I needed and I even figured out how to deal with repeated development installs that didn’t require a version number increment every time I made a change to the installer or program source.
Installing shortcuts for all users is a pain. I had to use advertised shortcuts that are part of the <File> element for the executable. Other methods never worked right.
Adding a <RemoveFolder> element for the executable file didn’t work and produced and ICE error until I finally figured out that it needed an Id attribute and a Directory attribute!
I could not find a copy of a working XML file like the one I am presenting here. I found lots of parts but no whole file.

So here it is. It might work for someone else and it might not.

My next task is to add dialog boxes so that I can ask the user if this is a per-user or all-user install and to show when the install is finished. I expect the per-user vs. all-user installs to be troublesome since there are many problems related to this that are reported but not resolved in many online forums.

Wix Home Page

Fixed That Bug!

May 8th, 2013

The bug mentioned in an earlier post today was an easy fix. During the simulation, I do error checking to make sure that a set of links that are being moved into their new locations are not already stuck in their current location. Sort of.

image

Invalid Connections Shown Correctly

The problem was that I was moving link 1 (dark blue) and link 3 (green) to meet each other at the common connector C. The code made a bad assumption of I just forgot to check that both links were not connected to something already stuck in place. The code only tested link 1 which has no other connections. Link 3 has that connection through link 2 (cyan) to link 4 (purple and not confused with link 6). Link 4 is already fixed in place so 2 cannot be moved later.

There is still a flaw because it is possible that link 2 could work properly in a mechanism like this and not cause link 3 to bind. I am not checking the distance to see if it is valid, just that there is nothing attached to link 3 that could keep it from moving into its new position. I will need to test my theory and then improve the code.

But what I really need to do is rewrite the simulator code to be a bit less complex. There should be a way to move things into their new positions and somehow just know that a mechanism is not valid. It will take some thought before that happens.

Bug In Linkage 2

May 8th, 2013

Note: The bug mentioned below has been fixed and is described in This Post.

I encountered a bug in the Linkage simulation code. I have error checking for mechanisms that won’t work and I was aware of some situations that were not working right. This new problem surprised me.

Video of the Failure

The simulation code uses an iterative approach where each element is moved if it can be and once all elements have been tried, the process repeats until there is an error or until all elements have been moved. This is a bit clumsy but it was the only way I knew how to do this. I knew that there was a bit of error checking missing when rotating input anchors but I didn’t expect this case.

Link 2 get stretched. It appears that either connector D or connector F is getting moved without regard to the other.

I’ll fix it as soon as I get a chance but I did want to at least have some record of the problem for anyone who might encounter it.

And if anyone doesn’t know this already, there is an exponential order of magnitude relationship between the amount of code in a program and the difficulty in writing that code. Double the code and it is like making it 10 times more complex. At least it seems that way sometimes.

Dave

I Didn’t Copy SAM

May 6th, 2013

About ten years ago, I was building a robot and I found a demo of a 4-bar linkage design program that would synthesize a mechanism based on an input curve. It suited my needs but I wanted to do more. I ended up wanting to write software for editing and animating mechanisms but I had no background in that field or in any field related to mechanical design.

So I wrote some code and let it sit for 8 years until a few years back, I got a fully functional and useful program written.

Then I did some research…

Sure, I did some internet searching back when I was writing the software for the first time but not much was available at that time and I was focused on free software.

I recently did some more research and didn’t skip programs that cost money. I’m not really surprised but it turns out that there is a package that has been around for a long time that I apparently copied. I only say that because there are enough similarities between my program and theirs that it might look that way. I actually had no idea about their software until recently.

SAM can be found here: http://www.artas.nl/

SAM looks like a nice package. I dislike what looks like a modal interface but that’s just a strange preference of mine. It doesn’t seem right to decide to change a property of a connector then click on the connectors that should have that property. I base this assessment on seeing a video where connectors are changed to ground connectors by first selecting something in the toolbar then clicking on the connectors. I could be wrong and there could instead of some key presses happening.

SAM sells for about 1425.00 Euros. That’s a pretty steep price for the software but maybe it’s not out of line considering some of the more advanced features that are in that package. I will certainly admit that it does what Linkage 2.x does and a lot more. In fact, it would take more than a few hours of development time to get anywhere close to the number and complexity of features available in SAM. Heck, I can create mechanisms in Linkage that don’t work and show no errors so I am certainly not building a commercial package.

So hats off to Artas Engineering Software for doing what I wanted to do and better and being able to sell a few copies!

But if you want some of those features and you want them for free, give Linkage a try.

Animated GIF in Linkage?

May 1st, 2013

test

Animate Gif Converted from Linkage AVI File

The image above was not created by the Linkage program. It was converted from an AVI file that was created with Linkage. I’m thinking about how I might be able to build in the GIF animation creation feature so that I can get easier-to-view videos that loop. YouTube is nice for sharing with strangers but the lack of a looping feature and the really ugly preview image (see High Quality Video Preview for YouTube Videos) makes it a mediocre video service. The animated GIF files don’t have a preview and are playing the moment the page is displayed but that is fine. JavaScript might also be a very useful tool that would allow me to present an animated GIF similar to how YouTube videos are presented; a play button over a preview image should be fairly easy other than having to create the preview image manually.

So there it is; a nice animated GIF showing some curved sliding connections in a mechanism.

Linkage Bug

April 26th, 2013

bug 1 [buhg]  noun, verb, bugged, bug·ging.

noun

  1. Also called true bug, hemipteran, hemipteron. a hemipterous insect.
  2. (loosely) any insect or insect-like invertebrate.
  3. Informal. any microorganism, especially a virus: He was laid up for a week by an intestinal bug.
  4. Informal. a defect or imperfection, as in a mechanical device, computer program, or plan; glitch: The test flight discovered the bugs in the new plane.
  5. Informal.
    1. a person who has a great enthusiasm for something; fan or hobbyist: a hi-fi bug.
    2. a craze or obsession: He’s got the sports-car bug.

I have an urge to add cams to the Linkage program. After adding the ability to affix drawing elements to links, I realized that I had created the method to affix cams to links. That was a stumbling block I was not able to overcome for a while. By using that method to attach cams to a mechanism, I get past what had been holding me back for a while.

I also figured out the other issue which is designing a user interface to edit cam shapes. Although I would prefer to edit the shape right in the drawing editor, and I may add that, I would use a properties dialog box to provide the initial cam creation UI.

Three Types of Cams

I have identified three types of cams: eccentrics, typical, and Bezier. Typical cams are those found in engines and have a single lobe or protrusion. Although they can have very complex shapes, I would limit them to having a base radius, a tangent radius, and a nose radius. Bezier cams would be my own method of letting a person create a complex motion controlling cam with almost any shape desired. Eccentrics are just offset circles and might not be so useful. I’m not sure if the follower motion of an eccentric is the same as a crank but I think that it is. The only reason to support eccentrics is to more accurately represent what a person intends to build.

Each cam type would be edited in it’s own properties dialog box that has controls for the specific cam type. Although it would require a lot of typing to create the code for this, there is nothing in the user interface that I have not already experimented with on my geometric constructions page.image

Geometric Constructions Page – Bezier Cam

image

Geometric Construction Page – Typical Cam

Getting the cams to work in the simulator is a different problem from creating the UI to create them. This part would be tricky since the typical and Bezier cam types have unusual mechanical issues. Intersecting a line or circle with a cam becomes problematic. For instance, finding an intersection with a typical cam requires intersecting with four different arcs. Intersecting with a Bezier curve might require iterations through a set of small lines used to form the curve and through multiple Bezier curves of a single cam.

Other Work

Unfortunately, or fortunately, I have a paid contract coming up. It is Windows Phone programming work. It has replaced the contract for IOS programming that I was looking forward to doing but it is a lot of work and a lot of extra pay. So the Linkage program gets a lower priority again. I will need to make sure that I don’t end up writing half-assed cam code like I did with the DXF file creation code. That stuff is still only partially working and I’ve lost interest in making it better.

Dave

Memory Leak in Linkage

April 24th, 2013

I found a major memory leak in the Linkage program. Fortunately, the leak only added up to large amounts of memory if a simulation was running for a while.

The leak was caused by my forgetting to create a virtual destructor for a C++ class. One of the changes that I made a few months ago before taking a break from working on this program was to place all rendering code inside of some C++ classes. I opted to use the regular GDI code as the basis for this rendering class instead of making it something that can be used cross platform but it still has the ability to convert any drawing operation from a GDI call to a call to some other functions. For instance, I use this rendering code to “draw” DXF files.

One thing I did with the structure of the program was to have a rendering class that contains a member object that is the actual renderer. When a rendering class is constructed, it accepts a parameter that indicates what type of final rendering is needed. The contained rendering class is based on a common base class so that the higher level renderer does not know or care what type of actual rendering is going on. The high level class is used just to hold the actual renderer and pass on requests to it.

So the bug was that I forgot to make the destructor of the base implementation class a virtual destructor. The destructor for the actual low level rendering class never got call and never cleaned itself up.

I wish that the compiler could have told me this.

I will upload a new installer for the Linkage program shortly.

I need to add that I created a linkage that caused the program to do something wrong and that in turn caused the entire system to become unstable. I think the problem was that I used up a critical and limited resource when I didn’t free things properly. I hope that the problem is gone now that I found the leak.

I am searching the code for other less obvious memory leaks but so far, it looks good. If anything is leaking, it is very very small.

Dave

Aligning Grid to Rotated Image

April 18th, 2013

I could not come up with a simple math solution for this. By “simple math”, I mean a math solution that uses a single equation without sine-cosine operations to solve the problem.

The Problem

I have an image that is a picture of a grid of information. The picture is a photo and may have the grid visible at any size and any rotation.

image

The Picture

Additionally, the grid information may be hard to see in some places due to the nature of the content.

The user needs to open the image and click in two places in the image and then tell the program about the two clicked locations. They tell the program the x,y coordinates of the two places within the grid and the program already knows the x,y coordinates within the image.

I need to determine the location, size, and orientation of the grid and draw it on top of the image. This needs to work for any image with any grid size, location, and orientation.

The Solution (Using Geometric Stuff)

First the user needs to click somewhere to solve this problem. The first click is on the left-most smiley face. The user then tells the program that this is at location 3,8 in the grid. Then they click on the bottom-right smiley face and tell the program that it is at location 18,17 in the grid.

Assuming that the upper left corner of the grid is 0,0 and the upper left pixel in the image is 0,0, these are the steps to find the grid location using data from within the grid:

  1. Calculate the distance in pixels and in grid spaces between the two smiley faces. This is the distance directly, not the x,y distances. This tells us how many pixels are in each step of the grid or a ratio of pixels to grid units, whatever you want to call it.
  2. Get the angle from the left smiley face to the bottom-right one relative to the grid.
  3. Get the angle from the left smiley face to the bottom-right one relative to the pixels in the image.
  4. Get the difference between the two angles.
  5. Rotate the coordinates of the right smiley face by the angle difference from step 4. The right smiley face is now in the correct location as if the grid were not rotated relative to the pixels.
  6. Now the interesting part. Setting DX=grid_to_pixel_count and DY=0, rotate DX,DY around 0,0 using the negated angle from step 4. The result is a delta for X and a delta for Y for stepping one column right in the grid. These values can be switched and negated properly to step one row in the grid too.
  7. Start at the first selected smiley face and then step -4 columns, the negated user-specified grid column of the first smiley face, using DX and DY.
  8. Step -8 rows using DX and DY, -DY is used for the X coordinate change and -DX is used for the Y coordinate change (I think that I write that correctly).
  9. The upper left corner of the grid is found. The DX and DY stepping values are known for the grid so it can now be drawn under the smiley faces to show the result.

image

The Resulting Grid Underlay

My daughter and I tried to come up with a math solution that does not use angles and rotate points. It might be possible using ratios of the various numbers but we could not find the solution. Rotating one point and using it to get values that are then rotated the opposite way is not a bad solution and it works great.

Showing Line Numbers Without JavaScript

April 18th, 2013

This is a method for showing line numbers in online code listings without using JavaScript. Since this is so simple, I will only say that viewing the page source of this post will show the method quite clearly.

This is an example of my line numbering scheme.

The numbers are not text, they are an image and
never get copied when the code text is copied.

I did this using two tags, the pre tag and the code tag. I could have manipulated the background image to have the numbers and the horizontal stripes but it would be a big image and isn’t necessary for this blog where I can add both tags to code listings.