This split line:

CORNERSETS=: (({~ giftwrap@:coords)^:(6=#))&.> (rms <@~./. ]) ,/CORNERVERTS

would need to be joined together to make the code runnable.

:/

-- 
Raul


On Tue, Dec 10, 2013 at 9:21 PM, Raul Miller <[email protected]> wrote:
> Trying again - I've shortened some lines so hopefully the code will
> actually run (I wish gmail would let me see ahead of time where lines
> of code will wrap).
>
> 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. 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"
>
> NB. use gift wrapping algorithm to find drawable order
> NB. http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
> start=: ,:@{. ; }. NB. structure list of corners for iterations
> keep=: 0 {:: [     NB. part of pair on convex hull
> try=:  1 {:: [     NB. part of pair not known to be on hull
> NB. pick next corner based on angle:
> choose=: try #~ [: (= >./) -@^.@rms@(try -"1 {:@keep)
> giftwrap=: i. 0 {:: (((keep,]) ; try-.]) choose)^:(#@try)@start
>
> CORNERPAIRS=: (#:i.8) {~ ~./:"1~8 8#:I.,1=rms-"1/~#:i.8
> CORNERVERTS=: (([ +"1 (85%~i.86) */ -~)/)"2 CORNERPAIRS
> NB. 256 = 86+85+85
> 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'
>
> --
> Raul
>
> On Tue, Dec 10, 2013 at 9:17 PM, Raul Miller <[email protected]> wrote:
>> 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 <[email protected]> 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