Trig example

Thanks again. The discussion has been helpful to me.

To graphics textbook authors everywhere, I apologize–on a more careful reading, my text in no way suggests that drawing a line between identical points should or will be supported in any implementation. I can see now that it’s problematic geometrically, as slope is undefined. But I’m not dealing with a class that has a property of ‘slope’ either, just plotting points on the display.

For that matter, my code would decide on infinite slope in that case, if it came to it. Any slope I calculate would be from real-world coordinates anyway–just that mapping those back through window/viewport routines may make the two real points the same one pixel on the display.

(EDIT: Public Service Warning!: Do not run, especially with random colours as suggested below, if you are prone to photo-sensitive epilepsy/seizures!)

some Polyspiral fun for now (for a simple use of trig) – I have a version using vec2s as points and a couple of supporting classes, but this was easier to cut and paste.

I see there are functions that do clipping against a rectangle, etc. so may make use of them more in future – plodding thru an old graphics textbook to refresh my understanding of principles.

-- Use this function to perform your initial setup
function setup()

    -- set up types and constants

    Maxx = WIDTH
    Maxy = HEIGHT
    
    R=Maxy/Maxx
    -- aspect ratio
    
    CD = 100
    --current direction angle
    
    CPx = math.floor(Maxx/2)
    CPy = math.floor(Maxy/2)
    --current position

    Wl=0
    Wt=Maxy
    Wr=Maxx
    Wb= 0
  
    --window in world coords - l,t,r,b
    --(how much of a model can we see?)
    --for now, same as screen size
    
   -- (adjust and MapRects again to "zoom"? how?)
    
    Vl=0.0
    Vt=R
    Vr=1.0
    Vb=0.0
    --view in (R)NDC coordinates
    --(where do we want to draw it?)
    --range up to 0,R,1,0 in real numbers
    
    --change with orientation?

    
    parameter("Distance",3,40,10)
    iparameter("Repeat",10,500,60)
    parameter("Angle",1,360,56.5)
    parameter("Increment",0,50,9)
    iparameter("LineWidth",1,20,4)
    
    smooth()
    lineCapMode(PROJECT)
   
    --for random colours
    --stroke(math.random(255),math.random(255),math.random(255)) 
    strokeWidth(LineWidth)
  --  clip()

    MapRects()

end

-- This function gets called once every frame
function draw()

    background(0, 0, 0, 0)

    saveCPx=CPx
    saveCPy=CPy
    
    --for random colours
    --stroke(math.random(255),math.random(255),math.random(255)) 
   strokeWidth(LineWidth)
    
    PolySpiral(Distance,Angle,Increment,Repeat)
    
    CPx=saveCPx
    CPy=saveCPy

end


function MapRects()
    --compute sx, tx, sy, ty needed to map points from 
    --W(indow - real world) to V(iew - NDC)

    -- call if window or viewport changed (zoom window, distort view)
    sx,sy,tx,ty=1,1,0,0
    
    sx = (Vr-Vl)/(Wr-Wl)
    sy = (Vt-Vb)/(Wt-Wb)
    tx = ((Vl*Wr)-(Wl*Vr))/(Wr-Wl)
    ty = ((Vb*Wt)-(Wb*Vt))/(Wt-Wb)
    
    
end

function PolySpiral(Dist,angle,incr,num)

    local i
    for i = 1,num do
       LineForward(Dist)
       TurnRight(angle)
       Dist = Dist + incr

    end
end

function MoveTo(x,y)
    -- move to point p (update current position in real world, CP)
  CPx=x
  CPy=y
end

function LineTo(x,y)
-- draw from current position CP to p
-- maybe prevent if same point?
-- but these are "real world" coordinates
   DrawLine(CPx,CPy,x,y)
   CPx = x
   CPy = y

end

function MoveRel(dx,dy)
    -- adjust current position by dx,dy
    CPx = CPx + dx
    CPy = CPy + dy
end

function LineRel(dx,dy)
-- draw from current position CP 
local x = CPx + dx
local y = CPy + dy
LineTo(x,y)

end

function LineForward(Dist)

  --local angle = CD * math.pi / 180
  local angle = math.rad(CD)

  local x = CPx + (Dist * math.cos(angle))
  local y = CPy + (Dist * math.sin(angle))
  LineTo(x,y)
 
end

function MoveForward(Dist)
 -- just update CP, don't draw line
--local angle = CD * math.pi /180
 local angle = math.rad(CD)
 
 local x = CPx + (Dist * math.cos(angle))
 local y = CPy + (Dist * math.sin(angle))

  CPx = x
  CPy = y
end

function TurnRight(angle)
    CD = CD - angle
    
    if CD < 0 then
        CD = CD + 360
    end
end

function LineNDC(x1,y1,x2,y2)

    x1=math.floor((x1*Maxx)+0.5)
    x2=math.floor((x2*Maxx)+0.5)

    y1=math.floor((y1*Maxx)+0.5)
    y2=math.floor((y2*Maxx)+0.5)
 

    line(x1, y1, x2, y2)

end


function MapPoint(x,y)
    
 -- map point x,y to point in NDC
 -- using values from MapRects

   x = (sx * x) + tx
   y = (sy * y) + ty
   return x, y

end

function HalfSpace(x,y)
 local l = false
 local t = false
 local r = false
 local b = false 
 
 if x < Wl then
    
    l = true
 end
 if x > Wr then
    r = true
 end
 if y < Wb then
    b = true
 end
 if y > Wt then
    t = true
  end
    
    return l,r,t,b
end

function Clipit(x1,y1,x2,y2,vis)
-- return 'visibility' and clipped line
-- clip real-world line segments against W
--Cohen-Sutherland clipping algorithm

 local in1=false
 local in2=false
 local done=false
  
  repeat
    
 l1,r1,t1,b1 = HalfSpace(x1,y1)
 l2,r2,t2,b2 = HalfSpace(x2,y2)
    
   in1 = not (l1 or t1 or r1 or b1)
   in2 = not (l2 or t2 or r2 or b2)
    
     if in1 and in2 then
        done = true
        vis = true
     elseif (l1 and l2) or (t1 or t2) or (r1 and r2) or (b1 and b2) then
            done = true
            vis = false
     else
            if in1 then
                -- swap , ensure p1 outside
    
              l1,l2,r1,r2,t1,t2,b1,b2=l2,l1,r2,r1,t2,t1,b2,b1
              x1,y1,x2,y2 = x2,y2,x1,y1

            end
            
            if x2 == x1 then -- line is vertical
                if t1 then 
                    y1 = Wt -- p1 is above
                -- ED.
                -- elseif c1.b then 
                elseif b1
                    y1 = Wb -- p1 is below
                end
            else -- not vertical
                m = (y2 - y1) / (x2 - x1) -- slope
                if l1 then
                    y1 = y1 + ((Wl - x1) * m)
                    x1 = Wl
                elseif r1 then
                    y1 = y1 + ((Wr - x1) * m)
                    x1 = Wr
                elseif b1 then
                    x1 = x1 + ((Wb - y1) / m)
                    y1 = Wb
                elseif t1 then
                    x1 = x1 + ((Wt - y1) / m)
                    y1 = Wt
                end
            end --vertical
        end
     until done 
    
 return x1,y1,x2,y2,vis

end

function DrawLine(x1,y1,x2,y2)
    
    local vis=false
    -- Ed.
    --nx1,ny1,nx2,ny2,vis = Clipit(x1,y1,x2,y2,vis)
    x1,y1,x2,y2,vis = Clipit(x1,y1,x2,y2,vis)


  if vis then

        nx1,ny1 = MapPoint(x1,y1)
        nx2,ny2 = MapPoint(x2,y2)
       
 
        LineNDC(nx1,ny1,nx2,ny2)

  end

end

(Edited to correct as below.)

I see other things I’ve done that are unnecessary, and certainly the code could be cleaned up otherwise, but that’s what this is for, quick development.

Well, I wasn’t that quick, but the code certainly seems to be. It runs pretty lickety-split on iPad2 (a total blur within a few seconds of trying to record anything, I can only see what I’m ‘doing’ for a few seconds. I haven’t tried recording anything else yet.)

Shoot, I think this works despite myself:

  nx1,ny1,nx2,ny2,vis = Clipit(x1,y1,x2,y2,vis)

  if vis then

        nx1,ny1 = MapPoint(x1,y1)
        nx2,ny2 = MapPoint(x2,y2)
       
        LineNDC(nx1,ny1,nx2,ny2)

  end

but it probably really should be either

 x1,y1,x2,y2,vis=Clipit(x1,y1,x2,y2,vis)

-or-

MapPoint(nx1,ny1) and MapPoint(nx2,ny2)

I changed it but can’t discern a difference – maybe because Codea politely clips for me when I’m being stupid! I commented out ‘clip()’ in setup shutting it off.

Originally: it was only vis=Clipit(p1,p2) and that’s all Clipit returned was vis. Simpler, but I mucked up on the table/variable scope with the vec2 stuff, and then switched it as above. It’s really the end result of my hacking at it until I got a result–but probably technically still not quite correct.

ack–and still incorrect–sorry, I should edit the original perhaps? [Edit: done.]
What is the etiquette? (Besides check my code better before posting? bleat bleat)

In Clipit function, the line:

elseif c1.b then 

should be

elseif b1 then

Almost certain I have a ‘stroke’ instruction in the actual code somewhere, but I don’t see it in the pasted code.

Anyway, it’s more fun when it’s colour - I changed it already from greyscale with stroke(math.random(255),math.random(255),math.random(255)) before the strokeWidth(LineWidth) calls in setup() and draw(), then.
(EDIT: DO NOT alter in this manner if prone to photo-sensitive epilepsy/seizures. Might be safer not to run it altogether, but at the very least, pick one colour.)