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