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;
|
||||
TargetType? _targetType;
|
||||
|
||||
// AJOUT PROTECTION DU PLOTTING : Stockage permanent de la rotation du Crop
|
||||
double _cropRotation = 0.0;
|
||||
|
||||
// Target detection results
|
||||
double _targetCenterX = 0.5;
|
||||
double _targetCenterY = 0.5;
|
||||
@@ -82,6 +85,7 @@ class AnalysisProvider extends ChangeNotifier {
|
||||
String? get errorMessage => _errorMessage;
|
||||
String? get imagePath => _imagePath;
|
||||
TargetType? get targetType => _targetType;
|
||||
double get cropRotation => _cropRotation; // Getter pour le Plotting
|
||||
double get targetCenterX => _targetCenterX;
|
||||
double get targetCenterY => _targetCenterY;
|
||||
double get targetRadius => _targetRadius;
|
||||
@@ -112,6 +116,12 @@ class AnalysisProvider extends ChangeNotifier {
|
||||
? _correctedImagePath
|
||||
: _imagePath;
|
||||
|
||||
/// Modifie et mémorise la rotation de l'image pour le Plotting
|
||||
void setCropRotation(double rotation) {
|
||||
_cropRotation = rotation;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Analyze an image
|
||||
///
|
||||
/// [autoAnalyze] determines if we should run automatic detection immediately.
|
||||
@@ -778,6 +788,7 @@ class AnalysisProvider extends ChangeNotifier {
|
||||
_errorMessage = null;
|
||||
_imagePath = null;
|
||||
_targetType = null;
|
||||
_cropRotation = 0.0; // Reset de la rotation
|
||||
_targetCenterX = 0.5;
|
||||
_targetCenterY = 0.5;
|
||||
_targetRadius = 0.4;
|
||||
|
||||
@@ -23,11 +23,8 @@ import '../crop/crop_screen.dart';
|
||||
import '../capture/capture_screen.dart';
|
||||
import 'widgets/target_overlay.dart';
|
||||
import 'widgets/target_calibration.dart';
|
||||
import 'widgets/target_overlay.dart';
|
||||
import 'widgets/score_card.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 {
|
||||
final String imagePath;
|
||||
@@ -57,12 +54,20 @@ class AnalysisScreen extends StatelessWidget {
|
||||
: null;
|
||||
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => AnalysisProvider(
|
||||
detectionService: context.read<TargetDetectionService>(),
|
||||
scoreCalculatorService: context.read<ScoreCalculatorService>(),
|
||||
groupingAnalyzerService: context.read<GroupingAnalyzerService>(),
|
||||
sessionRepository: context.read<SessionRepository>(),
|
||||
)..analyzeImage(imagePath, targetType, autoAnalyze: false, manualCenter: manualCenterOffset),
|
||||
create: (context) {
|
||||
final p = AnalysisProvider(
|
||||
detectionService: context.read<TargetDetectionService>(),
|
||||
scoreCalculatorService: context.read<ScoreCalculatorService>(),
|
||||
groupingAnalyzerService: context.read<GroupingAnalyzerService>(),
|
||||
sessionRepository: context.read<SessionRepository>(),
|
||||
);
|
||||
// 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(
|
||||
cropScale: cropScale,
|
||||
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: provider.imageAspectRatio,
|
||||
child: _isCalibrating
|
||||
@@ -217,19 +222,15 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
||||
ClipRect(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final double rotationAngle = widget.cropRotation ?? 0.0;
|
||||
|
||||
return Transform(
|
||||
transform: Matrix4.identity()
|
||||
..translate(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0)
|
||||
..scale(1.0, 1.0), // Zoom ignoré au plotting pour rester en vue globale
|
||||
..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
|
||||
..rotateZ((provider.cropRotation) * (math.pi / 180)), // FIX : Utilisation du provider dynamique
|
||||
alignment: Alignment.center,
|
||||
child: Transform.rotate(
|
||||
angle: rotationAngle * (math.pi / 180),
|
||||
child: Image.file(
|
||||
File(provider.imagePath!),
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
child: Image.file(
|
||||
File(provider.imagePath!),
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -486,10 +487,18 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Image.file(
|
||||
File(provider.imagePath!),
|
||||
key: _imageKey,
|
||||
fit: BoxFit.fill,
|
||||
// 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!),
|
||||
key: _imageKey,
|
||||
fit: BoxFit.contain, // Remplace BoxFit.fill pour s'aligner sur la Calibration
|
||||
),
|
||||
),
|
||||
TargetOverlay(
|
||||
targetCenterX: provider.targetCenterX,
|
||||
@@ -568,6 +577,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showSaveSessionDialog(BuildContext context, AnalysisProvider provider) {
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -645,7 +655,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
||||
weaponName: sessionProvider.currentWeapon,
|
||||
weaponId: sessionProvider.currentWeaponId,
|
||||
distance: sessionProvider.distance,
|
||||
date: sessionProvider.sessionDate, // <-- CORRECTION : Prise en compte de la date ici aussi !
|
||||
date: sessionProvider.sessionDate,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
@@ -667,4 +677,4 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user