Category Archives: Gorgeous Apps

B4J: ABMaterial Public 1.05/Donators 1.06 now released

The public version 1.05 of ABMaterial is now available from the B4J website!  Three new controls:

ABMSlider: Add a slider for values with a wide range.

Range

ABMRange: Add a range slider for values with two handlers.

Slider

ABMCustomControl: add your own components to the ABMaterial framework.

CustomComponent

Some more highlights on this release:

  • Complete rewrite of the Refresh system
  • Material Icon Fonts are now loaded locally
  • Disable the back button in the browser
  • ABMModalSheet FULL size option
  • LocalStorage support
  • ABMPlatform object containing basic info on the users browser and device
  • Integrate variables for SEO-optimization
  • Responsive tables

Read the README1.05.TXT for the full release notes.

Download ABMaterial Public version 1.05

Donators will receive an email with the download link to ABMaterial 1.06 containing two new controls, ABMDataTimeScroller and ABMDateTimePicker.

Happy programming!

Alwaysbusy

Click here to Donation if you like my work


Xojo: Comanche 3D in about 100 lines UPDATE

Tomas made HUD and Maps active!

Tomas made HUD and Maps active!

A quick update with a much smoother and faster version of the ABComanche article. This one is using some tricks out of the ABXVision framework using Memoryblocks and pointers. (Don’t worry, sound worse than it is).

You can download this new version here

I’ve been amazed how many people enjoyed playing with this! Some of you made great additions like the HUD display, camera views and added sound. Thanks Tomas Jakobs for this! Will Shank even made a OpenGL viewer for the maps. It’s not using the voxel engine discribed in the previous article but it looks great!

Will Shanks OpenGL version!

Will Shanks OpenGL version!

Check out the Xojo forum post for their creations!

Cheers!

Alwaysbusy

Click here to Donation if you like my work


Xojo: ABXVision – Version 1.0 Released

ABXVisionDISCONTINUED: Interested parties in purchasing the source code can contact me via email.

This is the first public release of ABXVision! I’ve spend a lot of time setting it up. Creating the documentation for the framework also took a fair amount of time, but as this project will grow in the future, it’s best I start documenting it from the beginning.

To centralize everything about ABXVision, I’ve created a new menu item on top of this page. Here you’ll be able to find the latest version, the help and the projects I’ll create with the ABXVision framework in the upcoming articles.

Latest version can be downloaded here

ABXVision

Halfway through writing the documentation, I realized this would take longer than expected so I stopped and build a tool to help me maintain the documentation: ABXDocumentor. I have a very good feeling about this tool and will probably update it and release it on this blog.

In the upcoming weeks I will try to write some demos using the framework. The first one will handle some basic functionality like ABXVImage as this object is really important. Later we’ll move on to Augmented Reality, Motion detection, maybe something on playcard recognition. Who knows were it takes us.

I just finish with this note: This is version 1.0. Not all functionality was tested so I can use your feedback to update it. I hope you join me on this ongoing journey and show us some projects your created with the framework.

Alwaysbusy

Click here to Donation if you like my work


Xojo: ABXVision 1.0 progress update

DISCONTINUED: Interested parties in purchasing the source code can contact me via email.

ABXVision
Some readers are getting impatient to try out ABXVision. So, I decided to pause programming new features for now and started to document the current framework. This is a big task but is needed for this kind of framework.

The main purpose of ABXVision is giving students and researchers the tools to do Computer Vision and A.I. with a RAD tool like Xojo. Without being a programming genius with a Phd in C++ or ASM, they can experiment with cutting edge algorithms with the ease of creating simple desktop apps.

Some of you who are familiar with Aforge will notice the resemblance. A lot of code is a direct translation of this framework to Xojo (mixed with own functions, Xojo optimalisations, Xojo wrappers to make it simpler to use, and translated code from other frameworks). I think it will make it easier to try out some of the functionalities by checking out the .NET examples. The code will be very similar when you try it out in Xojo.

The first release will contain GlyphDetectors, Color Filters, Edge Filters, Blur Filters, Motion Detectors, Blob finders, Transformations, Binarizers, Augmented Reality, etc… So a complete toolbox to start Computer Vision with Xojo!

Future features will be Fuzzy Logic, Neural Networks, Machine Learning, Genetic Algotithms, a lot more filters, Contour detectors, Corner Detectors, Interesting Point algorithms, Moment Computers, Kinematic… etc.

