54 lines
1.9 KiB
Dart
54 lines
1.9 KiB
Dart
import 'dart:math' as math;
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// Class utility untuk transformasi koordinat 3D World (meter) ke 2D Screen (piksel)
|
|
/// dengan proyeksi Isometrik.
|
|
class IsometricTransform {
|
|
/// Skala piksel per meter (misalnya 1 meter = 40 piksel)
|
|
final double scale;
|
|
|
|
/// Titik origin (0,0,0) di layar
|
|
final Offset origin;
|
|
|
|
const IsometricTransform({
|
|
required this.scale,
|
|
required this.origin,
|
|
});
|
|
|
|
/// Mengonversi koordinat 3D World (x, y, z) dalam satuan meter ke Offset 2D Canvas (piksel).
|
|
/// * [x] : Arah kedalaman kumbung (dari depan ke belakang) - e.g. 0 s.d 8 meter.
|
|
/// * [y] : Arah lebar kumbung (dari kiri ke kanan) - e.g. 0 s.d 6 meter.
|
|
/// * [z] : Arah tinggi kumbung (dari lantai ke atap) - e.g. 0 s.d 3 meter.
|
|
Offset toScreen(double x, double y, double z) {
|
|
const double angle = 30.0 * math.pi / 180.0; // Sudut proyeksi isometrik 30 derajat
|
|
|
|
// dx = (x - y) * cos(30) * scale
|
|
// dy = ((x + y) * sin(30) - z) * scale
|
|
final double dx = (x - y) * math.cos(angle) * scale;
|
|
final double dy = ((x + y) * math.sin(angle) - z) * scale;
|
|
|
|
return Offset(origin.dx + dx, origin.dy + dy);
|
|
}
|
|
|
|
/// Mengonversi koordinat 2D Screen (tap) kembali ke koordinat 2D World Ground (x, y) pada z = 0.
|
|
/// Berguna untuk mendeteksi penempatan/interaksi ketukan jari di lantai kumbung.
|
|
Offset toWorldGround(Offset screenPt) {
|
|
const double angle = 30.0 * math.pi / 180.0;
|
|
final double cos30 = math.cos(angle);
|
|
final double sin30 = math.sin(angle);
|
|
|
|
final double rx = screenPt.dx - origin.dx;
|
|
final double ry = screenPt.dy - origin.dy;
|
|
|
|
// x - y = rx / (cos(30) * scale)
|
|
// x + y = ry / (sin(30) * scale)
|
|
final double diffVal = rx / (cos30 * scale);
|
|
final double sumVal = ry / (sin30 * scale);
|
|
|
|
final double x = (sumVal + diffVal) / 2;
|
|
final double y = (sumVal - diffVal) / 2;
|
|
|
|
return Offset(x, y);
|
|
}
|
|
}
|