Re-reading this, I noticed a mistake. I wrote "CORNERSETS - is a boxed
list with 256." but I should have written "CORNERSETS - is a list of
256 boxes." (then going on to say that the end boxes have 1 item while
the rest of the boxes have 3 or 6 items - each item representing both
the 3d coordinates of a "corner" and the color of that "corner" - and
if the corny language isn't making sense then running the code and
looking at the display would probably help a lot).

I have also rewritten the code so that the dense parts are hopefully a
bit easier to read:

coclass 'colourchoice'
require 'jzopengl'
coinsert 'jzopengl'

Note 'wd'
  p - parent window
  s - scrollbar -- S will be numeric value 0..255
      repesents distance along white/black diagonal
  c - color display
)

NB. object constructor
create=:3 :0
  ogl=: ''conew'jzopengl'
  wd 'pc p;'
  wd 'xywh 0 0 10 256; cc s scrollbarv bottommove; set s 0 127 255 39;'
  S=: 127
  wd 'xywh 10 0 256 256; cc c isigraph opengl rightmove bottommove;'
  wd 'pas 0 0; pshow;'
)

NB. event handlers
p_close=: destroy

p_c_paint=: 3 :0
  rc__ogl''
  glClear GL_COLOR_BUFFER_BIT
  C=: S {:: CORNERSETS
  select. #C
    case. 1 do.
      if. C do. 1 1 1 tri 254 {:: CORNERSETS
      else.     0 0 0 tri 1   {:: CORNERSETS end.
    case. 3 do.
      tri C
    case. 6 do.
      tri C
  end.
  show__ogl''
)

p_s_button=: 3 :0
  S=: 0 ". s
  wd 'setinvalid c'
)

p_c_mbldown=: 3 :0
  trac 1
)

p_c_mmove=: 3 :0
  trac TRACK
)

p_c_mblup=: 3 :0
  trac 0
)

NB. implementation

destroy=: 3 :0
  destroy__ogl''
  wd'pclose'
  codestroy''
)

NB. a transform to plane tangent to white/black axis of colour cube
X0=: 1 _1 1 * %: 1 5 1%6
Y0=: _1 0 1 * %: %2
coords=: +/ .*"1&(X0,:Y0)"1

rms=: +/ &.: *:"1 NB. "root mean square" not "richard m stallman"

