Alex Tweedly wrote:

I'll post a couple of suggested solutions shortly (once I've got the stack running properly)

There are two approaches (at least) that consistently get the same answers as we all intuitively "know" are correct.

By AREA.

Calculate the (signed) area between each edge and some baseline (i.e. the area enclosed by the edge itself, its projectino onto the baseline and the two projection lines). Sum this area for all edges. Looking at whether this is positive or negative gives an answer.

By Point.

Find the leftmost, lowest point (**). (i.e. the one with the lowest X value, and of all those having the same X value, the lowest Y value). (Note that this same point (value) can occur multiple times in a polygon, due to self-intersection or self-overlapping polygons - this doesn't matter, just pick any of those points). Looking at the previous and next points, determine the change of direction implied for these two edges (you could use the cross-product to do this, or simply normalize and compare the gradients).

(**) - this description assumes 'normal' cartesian coordinates. Beware that RunRev uses a coordinate system where the vertical axis is "upside-down", so increasing Y values are associated with moving downawards.

Some sample code - adopted from elsewhere (and translated into revtalk) - with only moderate testing, but I'm fairly confident I converted it fairly accurately.
(It's a bit wordy, but seemed clearer that way).
constant kDebug  = false
on mouseUp
   put empty into field "F"
   repeat with i = 1 to the number of controls
      if char 2 to -2 of word 2 of the name of control i = "Polygon" then
         repeat for each line L in the points of control i
            put L & "; " after field "F"
         end Repeat
         put CR after field "F"
         if calculateflowusingarea (i, kDebug) then
            put "counterclockwise" & CR after field "F"
         else
            put "clockwise" & CR after field "F"
         end if
         if calculateflowusingpoint (i, false) then
            put "counterclockwise" & CR after field "F"
         else
            put "clockwise" & CR after field "F"
         end if
      end if
   end repeat
end mouseUp
function calculateflowusingarea P, pDebug
   put the points of control P into tPoints
   put item 1 of line 1 of tPoints into x2
   put item 2 of line 1 of tPoints into y2
   put 0 into total
   repeat for each line L in tPoints
      put x2 into x1
      put y2 into y1
      put item 1 of L into x2
      put item 2 of L into y2
      put (x2-x1) * (0.5*(y1+y2)) into t
if pDebug then put (x2-x1) && (x2-x1)*0.5*(y2+y1) && x1 && y1 && x2 && y2 && t & CR after field F
      add t to total
      put L into tLast
   end repeat
-- close the polygon in the case where Rev has an open polygon
   if tLast <> line 1 of tPoints then
      put x2 into x1
      put y2 into y1
      put item 1 of line 1 of tPoints into x2
      put item 2 of line 1 of tPoints into y2
      put (x2-x1) * (0.5*(y1+y2)) into t
if pDebug then put (x2-x1) && (x2-x1)*0.5*(y2+y1) && x1 && y1 && x2 && y2 && t & CR after field F
      add t to total
   end if
   if pDebug then put "Total is " & total & CR after field "F"
   return total > 0   -- i.e. true if the polygon is counter-clockwise
end calculateflowusingarea
function calculateflowusingpoint P, pDebug
   put the points of control P into tPoints
-- find the leftmost, lowest point put item 1 of line 1 of tPoints into x
   put item 2 of line 1 of tPoints into y
   repeat with i = 1 to the number of lines in tPoints
      if item 1 of line i of tPoints < x or \
(item 1 of line i of tPoints = x and item 2 of line 1 of tPoints <= y) then
         put item 1 of line i of tPoints into x
         put item 2 of line i of tPoints into y
         put i into tOne
      end if
   end repeat
-- find the adjacent points
   switch tOne
      case 1
         put the number of lines in tPoints into tPrev
         put 2 into tNext
         break
      case the number of lines in tPoints
         put tOne-1 into tPrev
         put 1 into tNext
         -- special case where the poly is already closed !!
         if line tOne of tPoints = line 1 of tPoints then put 2 into tNext
         break
      default
         put tOne-1 into tPrev
         put tOne+1 into tNext
         break
   end switch
if pDebug then put x && y && tPrev && tOne && tNext & CR after field "F" if pDebug then put line tPrev of tPoints && x && y && line tNext of tPoints & CR after field "F"
   -- now deal with the end-cases
if item 1 of line tPrev of tPoints = x then return false -- incoming edge is vertical, so counter
   if item 1 of line tNext of tPoints = x then return true -- outgoing ...
   -- so can safely that x-delta's are non-zero
put (y-item 2 of line tPrev of tPoints) / (x-item 1 of line tPrev of tPoints) into yprev put (y-item 2 of line tNext of tPoints) / (x-item 1 of line tNext of tPoints) into ynext
   if pDebug then put "ys are " && yprev && ynext & CR after field "F"
if yprev < ynext then return true
   return false
end calculateflowusingpoint

_______________________________________________
use-revolution mailing list
use-revolution@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-revolution

Reply via email to