Wednesday 16 November 2016

DiscoBall - Poking a stick at Rhino3D RhinoCommons






using System;
using Rhino;
using Rhino.Commands;
using Rhino.Geometry;
using Rhino.Input;
using Rhino.Input.Custom;
using Rhino.DocObjects;

namespace CeeBeeTest
{
    [System.Runtime.InteropServices.Guid("845BC3BC-02FF-4ED8-A116-2B7E3FEB2293")]

    public class CeeBeeTest : Command
    {
        private bool m_escape_key_pressed;
        private int loop = 1;
        public CeeBeeTest()
        {Instance = this;}
        public static CeeBeeTest Instance
        {get; private set;}
        public override string EnglishName
        {get { return "DiscoBall"; }}

        void RhinoApp_EscapeKeyPressed(object sender, EventArgs e)
        {m_escape_key_pressed = true;}
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            RhinoApp.EscapeKeyPressed += RhinoApp_EscapeKeyPressed;
            RhinoApp.WriteLine("The {0} creates a sphere with a random colour.", EnglishName);
            m_escape_key_pressed = false;

            Point3d pt0;
            using (GetPoint getPointAction = new GetPoint())
            {
                getPointAction.SetCommandPrompt("Click starting point.");
                if (getPointAction.Get() != GetResult.Point)
                {
                    RhinoApp.WriteLine("No start point was selected.");
                    return getPointAction.CommandResult();
                }
                pt0 = getPointAction.Point();              
            }

            Point3d pt1;
            using (GetPoint getPointAction = new GetPoint())
            {
                getPointAction.SetCommandPrompt("Click end point.");
                getPointAction.SetBasePoint(pt0, true);
                getPointAction.DynamicDraw +=
                  (sender, e) => e.Display.DrawLine(pt0, e.CurrentPoint, System.Drawing.Color.DarkRed);
                if (getPointAction.Get() != GetResult.Point)
                {
                    RhinoApp.WriteLine("No end point was selected.");
                    return getPointAction.CommandResult();
                }
                pt1 = getPointAction.Point();
            }

            Sphere sphere1 = new Sphere(pt0, pt0.DistanceTo(pt1));
            Random rnd = new Random();
            var attributes = new ObjectAttributes();
            int cnt = 0;
            while (loop == 1) 
            {
                cnt++;             
                if (m_escape_key_pressed) loop = 2;
                int RED = rnd.Next(1, 255);
                int BLUE = rnd.Next(1, 255);
                int GREEN = rnd.Next(1, 255);
                RhinoApp.SetCommandPrompt("Running colour #" + cnt + " press [ESC] to exit");                
                attributes.ObjectColor = System.Drawing.Color.FromArgb(RED,BLUE,GREEN);
                attributes.ColorSource = ObjectColorSource.ColorFromObject;
                Guid thesphere = doc.Objects.AddSphere(sphere1, attributes);
                doc.Views.Redraw();            
                doc.Objects.Delete(thesphere, true);             
            }

            loop = 1;
            doc.Objects.AddSphere(sphere1, attributes);
            doc.Views.Redraw();
            RhinoApp.WriteLine("Congrats, you just made a disco ball! Radius {0} {1}.", pt0.DistanceTo(pt1), doc.ModelUnitSystem.ToString().ToLower());
            RhinoApp.EscapeKeyPressed -= RhinoApp_EscapeKeyPressed;
            return Result.Success;
        }
    }
}

Wednesday 2 November 2016

Tkinter and Picamera in Python on RPi.

                                        (this is not my jewellery CNC blog, that's here : http://digital-jeweller.blogspot.com/)



              RPi Tkinter and Picamera

Having exhausted my attempts at getting results from my UP board which has no real working API and not much developer representation on its forum, other than to post the new products for sale, I have moved my efforts back to the RPi. 

Running IoT it has a reasonably fast result once setting the board to turbo, but its still pulling video over USB, which still sucks it dry and it has no drivers to utilise the RPi PiCamera which is lightning fast running on the GPU. 

SO: Something I have been trying to avoid.. Linux.. domain of pimpled skinny guys in server rooms with leaking pens in their pockets , and halitosis.... 

The API for Picamera is stunningly easy to use, best api I have seen to date, its biggest drawback however is the way it previews the camera, which cannot be locked to a window unless you do some opencv trickery which really drains the cpu.. you can trick the Tkinter window into a locked state (it cannot be moved or sized) with a single command though, and then overlay the preview, which gives a similar effect. Not yet decided how that plays out for me... 

My first crack at this was to familiarize myself with Tkinter and the Picamera copmands, so the obvious choice was to develop an interface to play with all the commands:

Create a Window
Create Sliders
Create DropDown boxes
and get them all talking to Picamera. 

Surprisingly small amount of code to be honest..

#!/usr/bin/python
import Tkinter as tk
import RPi.GPIO as GPIO
import picamera
from time import sleep

camera = picamera.PiCamera()
choices = ['off', 'auto', 'sunlight','cloudy','shade','tungsten','fluorescent','incandescent','flash','horizon']
effects = ['none','negative','solarize','sketch','denoise','emboss','oilpaint','hatch','gpen','pastel','watercolor','film','blur','saturation','colorswap','washedout','posterise','colorpoint','colorbalance','cartoon','deinterlace1','deinterlace2']

def CameraON():
    camera.preview_fullscreen=False
    camera.preview_window=(90,100, 320, 240)
    camera.resolution=(640,480)
    camera.start_preview()
    
def CameraOFF():
    camera.stop_preview()
    
def EXIT():
    root.destroy
    camera.stop_preview()
    camera.close()
    quit()

def UpdateBrightness(value):
    camera.brightness = int(value)
    
def UpdateContrast(value):
    camera.contrast = int(value)
    
def UpdateSharpness(value):
    camera.sharpness = int(value)
    
def UpdateSaturation(value):
    camera.saturation = int(value)

def SetAWB(var):
    camera.awb_mode = var

def SetEFFECTS(var):
    camera.image_effect = var

def Zoom(var):
    x = float("0."+var)
    camera.zoom = (0.5,0.5,x,x)
    
root = tk.Tk()
root.resizable(width=False, height=False)
root.geometry("320x300+89+50")
root.title("Camera Button Test")

root.buttonframe = tk.Frame(root)
root.buttonframe.grid(row=5, column=3, columnspan=2)

tk.Button(root.buttonframe, text='Start Camera', command=CameraON).grid(row=1, column = 1)
tk.Button(root.buttonframe, text='Kill Camera', command=CameraOFF).grid(row=1, column = 2)
tk.Button(root.buttonframe, text='Exit Program', command=EXIT).grid(row=1, column = 3)

tk.Scale(root.buttonframe, from_=30, to=100, orient=tk.HORIZONTAL, label = "Brightness", command=UpdateBrightness).grid(row=2,column=1)
tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL, label = "Contrast", command=UpdateContrast).grid(row=2,column=2)
tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL, label = "Sharpness", command=UpdateSharpness).grid(row=2,column=3)
tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL, label = "Saturation", command=UpdateSaturation).grid(row=3,column=1)
tk.Scale(root.buttonframe, from_=10, to=99, orient=tk.HORIZONTAL, label = "Zoom", command=Zoom).grid(row=4,column=1)

AWB_Var = tk.StringVar(root)
AWB_Var.set(choices[0]) 
AWB_Option = tk.OptionMenu(root.buttonframe, AWB_Var, *choices, command=SetAWB).grid(row=3,column=2)

EFFECT_Var = tk.StringVar(root)
EFFECT_Var.set(effects[0]) 
EFFECT_Option = tk.OptionMenu(root.buttonframe, EFFECT_Var, *effects, command=SetEFFECTS).grid(row=3,column=3)

#enable next line to lock window in place                     
#root.overrideredirect(True)

root.mainloop()

and the output while not exactly professional looking was quite a good result for a new language (for me anyhow)

time to start adding the GPIO to run the camera table now.