310 lines
8.5 KiB
Dart
310 lines
8.5 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:surface_tension_calculator/models/stc_output.dart';
|
|
|
|
import '../res/assets.dart';
|
|
|
|
class HomeScreen extends StatefulWidget {
|
|
const HomeScreen({super.key});
|
|
|
|
@override
|
|
State<HomeScreen> createState() => _HomeScreenState();
|
|
}
|
|
|
|
class _HomeScreenState extends State<HomeScreen> {
|
|
PlatformFile? _imageFile;
|
|
STCOutput out = STCOutput.clearOutput();
|
|
static const String scriptPath = 'scripts/img_V01.exe';
|
|
|
|
Future<void> _pickImage() async {
|
|
try {
|
|
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
|
type: FileType.image,
|
|
);
|
|
if (result == null) return;
|
|
|
|
setState(() {
|
|
_imageFile = result.files.first;
|
|
});
|
|
} catch (e) {}
|
|
}
|
|
|
|
Future<void> _computeSTC() async {
|
|
final List<String> args = [
|
|
'-img',
|
|
_imageFile!.path ?? '',
|
|
'-out',
|
|
'water-drop',
|
|
'-proc',
|
|
'8',
|
|
];
|
|
|
|
await Process.run(scriptPath, args);
|
|
|
|
out = STCOutput(
|
|
negCoordFile: 'negCoordFile',
|
|
posCoordFile: 'posCoordFile',
|
|
syringeWidth: 0.123,
|
|
radiusCurvRange: 'asd',
|
|
shapeFactorRange: 'asd',
|
|
initXCoordRange: 'asd',
|
|
initAngleRange: 'asd',
|
|
paramCombinations: 123,
|
|
numProcessors: 123,
|
|
juza: 12.09,
|
|
bestOutput: [0.123, 12.213],
|
|
lowestRMSD: 0.123,
|
|
surfaceTension: 0.123,
|
|
bestRadiusOfCurvature: 0.123,
|
|
bestShapeFactor: 0.123,
|
|
bestInitialXCoordinate: 123.123,
|
|
bestInitialAngle: 234.123,
|
|
elapsedTime: 12.12345,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: SizedBox.expand(
|
|
child: Container(
|
|
padding: const EdgeInsets.only(top: 35.0, left: 25, right: 25),
|
|
color: Color(0xFF7B1113),
|
|
child: Column(
|
|
children: [
|
|
buildHeader(),
|
|
const SizedBox(height: 20),
|
|
Container(
|
|
padding: const EdgeInsets.all(25),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(30),
|
|
),
|
|
child: IntrinsicHeight(
|
|
child: Row(
|
|
children: [
|
|
buildLeftImage(),
|
|
const SizedBox(width: 20),
|
|
const VerticalDivider(width: 20),
|
|
const SizedBox(width: 20),
|
|
buildRightResults(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
buildFooter(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget buildFooter() {
|
|
return Center(
|
|
child: Text(
|
|
'\u00a9 2025 UP Intelligent Systems Center',
|
|
style: TextStyle(color: Colors.white),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget buildHeader() {
|
|
return IntrinsicHeight(
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(width: 20),
|
|
Image.asset(Assets.logo, height: 70),
|
|
const SizedBox(width: 10),
|
|
const VerticalDivider(),
|
|
const SizedBox(width: 10),
|
|
Text(
|
|
'SURFACE TENSION CALCULATOR',
|
|
style: TextStyle(
|
|
fontSize: 45,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Column buildLeftImage() {
|
|
return Column(
|
|
children: [
|
|
if (_imageFile == null)
|
|
Container(
|
|
height: 400,
|
|
width: 500,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade500,
|
|
borderRadius: BorderRadius.circular(30),
|
|
),
|
|
child: Center(child: Text('No image uploaded')),
|
|
),
|
|
if (_imageFile != null)
|
|
Container(
|
|
height: 400,
|
|
width: 500,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade500,
|
|
borderRadius: BorderRadius.circular(30),
|
|
),
|
|
child: Image.memory(Uint8List.fromList(_imageFile!.bytes!)),
|
|
),
|
|
const SizedBox(height: 15),
|
|
Row(
|
|
children: [
|
|
ElevatedButton(
|
|
onPressed: _pickImage,
|
|
child: Text('Upload Droplet Image'),
|
|
),
|
|
const SizedBox(width: 10),
|
|
ElevatedButton(
|
|
onPressed: _imageFile == null ? null : _computeSTC,
|
|
child: Text('Compute Surface Tension'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildRightResults() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Results:',
|
|
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w600),
|
|
),
|
|
const SizedBox(height: 10),
|
|
SingleChildScrollView(child: buildResults()),
|
|
// Text(out),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildResults() {
|
|
return Row(
|
|
children: [
|
|
buildOutputFields(),
|
|
const SizedBox(width: 10),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(out.posCoordFile),
|
|
Text(out.posCoordFile),
|
|
Text(out.syringeWidth.toString()),
|
|
Text(out.radiusCurvRange),
|
|
Text(out.shapeFactorRange),
|
|
Text(out.initXCoordRange),
|
|
Text(out.initAngleRange),
|
|
Text(out.paramCombinations.toString()),
|
|
Text(out.numProcessors.toString()),
|
|
Text(out.juza.toString()),
|
|
Text(''),
|
|
Text(''),
|
|
Text(out.bestOutput.toString()),
|
|
Text(''),
|
|
Text(out.lowestRMSD.toString()),
|
|
Text(out.surfaceTension.toString()),
|
|
Text(out.bestRadiusOfCurvature.toString()),
|
|
Text(out.bestShapeFactor.toString()),
|
|
Text(out.bestInitialXCoordinate.toString()),
|
|
Text(out.bestInitialAngle.toString()),
|
|
Text(out.elapsedTime.toString()),
|
|
],
|
|
),
|
|
],
|
|
); //Text(Strings.sampleOut);
|
|
}
|
|
|
|
Column buildOutputFields() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Negative Coordinate File: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Positive Coordinate File: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Syringe Width (millimeter): ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Radius of Curvature: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Shape Factor Range: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Initial X Coordinate: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Initial Angle Range: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Parameter Combinations: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Number of Process: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Juza 5-Plane (1/H) Std.Dev: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(''),
|
|
Text(
|
|
'minimization success',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text('best output: ', style: TextStyle(fontWeight: FontWeight.w600)),
|
|
Text('', style: TextStyle(fontWeight: FontWeight.w600)),
|
|
Text('Lowest RMSD: ', style: TextStyle(fontWeight: FontWeight.w600)),
|
|
Text(
|
|
'Computed Surface Tension: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Best Radius of Curvature: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Best Shape Factor: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Best Initial X Coordinate: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Best Initial Angle: ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
Text(
|
|
'Lapsed Time (seconds): ',
|
|
style: TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|