Bug 15446 - CGAffine Transform Scale, get scale of Presentation Layer float sign error
Summary: CGAffine Transform Scale, get scale of Presentation Layer float sign error
Status: RESOLVED NOT_REPRODUCIBLE
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: 6.4.4
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-10-16 17:30 UTC by Jon Goldberger [MSFT]
Modified: 2013-10-17 09:54 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test Projects (3.39 MB, application/zip)
2013-10-16 17:30 UTC, Jon Goldberger [MSFT]
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED NOT_REPRODUCIBLE

Description Jon Goldberger [MSFT] 2013-10-16 17:30:44 UTC
Created attachment 5156 [details]
Test Projects

I found a strange behavior. Let's say I scale a UIView using CGAffineTransform' Scale. Then say I want to calculate that scale I do so by reading the UIView's Presentation Layer's like so:

layer.PresentationLayer.ValueForKeyPath(NSString.FromData("transform.rotation.z", NSStringEncoding.UTF8))

Using the function I have in the example, it works… sometimes. It doesn't work correctly when one of the scales is negative. Can you please look over this simple example and it's workaround and advise me on what I'm doing wrong or where to look for a solution?

Here's the link to both projects: https://www.dropbox.com/s/zr9u33s6hpp72x2/Two%20Projects%2C%20one%20is%20bugged%20the%20other%20is%20a%20workaround.zip
===============================================================

=== Xamarin Studio ===

Version 4.0.13 (build 38)
Installation UUID: 2dc9022f-f9a8-424f-8284-bf224cbbfde0
Runtime:
	Mono 3.2.3 ((no/8d3b4b7)
	GTK+ 2.24.20 theme: Raleigh
	GTK# (2.12.0.0)
	Package version: 302030000

=== Apple Developer Tools ===

Xcode 5.0 (3332.22)
Build 5A1412

=== Xamarin.iOS ===

Version: 7.0.2.7 (Business Edition)
Hash: 57edee2
Branch: 
Build date: 2013-04-10 18:05:51-0400

=== Xamarin.Mac ===

Xamarin.Mac: 1.6.19

=== Xamarin.Android ===

Version: 4.8.3 (Business Edition)
Android SDK: /Users/apple/Library/Developer/Xamarin/android-sdk-mac_x86
	Supported Android versions:
		2.1   (API level 7)
		2.2   (API level 8)
		2.3   (API level 10)
		3.1   (API level 12)
		3.2   (API level 13)
		4.0   (API level 14)
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.2   (API level 17)
		4.3   (API level 18)
Java SDK: /usr
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-11M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)

=== Build Information ===

Release ID: 400130038
Git revision: 07afec667f7be5d0ee511eb7115bbac6377fbae8
Build date: 2013-09-24 08:53:29+0000
Xamarin addins: 61140345a5b109633a94409edcbc7a4c19a425c6

=== Operating System ===

Mac OS X 10.8.5
Darwin MacBook-Pro.local 12.5.0 Darwin Kernel Version 12.5.0
    Sun Sep 29 13:33:47 PDT 2013
    root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64
Comment 2 Jon Goldberger [MSFT] 2013-10-16 17:32:43 UTC
Found this related bug, tried using the code given by Rolf, but returned results still displayed wrong signs if either x or y is negative..
https://bugzilla.xamarin.com/show_bug.cgi?id=7832
Comment 3 Rolf Bjarne Kvinge [MSFT] 2013-10-17 04:42:45 UTC
The values you get are correct, they're just incomplete. The underlying problem is that once matrix multiplication takes place, it's impossible to get back the original values used to do the matrix multiplication, which means that you need to take all possible combinations of rotation and scaling into account when looking at the post-multiplied matrix.

I printed out the different values:

	Scale (1, 1);
		transform:  IsIdentity: True IsAffine: True
			[1 0 0 0]
			[ 0 1 0 0]
			[ 0 0 1 0]
			[ 0 0 0 1]
		transform.rotation.x: 0
		transform.rotation.y: -0
		transform.rotation.z: 0
		transform.scale.x: 1
		transform.scale.y: 1
		transform.scale.z: 1

This is a clear identity matrix, nothing special here.

	Scale (1, -1);
		transform:
			[1 0 0 0]
			[ 0 -1 0 0]
			[ 0 0 1 0]
			[ 0 0 0 1]
		transform.rotation.x: -3.141592653589793
		transform.rotation.y: 0
		transform.rotation.z: -3.141592653589793
		transform.scale.x: -1
		transform.scale.y: -1
		transform.scale.z: -1

A rotation of +-pi is the same as a scale of +-1, so here rotation.x cancels out scale.x and rotation.z cancels out scale.z, leaving just scale.y = -1, which is the initial input.


	Scale (-1, 1);
		transform:
			[-1 0 0 0]
			[ 0 1 0 0]
			[ 0 0 1 0]
			[ 0 0 0 1]
		transform.rotation.x: -3.141592653589793
		transform.rotation.y: 0
		transform.rotation.z: -0
		transform.scale.x: -1
		transform.scale.y: -1
		transform.scale.z: -1

Here rotation.x cancels out scale.x, so you're left with two flips, one in the y axis and one in the z axis - which when combined is the same as a flip in the x axis, i.e. the original input.

	Scale (-1, -1):
		transform:
			[-1 0 0 0]
			[ 0 -1 0 0]
			[ 0 0 1 0]
			[ 0 0 0 1]
		transform.rotation.x: 0
		transform.rotation.y: -0
		transform.rotation.z: 3.141592653589793
		transform.scale.x: 1
		transform.scale.y: 1
		transform.scale.z: 1

A pi rotation along the z axis is the same as a flip along the x axis and the y axis.
Comment 4 Joey Z 2013-10-17 09:54:44 UTC
Thanks for providing the explanation so quickly.  This makes sense now that you've laid it out.  I'll use my work around to achieve my desired result.  Rather than scaling the X and Y in the same view, I separate them into a ScaleXView and ScaleYView.

So let's say I had an ImageView.  Now I have an ImageView that's sitting on top of a ScaleYView which is sitting on top of a ScaleXView.  I'll just code my project to get the ScaleX value from the ScaleXView's Presentation Layer, and get the ScaleY value from the ScaleYView's Presentation Layer.