NB. use gift wrapping algorithm to find drawable order for corners
NB. http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
keep=: 0 {:: [     NB. part of pair on convex hull
try=:  1 {:: [     NB. part of pair not known to be on hull
start=: ,:@{. ; }. NB. structure list of corners for iterations using try/keep
NB. pick next corner based on angle
choose=: try #~ [: (= >./) -@^.@rms@(try -"1 {:@keep)
giftwrap=: i. 0 {:: (((keep,]) ; try-.]) choose)^:(#@try)@start

assert  12 2 3-: $CORNERPAIRS=: (#:i.8) {~ ~./:"1~8 8#:I.,1=rms-"1/~#:i.8
assert 12 86 3-: $CORNERVERTS=: (([ +"1 (85%~i.86) */ -~)/)"2 CORNERPAIRS
NB. 256 = 86+85+85
assert  (,256)-: $CORNERSETS=: (({~ giftwrap@:coords)^:(6=#))&.> (rms
<@~./. ]) ,/CORNERVERTS

corner=: 4 :0
  glColor3d x
  glVertex2d y
)

tri=: 3 :0"2
  y tri y
:
  glBegin GL_POLYGON
    x corner"1 coords y
  glEnd''
)

TRACK=: 0
trac=: 3 :0
  if. y+.TRACK do.
    smoutput y,TRACK,2 {. 0".sysdata
  end.
  TRACK=: y
)

smoutput '' conew 'colourchoice'


And remember that this is written for J version 6.

Thanks,

-- 
Raul


On Fri, Aug 9, 2013 at 12:25 PM, Raul Miller <rauldmil...@gmail.com> wrote:
> I should probably document this color-thing somewhat.
>
> From a top down view, let's pretend that I researched how we perceive
> color (and how this can vary from person to person), and how that
> relates to various implementations of how computers implement color.
> But really, this is something of cubic representation of color, with
> the slider representing the white-black range, and the colored part
> representing a cross section of that cube perpendicular to the
> white/black axis.
>
> Anyways, this line:
>
> CORNERSETS=: ((+/&.:*:"1) <@(({~ giftwrap)^:(6=#))@~./. ]) ,/(([ +"1
> (85%~i.86) */ -~)/)"2 ((#~ </"1)8 8 #:I. ,/1=|+/&.:  *:"1 -"1/~ #:i.8)
> { #:i.8
>
> represents that cube.
>
> This value - CORNERSETS - is a boxed list with 256.  The first box
> represents black (color: 0 0 0 - red, green, blue) and the last box
> represents white (color: 1 1 1). This concept of representing a color
> as a sequence of three numbers in the range 0..1 is convenient for use
> with opengl.
>
> The rest of the boxes contain slices of a polygon (either three sided
> or six sided) corresponding to a slice across a color cube
> perpendicular to the white/black access.  Each element of a box can be
> thought of as an rgb color value, or as a corner of the face of a
> polygon.
>
> So let's go bottom-up, for a bit, to see how this gets constructed.
>
> A cube has eight corners, and we can number them:
>    i. 8
> 0 1 2 3 4 5 6 7
>
> The binary representation of these numbers can be thought of as rgb
> coordinates for these eight colors.
>    #:i.8
> 0 0 0
> 0 0 1
> 0 1 0
> 0 1 1
> 1 0 0
> 1 0 1
> 1 1 0
> 1 1 1
>
> But that's not enough for the color palette that I wanted. I want not
> just the corners, but lines between them.  And, for that, I decided to
> pair up adjacent corners, so that I could draw lines between them.
> That's this:
>
>     ((#~ </"1)8 8 #:I. ,/1=|+/&.:*:"1 -"1/~ #:i.8) { #:i.8
>
> The part in parenthesis first finds differences between all corner pairs:
>    -"1/~ #:i.8
>
> and then finds the distance described by that pair
>    +/&.:*:"1 -"1/~ #:i.8
>
> And then I take an absolute value for no good reason - it's a holdover
> from an earlier version that's not useful here.  (I built this code
> "artistically" - thinking of the effect I wanted and using trial and
> error, based on appearance and taste, and then posted it before doing
> any final cleanup - I felt that give some of you some of the flavor of
> my code building process might be useful to you?)
>
> Anyways, the edges I am interested in have a length of 1, so that's
> easy to define:
>    1=+/&.:*:"1 -"1/~ #:i.8
>
> wait, I'm throwing away all that work! oh no!
>
> But the interesting bit is in the coordinates of the array, so I
> haven't lost anything essential here.  All I need to do is ravel it
> and use I. and I almost have the coordinates of the interesting edges.
>  (And I should have just used , instead of ,/ to flatten the cube - at
> the time I wrote it, I wasn't thinking clearly there - ,/ gets rid of
> just the leading dimension, and I was not looking at my data and had
> forgotten that I only had two dimensions here.)  But the problem with
> I., is that I just get a single number for each 1 bit, and I want a
> pair of numbers.  But I can recover the information as separate
> numbers by using an octal representation:
>
>    8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
>
> That gives me 24 rows of result, and a cube only has 12 edges. I went
> a bit over board here, and am representing each edge twice.  I can
> throw away half of them, but which half?  One easy approach discards
> edges where the first index is greater than the second index.  (#~
> </"1) accomplishes this, but there's another way:
>
>    ~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
> 0 1
> 0 2
> 0 4
> 1 3
> 1 5
> 2 3
> 2 6
> 3 7
> 4 5
> 4 6
> 5 7
> 6 7
>
> Now all I need are the corresponding rgb values for each of these cube
> indices.  I had used (expression) { #:i.8 to get those values, but
> there's another way:
>
>       #: ~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
>
> Here, I've a rank three array:
>
>    $#:~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
> 12 2 3
>
> The 12 is the number of edges of a cube, the 2 is the number of ends
> of each edge, and the 3 is the number of dimensions (which I will
> think of as red, green, and blue).
>
> If I could think up a good name, I'd probably stuff this in a variable
> to make the rest of it easy.
>
> Since this is getting long, I'll save the rest of it for another day
> (unless someone else wants to take up the banner here?)
>
> But, briefly, 255=3*85 so I if I make each edge 85 units long (which
> becomes 86 values if I include the zero of the axis) I get a total of
> 256 values making up my cube diagonal. And, since we have a fair bit
> of hardware designed around a 256 division scale for color rendering
> that seemed like a nice choice.
>
> Also, these edges are not arranged in any particular order, so I use a
> convex hull algorithm (giftwrap) to arrange them in a form useful for
> opengl rendering.
>
> (And, yes, I am aware that some opengl hardware is... less than ideal?
> in terms of color quality. That's not a priority issue for me, at this
> stage of the game.)
>
> So... time for lunch for me. And then I need to do something useful
> for the people I work for. I may or may not come back to this bit of
> code at a later time. Meanwhile, hopefully I will be able to have
> provoked at least a little speculation about what I've written here
> and what other mistakes I've made?
>
> Thanks,
>
> --
> Raul
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to