Carry on coding!

Alwaysbusy


Xojo: Mouse (Touch) Gestures Engine

Random Generated Gestures

Random Generated Gestures

Here is a complete framework to make ‘gestures’ with the mouse (or touch) to perform some action. It’s a Xojo translation (with some additions) of the work of Dr Per Ola Kristensson. The engine can recognize user build gestures on the fly.

As always, I’ve tried to make using the engine as easy as possible. The Engine contains the following classes:

Gesture Engine Structure

Gesture Engine Structure

You can use this with very little code, so let’s start!

In the Open() of the window, Initialize a ABMGRecognizer:

  ' MUST BE INITIALIZED AS SOME FUNCTIONS ARE USED TO BUILD THE TEMPLATE BITMAP IN VALUEPAIR !
  Recognizer = new ABMGRecognizer

Load some templates in the engine. A template is build by adding keypoints. Suppose we want to add the following template:

Example Template

Example Template

dim ID as string = "My template"
dim Templates(-1) as ABGMTemplate
' set the points
dim newPoints as new ABMGPoints
newPoints.Vals.Append(new ABMGPoint(0,0)) ' start point (always 0,0)
newPoints.Vals.Append(new ABMGPoint(0,1)) ' One Down (0 + 1 = 1)
newPoints.Vals.Append(new ABMGPoint(-1,2)) ' One Left (0 - 1 = -1), One down (1 + 1 = 2)
newPoints.Vals.Append(new ABMGPoint(-1,0)) ' two Up (2 - 2 = 0)
newPoints.Vals.Append(new ABMGPoint(-2,0)) ' One left (-1 - 1 = -2)
newPoints.Vals.Append(new ABMGPoint(-2,-1)) ' One Up (0 - 1 = -1)
' create and add the template
Templates.Append(new ABMGTemplate(ID, newPoints))

So every point is relative to the start point (0,0).

Next we add the Templates() to the the engine:

  ' Creates the continuous gesture recognizer for the template set. This
  ' template set can be changed later by calling the recognizer's
  ' setTemplateSet method. The second parameter is the distance between
  ' sampling points in the normalized gesture space (1000 x 1000 units).
  ' A lower value improves precision at the cost of increased memory and
  ' processing time.
Recognizer = new ABMGRecognizer(Templates, 5)

In the canvas we handle the movement of the mouse cursor. We add the new position to Input (global defined ABMGPoints). And run a recognize function to check for the pattern.

Function MouseDown(X as integer, Y as integer) as Boolean
    ' Initilaize our Input
    Input = new ABMGPoints
End Function

Function MouseDrag(X as integer, Y as integer)
    ' add the new point
    Input.Vals.Append new ABMGPoint(X,Y)
    Recognize
End Function

Function MouseUp(X as integer, Y as integer)
     ' add the last point
    Input.Vals.Append new ABMGPoint(X,Y)
    Recognize
End Function

Sub Recognize()
  if Input = nil then Return
  if UBound(Input.Vals) < 1 then Return ' we need at least to points
  if Recognizer = nil then Return ' precaution
  dim Results() as ABMGResult = Recognizer.Recognize(input)
  if Ubound(Results) = -1 then
    Return ' nothing found
  end if
  ' do something with the results! They are ordered with the most likely one first.
End Sub

A more extented example is added at the bottom of this article.
Here you can see the extended example running:

This engine works on Xojo for Windows and OSX.

Download the full source code from:
http://gorgeousapps.com/ABMouseGesture.zip

Bye!

Alwaysbusy

Click here to Donation if you like my work


Xojo: About cables, chains and other curves…

Mimicking Propellerheads Reason interface in Xojo

Mimicking Propellerheads Reason interface in Xojo

When I first saw Propellerheads Reason interface years ago, I was mesmerised by the cabling system. It seemed so intuitive to connect devices with each other. I rebuilded such an interface in RealBasic and was very satisfied with it. Lataly, I stumbled on this old project and I decided to give it a go in Xojo. It seemed like a good idea for an article on my blog.

For this article I wrote some classes (ABCable mainly) so it’s easy to implement in other projects in Xojo. I wrote a quick and dirty system to add and move cables cutting a couple of corners, as you may know I tend to do 🙂
When you want to use such a system, I urge you to rewrite that part in a more stable framework. But all the principles are here.

The Windows and OSX versions will also look slightly different. I did not find a good way to draw a smooth Catenary curve with the MacOSLib so I decided to use different functions for them, simulating the Windows version as much as possible. (Check DrawOSX and DrawWIN in the ABCable class to see what I’ve done). You can rewrite them as you please.

ABCable has three possible constructors:

' use for itaerations
Constructor()
' the start and end point, the color, the minimum length of the cable (will not be exact), the cable thickness (experimental)
Constructor(iStartPoint as ABPoint, iEndPoint as ABPoint, iCableColor as Color, iCableMinimumLength as double, iCableThickness as double )
' is the same as above but with an additional parameter: iPointSpacing
' this param can be used to 'smoothen' the curve by considering more points. The default is 8 segments. Increasing this number will slow down the animation.
Constructor(iStartPoint as ABPoint, iEndPoint as ABPoint, iCableColor as Color, iCableMinimumLength as double, iPointSpacing as Double, iCableThickness as double )

The other functions you’ll need from the ABCable class are:

Draw(DrawType as integer)

This function updates the graphics. I added two types of drawing. You can use DrawType to change it to the way you like:
DRAWBEZIER: Draw the curve as a Bezier curve
DRAWCATENARY: Draw the curve as a Catenary curve (for OSX it’s a simulation as described above)

The left one is as a Bezier, the other as a Catenary.

Drawtype as Bezier and as Caterary

Drawtype As Bezier and as Caterary

SetStartPoint(value as ABPoint)
SetEndPoint(value as ABPoint)

With these functions you can change the the Start en End connection points of the cable.

All the rest is done automatically (the shadow of the cable, the length increases/decreases when needed, etc…)

Let’s get into the rest of the program using this class.

I’m using a trick we learned in a previous canvas lesson to find where cables are and if there are connection points. We need 3 pictures. Our background without cables, a picture with the possible connection points in yellow (&cFFFF00) and a third one with the current connections. This last one will be created within the program and changes dynamically. (I’ll go deeper into this last one later in this article)

Principle

Click to enlarge

I’ll go through some of the source code and explain each part as we encounter it.

First, setup manual double buffering as we did in all the other lessons (using pBuffer as Picture, gBuffer as Graphics) so that our paint event in the canvas can simply be:

Sub Paint(g As Graphics)
  if pBuffer <> nil then
    g.DrawPicture pBuffer,0,0
  end if
End Sub

In the open event of the Window, we’ll set everything up:

Sub Open()
  ' setup the buffer
  pBuffer = New Picture(Canvas1.Width, Canvas1.Height, 32)
  gBuffer = pBuffer.Graphics

  ' setup the connections bitmap
  CurrentConnections = New Picture(Canvas1.Width, Canvas1.Height, 32)

  ' try = DRAWBEZIER to see another effect
  DrawMethod = DRAWCATENARY

  ' Important! Set lastColor to 2 so even numbers, not = 0, are startpoints, odd numbers are endpoints
  ConnectionLastColor = 2

  ' draw it
  DrawCables
End Sub

We initialized our Buffer and also our CurrentConnections bitmap (the third picture from above). It has the same dimensions as the canvas (and background). We pick a Drawing method (here the Catenary type) and a help variable for identifying the start and end points of each cable we will draw. As the background is black, we’ll start at 2 so our starts will be even numbers (not being 0) and our odd numbers will be the end points. Finally, we draw the cables (in this case, none are defined, so just the background).

I’ll come back to the DrawCables function in a moment. First let’s check the canvas mouse events:

Function MouseDown(X As Integer, Y As Integer) As Boolean
  ' check if it is an existing cable
  dim c as ABCable
  c = CheckCables(X,Y)
  if c <> nil then
    BringToFront(c)
    DrawCables
  end if

  Return true
End Function

Sub MouseDrag(X As Integer, Y As Integer)
  if IsDraggingEnd then
    Cables(UBound(Cables)).SetEndPoint(new ABPoint(X,Y))
    DrawCables
    me.MouseCursor = System.Cursors.InvisibleCursor
  Elseif IsDraggingStart then
    Cables(UBound(Cables)).SetStartPoint(new ABPoint(X,Y))
    DrawCables
    me.MouseCursor = System.Cursors.InvisibleCursor
  end if
End Sub

