Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coordinates by reverse use of matrix to get original value #16

Open
meDerekD17 opened this issue Apr 21, 2020 · 11 comments
Open

coordinates by reverse use of matrix to get original value #16

meDerekD17 opened this issue Apr 21, 2020 · 11 comments

Comments

@meDerekD17
Copy link

After scaling and translating, i tap on the screen. I use the values from MatrixDecompose (translation , scale) to go back to the 'real world without translation and scale' coordinates. They value are always off in Y by the same amount. I am fairly sure it is caused by the AppBar distance. When I remove the AppBar values work.
My problem is I I am not completely sure what is happening, so I might get it wrong on different devices. Also, I would prefer to be able to use the Appbar. I can not find a solution of finding AppBar height. Any Suggestions? What have others done with this problem?

@meDerekD17
Copy link
Author

But I notice if I do not enlarge the object on the screen (scale = 1.0) there is no problem. This makes me think I do not understand everything. I use
decomposeToValues(matrix) to get translation and scale.
I use details.globalPosition to get an Offset (localOffset)
then to get the real world coordinates I use:
Offset baseOffset = (localOffset - matrixValue.translation) / matrixValue.scale;

@Venusdjinni
Copy link

Hello, please did you manage to find a solution for this? I am facing the exact same issue

@meDerekD17
Copy link
Author

meDerekD17 commented Dec 19, 2022 via email

@meDerekD17
Copy link
Author

I think the comments above are what I did. I do not do any rotation, but I do allow translation and scale, and it works. I think what I was concerned about is that I did not quite understand everything, and so something might not work with a different device. But it has worked OK. Maybe if you can say what you have written and what problems you have?

@Venusdjinni
Copy link

Venusdjinni commented Dec 19, 2022

I am building an image editor, and what I want is to convert the transformation of a widget into 'real scale' values. I managed to do it accurately when there is no scale or rotation, but whenever I enable one of them, MatrixGestureDetector.decompose gives me a bad translation offset

@meDerekD17
Copy link
Author

I did not do rotation, but I did get scale and offset (Translate/move of origin) to work. Sometimes knowing that something works does allow solving. It is getting a bit late here.

@meDerekD17
Copy link
Author

In my gesture detector I have:

//GestureDetector activates 3 'handle' methods below to account for screen
//scale and translation (not rotation)
void _handleScaleStart(ScaleStartDetails details) {
//print('scaleStart details: ${details}');
//from MatrixGestureDetector - onScaleStart()to
//seems to be when user does initial touch to drag the screen
//focal point is where screen touched. Initializes drag/scale for Board screen
// widget.scaleTranslateMatrices.translationUpdater.value = details.focalPoint;
// widget.scaleTranslateMatrices.scaleUpdater.value = 1.0;
//now using singleton class
scaleTranslateMatrices.translationUpdater.value = details.focalPoint;
scaleTranslateMatrices.scaleUpdater.value = 1.0;
setState(() {});
}

void _handleScaleUpdate(ScaleUpdateDetails details) {
//uses singleton class
if(referencedData.bOneOfBeginnerHelpsAreShowing) return;
scaleTranslateMatrices.translationDeltaMatrix = Matrix4.identity();
scaleTranslateMatrices.scaleDeltaMatrix = Matrix4.identity();

Offset translationDelta = scaleTranslateMatrices.translationUpdater
    .update(details.focalPoint);

//attempt draw 'real' top Left - works for translates & practical zooms
referencedData.osUntransformedTopLeft -=
    translationDelta; //works for translate

scaleTranslateMatrices.translationDeltaMatrix =
    scaleTranslateMatrices.translate(translationDelta);
scaleTranslateMatrices.matrix =
    scaleTranslateMatrices.translationDeltaMatrix *
        scaleTranslateMatrices.matrix; //problem

Offset focalPoint;
RenderBox renderBox = context.findRenderObject();
focalPoint = renderBox.globalToLocal(details.focalPoint);

if (details.scale != 1.0) {
  double scaleDelta =
  scaleTranslateMatrices.scaleUpdater.update(details.scale);

  scaleTranslateMatrices.scaleDeltaMatrix =
      scaleTranslateMatrices.scale(scaleDelta, focalPoint);
  scaleTranslateMatrices.matrix =
      scaleTranslateMatrices.scaleDeltaMatrix *
          scaleTranslateMatrices.matrix;
}
scaleTranslateMatrices.notifier.value =
    scaleTranslateMatrices.matrix;
setState(() {});

}

void _handleScaleReset() {
//double tap causes Game screen to reset to default scale and position
scaleTranslateMatrices
.resetMatrices(); //reset Matrix4s back to initial values
referencedData.osUntransformedTopLeft = Offset(0.0, 0.0);
setState(() {});
}

