fix(analysis): appliquer la rotation du crop sur l'image en modes calibration et plotting
This commit is contained in:
@@ -50,6 +50,9 @@ class AnalysisProvider extends ChangeNotifier {
|
|||||||
String? _imagePath;
|
String? _imagePath;
|
||||||
TargetType? _targetType;
|
TargetType? _targetType;
|
||||||
|
|
||||||
|
// AJOUT PROTECTION DU PLOTTING : Stockage permanent de la rotation du Crop
|
||||||
|
double _cropRotation = 0.0;
|
||||||
|
|
||||||
// Target detection results
|
// Target detection results
|
||||||
double _targetCenterX = 0.5;
|
double _targetCenterX = 0.5;
|
||||||
double _targetCenterY = 0.5;
|
double _targetCenterY = 0.5;
|
||||||
@@ -82,6 +85,7 @@ class AnalysisProvider extends ChangeNotifier {
|
|||||||
String? get errorMessage => _errorMessage;
|
String? get errorMessage => _errorMessage;
|
||||||
String? get imagePath => _imagePath;
|
String? get imagePath => _imagePath;
|
||||||
TargetType? get targetType => _targetType;
|
TargetType? get targetType => _targetType;
|
||||||
|
double get cropRotation => _cropRotation; // Getter pour le Plotting
|
||||||
double get targetCenterX => _targetCenterX;
|
double get targetCenterX => _targetCenterX;
|
||||||
double get targetCenterY => _targetCenterY;
|
double get targetCenterY => _targetCenterY;
|
||||||
double get targetRadius => _targetRadius;
|
double get targetRadius => _targetRadius;
|
||||||
@@ -112,6 +116,12 @@ class AnalysisProvider extends ChangeNotifier {
|
|||||||
? _correctedImagePath
|
? _correctedImagePath
|
||||||
: _imagePath;
|
: _imagePath;
|
||||||
|
|
||||||
|
/// Modifie et mémorise la rotation de l'image pour le Plotting
|
||||||
|
void setCropRotation(double rotation) {
|
||||||
|
_cropRotation = rotation;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
/// Analyze an image
|
/// Analyze an image
|
||||||
///
|
///
|
||||||
/// [autoAnalyze] determines if we should run automatic detection immediately.
|
/// [autoAnalyze] determines if we should run automatic detection immediately.
|
||||||
@@ -778,6 +788,7 @@ class AnalysisProvider extends ChangeNotifier {
|
|||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
_imagePath = null;
|
_imagePath = null;
|
||||||
_targetType = null;
|
_targetType = null;
|
||||||
|
_cropRotation = 0.0; // Reset de la rotation
|
||||||
_targetCenterX = 0.5;
|
_targetCenterX = 0.5;
|
||||||
_targetCenterY = 0.5;
|
_targetCenterY = 0.5;
|
||||||
_targetRadius = 0.4;
|
_targetRadius = 0.4;
|
||||||
|
|||||||
@@ -23,11 +23,8 @@ import '../crop/crop_screen.dart';
|
|||||||
import '../capture/capture_screen.dart';
|
import '../capture/capture_screen.dart';
|
||||||
import 'widgets/target_overlay.dart';
|
import 'widgets/target_overlay.dart';
|
||||||
import 'widgets/target_calibration.dart';
|
import 'widgets/target_calibration.dart';
|
||||||
import 'widgets/target_overlay.dart';
|
|
||||||
import 'widgets/score_card.dart';
|
import 'widgets/score_card.dart';
|
||||||
import 'widgets/grouping_stats.dart';
|
import 'widgets/grouping_stats.dart';
|
||||||
import '../capture/capture_screen.dart'; // Si ton écran principal s'appelle comme ça
|
|
||||||
import '../crop/crop_screen.dart';
|
|
||||||
|
|
||||||
class AnalysisScreen extends StatelessWidget {
|
class AnalysisScreen extends StatelessWidget {
|
||||||
final String imagePath;
|
final String imagePath;
|
||||||
@@ -57,12 +54,20 @@ class AnalysisScreen extends StatelessWidget {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return ChangeNotifierProvider(
|
return ChangeNotifierProvider(
|
||||||
create: (context) => AnalysisProvider(
|
create: (context) {
|
||||||
|
final p = AnalysisProvider(
|
||||||
detectionService: context.read<TargetDetectionService>(),
|
detectionService: context.read<TargetDetectionService>(),
|
||||||
scoreCalculatorService: context.read<ScoreCalculatorService>(),
|
scoreCalculatorService: context.read<ScoreCalculatorService>(),
|
||||||
groupingAnalyzerService: context.read<GroupingAnalyzerService>(),
|
groupingAnalyzerService: context.read<GroupingAnalyzerService>(),
|
||||||
sessionRepository: context.read<SessionRepository>(),
|
sessionRepository: context.read<SessionRepository>(),
|
||||||
)..analyzeImage(imagePath, targetType, autoAnalyze: false, manualCenter: manualCenterOffset),
|
);
|
||||||
|
// Sauvegarde de l'angle de rotation d'origine directement dans l'état global
|
||||||
|
if (cropRotation != null) {
|
||||||
|
p.setCropRotation(cropRotation!);
|
||||||
|
}
|
||||||
|
p.analyzeImage(imagePath, targetType, autoAnalyze: false, manualCenter: manualCenterOffset);
|
||||||
|
return p;
|
||||||
|
},
|
||||||
child: _AnalysisScreenContent(
|
child: _AnalysisScreenContent(
|
||||||
cropScale: cropScale,
|
cropScale: cropScale,
|
||||||
cropOffset: cropOffset,
|
cropOffset: cropOffset,
|
||||||
@@ -207,7 +212,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// SECTION CORRIGÉE : Utilise maintenant widget.cropRotation sans aucune erreur !
|
// SECTION CORRIGÉE : Utilise maintenant la réactivité du provider globale
|
||||||
AspectRatio(
|
AspectRatio(
|
||||||
aspectRatio: provider.imageAspectRatio,
|
aspectRatio: provider.imageAspectRatio,
|
||||||
child: _isCalibrating
|
child: _isCalibrating
|
||||||
@@ -217,20 +222,16 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
ClipRect(
|
ClipRect(
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final double rotationAngle = widget.cropRotation ?? 0.0;
|
|
||||||
|
|
||||||
return Transform(
|
return Transform(
|
||||||
transform: Matrix4.identity()
|
transform: Matrix4.identity()
|
||||||
..translate(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0)
|
..setTranslationRaw(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0, 0.0)
|
||||||
..scale(1.0, 1.0), // Zoom ignoré au plotting pour rester en vue globale
|
..scale(1.0, 1.0) // Zoom ignoré au plotting pour rester en vue globale
|
||||||
|
..rotateZ((provider.cropRotation) * (math.pi / 180)), // FIX : Utilisation du provider dynamique
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Transform.rotate(
|
|
||||||
angle: rotationAngle * (math.pi / 180),
|
|
||||||
child: Image.file(
|
child: Image.file(
|
||||||
File(provider.imagePath!),
|
File(provider.imagePath!),
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -486,10 +487,18 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
},
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Image.file(
|
// FIX CRITIQUE PLOTTING : L'image de fond doit appliquer exactement le même angle de rotation qu'en calibration !
|
||||||
|
Transform(
|
||||||
|
transform: Matrix4.identity()
|
||||||
|
..setTranslationRaw(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0, 0.0)
|
||||||
|
..scale(1.0, 1.0)
|
||||||
|
..rotateZ((provider.cropRotation) * (math.pi / 180)),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Image.file(
|
||||||
File(provider.imagePath!),
|
File(provider.imagePath!),
|
||||||
key: _imageKey,
|
key: _imageKey,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.contain, // Remplace BoxFit.fill pour s'aligner sur la Calibration
|
||||||
|
),
|
||||||
),
|
),
|
||||||
TargetOverlay(
|
TargetOverlay(
|
||||||
targetCenterX: provider.targetCenterX,
|
targetCenterX: provider.targetCenterX,
|
||||||
@@ -568,6 +577,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showSaveSessionDialog(BuildContext context, AnalysisProvider provider) {
|
void _showSaveSessionDialog(BuildContext context, AnalysisProvider provider) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -645,7 +655,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
weaponName: sessionProvider.currentWeapon,
|
weaponName: sessionProvider.currentWeapon,
|
||||||
weaponId: sessionProvider.currentWeaponId,
|
weaponId: sessionProvider.currentWeaponId,
|
||||||
distance: sessionProvider.distance,
|
distance: sessionProvider.distance,
|
||||||
date: sessionProvider.sessionDate, // <-- CORRECTION : Prise en compte de la date ici aussi !
|
date: sessionProvider.sessionDate,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
|
|||||||
Reference in New Issue
Block a user