Sub MouseUp(X As Integer, Y As Integer)
  if IsDraggingStart or IsDraggingEnd then
    dim col as Color
    col = CurrentConnections.Graphics.Pixel(X,Y)
    if col <> &c000000 then ' it's used by another one, cannot be connected
      Cables.Remove(UBound(Cables))
    else
      ' is it a connection point?
      col = BackgroundConnections.Graphics.Pixel(X,Y)
      if col <> &cFFFF00 then ' not yellow, so can not be used to connect a cable
        Cables.Remove(UBound(Cables))
      end if
    end if
    IsDraggingStart = false
    IsDraggingEnd = false
    DrawCables
  end if

  me.MouseCursor = System.Cursors.StandardPointer
End Sub

In the MouseDown we’ll check if we have an existing cable or if we have to create a new one. This is done with the CheckCables() function. This function uses the CurrentConnections picture to check which, if any, cable you clicked on. We grab the pixel at postion X,Y and if it’s not black, we’ve touched a start or end point of a cable. If the color is even, we have a start point so we set IsDraggingStart = true. If it is odd, we’ll set IsDraggingEnd = true.

If it is black, we’ll check if it may be a possible connection point. We grab the pixel at position X,Y in the BackgroundConnections picture. If it is yellow, we can create a new Cable. We always assume you’re dragging the end of the cable to we’ll set IsDraggingEnd = true.

In both cases, we return the existing cable, the new cable or nil if you just clicked on the background. Check out the code to see how it works. I’ve added comments to make it easier to follow.

Function CheckCables(X as integer, Y as integer) As ABCable
  Dim c as ABCable

  dim col as Color
  dim colInt as Integer
  ' check if a cable is already connected to this connection point
  col = CurrentConnections.Graphics.Pixel(X,Y)
  if col <> &c000000 then ' it's an existing one
    for each c in Cables
      if c.StartPointColor = col or c.EndPointColor = col then
        ' found the cable
        colInt = ColorToInteger(col)
        if colInt mod 2 = 0 then
          ' is the start
          IsDraggingStart = true
        else
          ' is the end
          IsDraggingEnd = true
        end if
        Return c
      end if
    next
  else ' it's a new one, can it be connected
    col = BackgroundConnections.Graphics.Pixel(X,Y)
    if col = &cFFFF00 then ' yellow, so can be used to connect a cable
      dim i as Integer
      ' pick a random color for the cable
      dim NewCableColor as Color
      i = rnd*4
      select case i
      case 0
        NewCableColor = RGB(242, 131, 42)
      case 1
        NewCableColor = RGB(97,149,102)
      case 2
        NewCableColor = RGB(110,196,196)
      case 3
        NewCableColor = RGB(206,73,78)
      end select
      ' create a new cable
      c = new ABCable(new ABPoint(X,Y), new ABPoint(X,Y), NewCableColor,400,30)
      ' set its start end end color for the CurrentConnections bitmap to trace the mouse
      c.StartPointColor = IntegerToColor(ConnectionLastColor)
      c.EndPointColor = IntegerToColor(ConnectionLastColor+1)
      ' update the new last color for the next cable
      ConnectionLastColor = ConnectionLastColor + 2
      ' add the cable
      Cables.Append c
      ' always assume it's the end
      IsDraggingEnd = true
    end if
  end if

  Return c
End Function

Now we return to the MouseDown() event. If we have a Cable (c not nil), bring this cable to the front and draw again.

When we pass through the MouseDrag() event, one of our ends (start or end) will be active. Depending on which one it is, we’ll adjust the position by using SetStartPoint and SetEndPoint of the last Cable in our stack. Because we used the BringToFront() function, the last one in the stack is always our current one.

In the MouseUp() event we’ll do something similar as in the CheckCables() function. Now we first check if nobody is yet connected to this connection point (CurrentConnections.Graphics.Pixel(X,Y) not &c000000). In this case, we’ll just remove the cable. If it is black, we’ll check if it is a possible connection point (BackgroundConnections.Graphics.Pixel(X,Y) not &cFFFF00 ‘ yellow). If it is something else than yellow, remove the cable also.

Reset the Dragging variables to false and Draw the cables.

In the DrawCables() function, we’ll do five things:
1. Setup our GDIPlusGraphics for windows or our CGContextGraphicsPort for OSX if not done yet
2. We draw the background
3. We reset the CurrentConnection picture
4. We’ll draw all the cables on it
5. We’ll draw the current Start and End points of the cables to our CurrentConnection picture