@OverRide
Widget build(BuildContext context) {
return GestureDetector(
.......
I think any functions called are in the original library. I could have another look tomorrow if you have further questions

@Venusdjinni
Copy link

Thank you. I will have a look at it tomorrow, it's pretty late here too

@Venusdjinni
Copy link

Okay I see that you managed the scale using the focal point. Can you share the implementation of scaleTranslateMatrices's class?

@meDerekD17
Copy link
Author

meDerekD17 commented Dec 19, 2022 via email

@meDerekD17
Copy link
Author

I have to go to do something with snow. But I have a file named: matrices_classes.dart. It may be that the original has changed since a couple of years ago. I can see a lot of the functions match, but not all:
//Classes used in matrix manipulation for scale and translation(offsets)
//uses features and code of MatrixGestureDetector - But no rotation
//from
//https://github.com/pskink/matrix_gesture_detector/blob/master/lib/matrix_gesture_detector.dart

import 'package:flutter/material.dart';

//based on Matrix Gesture Detector
// From: https://github.com/pskink/matrix_gesture_detector

class MatrixDecomposedValues {
/// Translation, in most cases useful only for matrices that are nothing but
/// a translation (no scale and no rotation).
final Offset translation;

/// Scaling factor.
final double scale;

//2022Aug1 - removed rotation, was not used anyway
/// Rotation in radians, (-pi..pi) range.
//final double rotation; //But we don't include rotation

MatrixDecomposedValues(this.translation, this.scale);
//, this.rotation);

@OverRide
String toString() {
return 'MatrixDecomposedValues(translation: $translation, ' +
'scale: ${scale.toStringAsFixed(3)}';
// ', rotation: ${rotation.toStringAsFixed(3)})';
}
} //class MatrixDecomposedValues {

//From MatrixGestureDetector
//appears to set up a class to hold a value, and return (probably) difference
//between old value and new value.
//Difference needed as applying to Matrices, and want changes - maybe??
typedef _OnUpdate = T Function(T oldValue, T newValue);

class _ValueUpdater {
final _OnUpdate onUpdate;
T value;

_ValueUpdater({this.onUpdate});

T update(T newValue) {
T updated = onUpdate(value, newValue);
value = newValue;
return updated;
}
}

class ScaleTranslateMatrices {
//appears to be a Singleton class, with, sort of, passed parameters
//that are initialized in constructor
ScaleTranslateMatrices._privateConstructor(){
//
translationDeltaMatrix = Matrix4.identity();
scaleDeltaMatrix = Matrix4.identity();
matrix = Matrix4.identity();
notifier = ValueNotifier(matrix);
}

static final ScaleTranslateMatrices instance = ScaleTranslateMatrices
._privateConstructor();

Matrix4 matrix;
ValueNotifier notifier;
Matrix4 translationDeltaMatrix;
Matrix4 scaleDeltaMatrix;

void resetMatrices() {
//go back to default view
translationDeltaMatrix = Matrix4.identity();
scaleDeltaMatrix = Matrix4.identity();
matrix = Matrix4.identity();
notifier = ValueNotifier(matrix); //is needed
}

// Decomposes [matrix] into [MatrixDecomposedValues.translation],
// [MatrixDecomposedValues.scale] and [MatrixDecomposedValues.rotation]
// components.
static MatrixDecomposedValues decomposeToValues(Matrix4 matrix) {
var array = matrix.applyToVector3Array([0, 0, 0, 1, 0, 0]);
Offset translation = Offset(array[0], array[1]);
Offset delta = Offset(array[3] - array[0], array[4] - array[1]);
double scale = delta.distance;
double rotation = delta.direction;
return MatrixDecomposedValues(translation, scale);
//, rotation);
}

//Matrix creation from GestureDetector - composed from translation and scale
// Compose the matrix from translation, scale.
// pass a null to skip any matrix from composition.
// If [matrix] is not null the result of the composing will be concatenated
// to that [matrix], otherwise the identity matrix will be used.
static Matrix4 compose(
Matrix4 matrix, Matrix4 translationMatrix, Matrix4 scaleMatrix) {
if (matrix == null) matrix = Matrix4.identity();
if (translationMatrix != null) matrix = translationMatrix * matrix;
if (scaleMatrix != null) matrix = scaleMatrix * matrix;
return matrix;
}

//hold values and differences in values
_ValueUpdater translationUpdater = _ValueUpdater(
onUpdate: (oldVal, newVal) => newVal - oldVal,
);

_ValueUpdater scaleUpdater = _ValueUpdater(
onUpdate: (oldVal, newVal) => newVal / oldVal,
);

Matrix4 translate(Offset translation) { //was _translate
//create the translation matrix from dx,dy translation
var dx = translation.dx;
var dy = translation.dy;
// ..[0] = 1 # x scale
// ..[5] = 1 # y scale
// ..[10] = 1 # diagonal "one"
// ..[12] = dx # x translation
// ..[13] = dy # y translation
// ..[15] = 1 # diagonal "one"
return Matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, dx, dy, 0, 1);
}

Matrix4 scale(double scale, Offset focalPoint) { //was_scale
//create scale matrix from scale, and focal point (to be clarified***)
var dx = (1 - scale) * focalPoint.dx;
var dy = (1 - scale) * focalPoint.dy;
// ..[0] = scale # x scale
// ..[5] = scale # y scale
// ..[10] = 1 # diagonal "one"
// ..[12] = dx # x translation
// ..[13] = dy # y translation
// ..[15] = 1 # diagonal "one"
return Matrix4(scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, 1, 0, dx, dy, 0, 1);
}
} //Singleton class ScaleTranslateMatrices

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants