help: SketchMorph scaling

Bob Arning arning at charm.net
Tue Jan 25 21:27:23 UTC 2000


On Tue, 25 Jan 2000 13:42:03 -0500 "Stephan B. Wessels" <stephan.wessels at sdrc.com> wrote:
>Open up a new Morphic Project and then in a workspace execute the following...
>
>Display border: (10 at 10 extent: 1024 at 768) width: 2.
>form _ ScriptingSystem formAtKey: 'TinyMenu'.
>morph _ SketchMorph new form: form.
>morph extent: 1024 at 20.
>morph align: morph topLeft with: 10 at 40.
>morph openInWorld.
>
>So, why isn't the scaled sketch morph reaching the vertical line at 1024?
>
>I dont' get it.

Hi Steve,

Your example is an unfortunate collision between very large scale factors and a approximation in WarpBlt class>>rotate:degrees:center:scaleBy:smoothing:. I have included an incomplete revision of that method that does fix (mostly) your problem.

The problem is that WarpBlt computes the quad from which to copy by rotating and scaling the srcRect corners, then taking the inner corners of the resulting rectangle and rotating and scaling those back to the source coordinate system. If the scale factor is 1, then this isn't too bad, but, in your case, the scale was over 100 in the x direction and the inner corners thus computed extended too far to the right and bottom. I'm still a bit perplesed by this, but the code below makes your example come out a lot more as you would expect.

Cheers,
Bob


==============
'From Squeak2.7 of 5 January 2000 [latest update: #1789] on 25 January 2000 at 4:14:04 pm'!

!WarpBlt class methodsFor: 'form rotation' stamp: 'RAA 1/25/2000 16:14'!
rotate: srcForm degrees: angleInDegrees center: aPoint scaleBy: scalePoint smoothing: cellSize
	"Rotate the given Form the given number of degrees about the given center and scale its width and height by x and y of the given scale point. Smooth using the given cell size, an integer between 1 and 3, where 1 means no smoothing. Return a pair where the first element is the rotated Form and the second is the position offset required to align the center of the rotated Form with that of the original. Note that the dimensions of the resulting Form generally differ from those of the original."

	| srcRect center radians dstOrigin dstCorner p dstRect inverseScale quad dstForm newCenter warpSrc |
	srcRect _ srcForm boundingBox.
	center _ srcRect center.
	radians _ angleInDegrees degreesToRadians.
	dstOrigin _ dstCorner _ center.
	srcRect corners do: [:corner |
		"find the limits of a rectangle that just encloses the rotated
		 original; in general, this rectangle will be larger than the
		 original (e.g., consider a square rotated by 45 degrees)"
		p _ ((corner - center) scaleBy: scalePoint) + center.
		p _ (p rotateBy: radians about: center) rounded.
		dstOrigin _ dstOrigin min: p.
		dstCorner _ dstCorner max: p].

	"rotate the enclosing rectangle back to get the source quadrilateral"
	dstRect _ dstOrigin corner: dstCorner.
	inverseScale _ (1.0 / scalePoint x)@(1.0 / scalePoint y).

	quad _ angleInDegrees = 0.0 ifTrue: [	"partial hack for large scale factors"
		srcRect innerCorners
	] ifFalse: [
		dstRect innerCorners collect: [:corner |
			p _ corner rotateBy: radians negated about: center.
			((p - center) scaleBy: inverseScale) + center].
	].


	"make a Form to hold the result and do the rotation"
	warpSrc _ srcForm.
	(srcForm isKindOf: ColorForm)
		ifTrue: [
			cellSize > 1
				ifTrue: [
					warpSrc _ Form extent: srcForm extent depth: 16.
					srcForm displayOn: warpSrc.
					dstForm _ Form extent: dstRect extent depth: 16]  "use 16-bit depth to allow smoothing"
				ifFalse: [
					dstForm _ srcForm class extent: dstRect extent depth: srcForm depth]]
		ifFalse: [
			dstForm _ srcForm class extent: dstRect extent depth: srcForm depth].

	(WarpBlt toForm: dstForm)
		sourceForm: warpSrc;
		colorMap: (dstForm colormapIfNeededForDepth: warpSrc depth);
		cellSize: cellSize;  "installs a new colormap if cellSize > 1"
		combinationRule: Form paint;
		copyQuad: quad toRect: dstForm boundingBox.

	(dstForm isKindOf: ColorForm) ifTrue: [dstForm colors: srcForm colors copy].
	newCenter _ (center rotateBy: radians about: aPoint) truncated.
	^ Array with: dstForm with: dstRect origin + (newCenter - center)
! !






More information about the Squeak-dev mailing list