On 16/01/2007, at 12:28 PM, Ryan Dary wrote:

I'm working on a drawing program and I wanted to have those guides like in so many apps.... does anyone have an algorithm for the guides

what behaviour do you want the algorithm for - the magnetic effect?

If so, the following should help.

Basically, I have a multi-layered drawing program - all the shapes in one particular layer are guidelines. Whilst currently I have lines that are just horizontal and vertical, later a subclass of ADGuidelineShape could implement different snapping.

The key thing is abstracting who does the snapping - the dragging code just asks the entire layer to snapX and snapY, adjusting the position if it does so.

Inside the layer, a linear search of guideline shapes does the snapping but that could change independent of the dragging code.

Note also that the snapping code is just adjusting a coordinate - it could be snapping an edge being dragged, something being moved or anything - the snapping code has no knowledge of the effect of it adjusting that coordinate.

Thus we have abstraction looking down (how snapping works) and information hiding looking back up (the significance of snapping).


my dragging code looks like (note I also have snapping to grids and both features are on or off independently, with guidelines overriding)

  dim snappedToGuideline as boolean
  if mSnapToGuidelines then
    snappedToGuideline = fw.mGuidelines.SnapX(clickX)
snappedToGuideline = fw.mGuidelines.SnapY(clickY) or snappedToGuideline ' note this order allows for both X and Y to be adjusted, snapping to a corner
  end if
  if not snappedToGuideline and mSnapToGrid then
MouseUtilities.SnapXY fw.mGridCoords(), fw.GridSize(), clickX, clickY
  end if


======= guidelines collection
Function SnapX(byref ioScreenPts as integer) As boolean
' unlike snapping to grid, may not actually snap if no guidline in range

  dim actualPts as double
' scale the screen coords and allow an absolute number points sloppiness
  actualPts = scnStatics.screen2Points(ioScreenPts)

  dim aGuideline as ADBaseShape
  for each aGuideline in mObjectList
    assert aGuideline isa ADGuidelineShape
    if ADGuidelineShape(aGuideline).SnapX(actualPts) then
      ioScreenPts = scnStatics.points2Screen(actualPts)
      return true
    end if
  next
return false
End Function


================= ADGuidelineShape
Function SnapX(byref ioPts as double) As boolean
  if mHorizontal then return false

  dim myPts as double = mXPos.points()
  dim dx as double = abs(ioPts - myPts)
if dx <= kSnapPtsThreshold then ************* key point, comparing to constant threshold, this could become a user preference
    ioPts = myPts
    return true
  end if
  return false
End Function
_______________________________________________
Unsubscribe or switch delivery mode:
<http://www.realsoftware.com/support/listmanager/>

Search the archives of this list here:
<http://support.realsoftware.com/listarchives/lists.html>

Reply via email to