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>