Sub DrawCables()
'1. SETUP + 2. DRAW THE BACKGROUND
  #if TargetWin32
    if WINGfx = nil then
      dim s as Status
      WINGfx =  new GdiPlusGraphics( gBuffer.Handle( Graphics.HandleTypeHDC ) )
      s = WinGfx.SetInterpolationMode(InterpolationMode.High)
      s = WinGfx.SetCompositingQuality(CompositingQuality.High)
      s = WinGfx.SetSmoothingMode(SmoothingMode.AntiAlias)
    end if
    gBuffer.DrawPicture BackGround,0,0
  #else
    if OSXGfx = nil then
      OSXGfx = new CGContextGraphicsPort( gBuffer )

      OSXGfx.SetSAllowsAntialiasing(true)
      OSXGfx.SetShouldAntialias(true)

      OSXGfx.TranslateCTM(0, gBuffer.Height)
      OSXGfx.ScaleCTM(1.0, -1.0)
    end if
    OSXGfx.SaveGState
    OSXGfx.TranslateCTM(0,gBuffer.Height)
    OSXGfx.ScaleCTM(1.0, -1.0)
    dim r as CGRect = CGRectMake(0,0,gBuffer.Width, gBuffer.Height)
    if ImageOSX = nil then
      dim f as FolderItem
      dim p as Picture
      f = GetFolderItem("Background.png")
      if f.Exists then
        ImageOSX = CGImage.NewCGImage(p.Open(f))
      end if
    end if
    OSXGfx.DrawImage(ImageOSX, r)
    OSXGfx.RestoreGState
  #endif

' 3. CLEAR THE CURRENT CONNECTIONS
  CurrentConnections.Graphics.ForeColor = &c000000
  CurrentConnections.Graphics.FillRect 0,0, CurrentConnections.Width, CurrentConnections.Height

' 4. DRAW ALL OUR CABLES + 5. DRAW OUR START AND ENDPOINTS
  dim c as ABCable
  for each c in Cables
    c.Draw(gBuffer, DrawMethod)
    ' if it's not the current cable
    if c <> Cables(UBound(Cables)) then
      CurrentConnections.Graphics.ForeColor = c.StartPointColor
      CurrentConnections.Graphics.FillOval(c.StartPoint.x-6, c.StartPoint.y-6, 12,12)
      CurrentConnections.Graphics.ForeColor = c.EndPointColor
      CurrentConnections.Graphics.FillOval(c.EndPoint.x-6, c.EndPoint.y-6, 12,12)
    else
      'if it is, see if it is being dragged
      if not IsDraggingStart then
        CurrentConnections.Graphics.ForeColor = c.StartPointColor
        CurrentConnections.Graphics.FillOval(c.StartPoint.x-6, c.StartPoint.y-6, 12,12)
      end if
      if not IsDraggingEnd then
        CurrentConnections.Graphics.ForeColor = c.EndPointColor
        CurrentConnections.Graphics.FillOval(c.EndPoint.x-6, c.EndPoint.y-6, 12,12)
      end if
    end if
  next
  Canvas1.Refresh(false)
End Sub

The result is this:

ConnectionPoints Principle

Click to enlarge

The first is the result in our Buffer. The second one is the result of the CurrentConnections Drawings. We’ll see the start and end points. The third picture is just to show you where each point in CurrentConnections comes from. So now you see when we use the CheckCables function, we can know exactly which cable and at what end we clicked by checking the pixel color of currentConnections.

Note: the colors in 2 and 3 are faked to make it clear how the principle works. In the real thing, all points are only one integer away from each other, but this is not very visible for us.

And that’s it! There are some help functions like IntegerToColor, ColorToInteger and an extra MouseMove event to hide the cursor but they need no explanation.

This was a fun project I think. Let’s look how it goes in this video:

You can download the full source code here:
http://gorgeousapps.com/ABCablesOSXWINXojo.zip

This concludes the cable and chains tutorial.

Alwaysbusy

Click here to Donation if you like my work


QuiQRun! launched

Barcelona Skin

Barcelona Skin


QuiQRun!, the social, fast barcode scanner and creator!

I’m very happy to release the first version of QuiQRun! for Android! In the next weeks I may do a couple of articles on the blog on how some things are done. (Basic4Android and Java).

I want to thank everyone that did test and translate the app!

Download free version

Please rate QuiQRun! if you like it!

More information and screenshots can be found at http://www.quiqrun.com

Alain


%d bloggers like this: