IgnoreExtensions-nef

Config-LoadPhotoPrismLocations
TestMethodIntersect
This commit is contained in:
Mike Phares 2023-06-23 19:19:41 -07:00
parent 1d0506d74c
commit 6f22929136
34 changed files with 364 additions and 140 deletions

View File

@ -13,6 +13,9 @@ completedColumns:
## Todo
- [nef-support](tasks/nef-support.md)
- [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md)
- [import-face-region-metadata](tasks/import-face-region-metadata.md)

View File

@ -0,0 +1,17 @@
---
created: 2023-06-12T15:44:11.932Z
updated: 2023-06-12T15:45:59.891Z
assigned: ""
progress: 0
tags: []
---
# determine-if-location-container-collection-is-needed-in-get-faces
```c#
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(collection, results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
```
## Sub-tasks
- [ ] See code above

View File

@ -0,0 +1,13 @@
---
created: 2023-06-12T15:44:11.932Z
updated: 2023-06-12T15:45:59.891Z
assigned: ""
progress: 0
tags: []
---
# nef-support
## Sub-tasks
- [ ] asdf

View File

@ -0,0 +1,13 @@
---
created: 2023-06-12T15:44:11.932Z
updated: 2023-06-12T15:45:59.891Z
assigned: ""
progress: 0
tags: []
---
# use-eyes-to-find-orientation
## Sub-tasks
- [ ] asdf

View File

@ -18,6 +18,7 @@
"Greyscale",
"Hasher",
"jfif",
"JOSN",
"mmod",
"Nicéphore",
"Niépce",
@ -42,5 +43,8 @@
"**/.git": false
},
"coverage-gutters.coverageBaseDir": "./.vscode/ReportGenerator/Cobertura/*",
"extensions.ignoreRecommendations": true
"extensions.ignoreRecommendations": true,
"[markdown]": {
"editor.wordWrap": "off"
}
}

View File

@ -92,6 +92,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -72,6 +72,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -72,6 +72,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -74,6 +74,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -69,6 +69,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -23,7 +23,7 @@ public partial class E_Distance
private readonly double _RangeDistanceToleranceAverage;
private readonly List<string> _DuplicateMappedFaceFiles;
public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, float[] rangeDistanceTolerance, float[] rangeFaceConfidence, float[] rectangleIntersectMinimum)
public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, float[] rangeDistanceTolerance, float[] rangeFaceConfidence, float[] rectangleIntersectMinimums)
{
_Debug = new();
_Moved = new();
@ -36,7 +36,7 @@ public partial class E_Distance
_DistanceRenameToMatch = distanceRenameToMatch;
_FaceConfidencePercent = faceConfidencePercent;
_DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
_RectangleIntersectMinimum = rectangleIntersectMinimum.Max();
_RectangleIntersectMinimum = rectangleIntersectMinimums.Max();
_RangeDistanceToleranceAverage = rangeDistanceTolerance.Average();
}
@ -199,7 +199,7 @@ public partial class E_Distance
}
}
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List<Face> faces, List<LocationContainer<MetadataExtractor.Directory>> collection)
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List<Face> faces, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
string? json;
string fileName;
@ -211,7 +211,7 @@ public partial class E_Distance
Face[] filteredFaces = (from l in faces where l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null select l).ToArray();
if (filteredFaces.Length != faces.Count)
checkFaces.Clear();
foreach (LocationContainer<MetadataExtractor.Directory>? locationContainer in collection)
foreach (LocationContainer<MetadataExtractor.Directory>? locationContainer in locationContainers)
{
if (_Renamed.Contains(locationContainer.File))
continue;

View File

@ -71,6 +71,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -34,12 +34,14 @@ public class D_Face
private readonly Serilog.ILogger? _Log;
private readonly bool _OverrideForFaceImages;
private readonly Configuration _Configuration;
private readonly bool _LoadPhotoPrismLocations;
private readonly ImageCodecInfo _ImageCodecInfo;
private readonly ModelParameter _ModelParameter;
private readonly PredictorModel _PredictorModel;
private readonly bool _CheckDFaceAndUpWriteDates;
private readonly bool _PropertiesChangedForFaces;
private readonly ConstructorInfo _ConstructorInfo;
private readonly float _RectangleIntersectMinimum;
private readonly int _FaceDistanceHiddenImageFactor;
private readonly EncoderParameters _EncoderParameters;
private readonly ImageCodecInfo _HiddenImageCodecInfo;
@ -59,11 +61,13 @@ public class D_Face
string hiddenFileNameExtension,
ImageCodecInfo hiddenImageCodecInfo,
ImageCodecInfo imageCodecInfo,
bool loadPhotoPrismLocations,
string modelDirectory,
string modelName,
bool overrideForFaceImages,
string predictorModelName,
bool propertiesChangedForFaces)
bool propertiesChangedForFaces,
float[] rectangleIntersectMinimums)
{
_ArgZero = argZero;
_Configuration = configuration;
@ -76,17 +80,17 @@ public class D_Face
_OverrideForFaceImages = overrideForFaceImages;
_HiddenEncoderParameters = hiddenEncoderParameters;
_HiddenFileNameExtension = hiddenFileNameExtension;
_LoadPhotoPrismLocations = loadPhotoPrismLocations;
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
_PropertiesChangedForFaces = propertiesChangedForFaces;
_RectangleIntersectMinimum = rectangleIntersectMinimums.Min();
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
_Model = model;
_PredictorModel = predictorModel;
_ModelParameter = modelParameter;
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
if (constructorInfo is null)
throw new Exception();
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
_ConstructorInfo = constructorInfo;
_WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
}
@ -294,7 +298,7 @@ public class D_Face
#pragma warning restore CA1416
private static List<LocationContainer<MetadataExtractor.Directory>> GetCollection(string outputResolution, List<LocationContainer<MetadataExtractor.Directory>> collection, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
private static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(string outputResolution, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
{
List<LocationContainer<MetadataExtractor.Directory>> results = new();
string? json;
@ -309,7 +313,7 @@ public class D_Face
continue;
skip.Add(Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, ILocation.Digits, face.OutputResolution));
}
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in collection)
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
if (locationContainer.Directories is null)
continue;
@ -340,7 +344,7 @@ public class D_Face
return results;
}
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<LocationContainer<MetadataExtractor.Directory>>? collection, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<LocationContainer<MetadataExtractor.Directory>>? locationContainers, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
{
List<Shared.Models.Face>? results;
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
@ -383,15 +387,15 @@ public class D_Face
parseExceptions.Add(nameof(D_Face));
}
}
List<LocationContainer<MetadataExtractor.Directory>> locationContainers;
if (results is null || collection is null)
locationContainers = new();
List<LocationContainer<MetadataExtractor.Directory>> collection;
if (results is null || locationContainers is null)
collection = new();
else
locationContainers = GetCollection(outputResolution, collection, outputResolutionToResize, results);
if (mappingFromPhotoPrismCollection is null || results is null)
locations = (from l in locationContainers where l is not null select l.Location).ToList();
collection = GetLocationContainers(outputResolution, locationContainers, outputResolutionToResize, results);
if (!_LoadPhotoPrismLocations || mappingFromPhotoPrismCollection is null || results is null)
locations = (from l in collection where l is not null select l.Location).ToList();
else
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results, locationContainers);
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(collection, results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
if (results is null || (locations is not null && locations.Any()))
{
results = GetFaces(outputResolution, property, mappingFromItem, outputResolutionToResize, locations);

View File

@ -3,7 +3,7 @@
/// <summary>
/// Represents an ordered pair of integer x- and y-coordinates that defines a point in a two-dimensional plane.
/// </summary>
public struct Point : IEquatable<Point>
public readonly struct Point : IEquatable<Point>
{
#region Constructors
@ -73,7 +73,9 @@ public struct Point : IEquatable<Point>
/// Returns the hash code for this <see cref="Point"/>.
/// </summary>
/// <returns>The hash code for this <see cref="Point"/> structure.</returns>
#pragma warning disable IDE0070
public override int GetHashCode()
#pragma warning restore IDE0070
{
int hashCode = 1861411795;
hashCode = hashCode * -1521134295 + X.GetHashCode();

View File

@ -95,11 +95,13 @@ public partial class DlibDotNet
hiddenFileNameExtension,
hiddenImageCodecInfo,
imageCodecInfo,
configuration.LoadPhotoPrismLocations,
configuration.ModelDirectory,
configuration.ModelName,
configuration.OverrideForFaceImages,
configuration.PredictorModelName,
configuration.PropertiesChangedForFaces);
configuration.PropertiesChangedForFaces,
configuration.RectangleIntersectMinimums);
}
{
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality();
@ -456,14 +458,14 @@ public partial class DlibDotNet
else
{
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
List<LocationContainer<MetadataExtractor.Directory>>? collection;
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
if (item.Property?.Id is null)
collection = null;
locationContainers = null;
else
_ = idToLocationContainers.TryGetValue(item.Property.Id.Value, out collection);
_ = idToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers);
if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null;
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, collection, mappingFromPhotoPrismCollection);
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection);
if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
@ -474,8 +476,8 @@ public partial class DlibDotNet
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
if ((_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch)
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& collection is not null && faceCollection.All(l => !l.Saved))
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, collection);
&& locationContainers is not null && faceCollection.All(l => !l.Saved))
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, locationContainers);
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
{
bool saveRotated = false;
@ -881,11 +883,11 @@ public partial class DlibDotNet
private static void LookForAbandoned(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
{
List<string> renameCollection = new();
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> idToCollection in idToLocationContainers)
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in idToLocationContainers)
{
if (distinctFilteredIds.Contains(idToCollection.Key))
if (distinctFilteredIds.Contains(keyValuePair.Key))
continue;
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in idToCollection.Value)
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in keyValuePair.Value)
{
if (locationContainer.File.Contains('!'))
continue;

View File

@ -34,6 +34,7 @@ public class Configuration
[Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JLinks { get; set; }
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
[Display(Name = "Load PhotoPrism Locations"), Required] public bool? LoadPhotoPrismLocations { get; set; }
[Display(Name = "Location Digits"), Required] public int? LocationDigits { get; set; }
[Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; }
[Display(Name = "Look for Abandoned"), Required] public bool? LookForAbandoned { get; set; }
@ -145,6 +146,8 @@ public class Configuration
configuration.IgnoreRelativePaths ??= Array.Empty<string>();
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ??= Array.Empty<string>();
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ??= Array.Empty<string>();
if (configuration.LoadPhotoPrismLocations is null)
throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations));
if (configuration.LocationDigits is null)
throw new NullReferenceException(nameof(configuration.LocationDigits));
if (configuration.LocationFactor is null)
@ -261,6 +264,7 @@ public class Configuration
configuration.JLinks,
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
configuration.LoadPhotoPrismLocations.Value,
configuration.LocationDigits.Value,
configuration.LocationFactor.Value,
configuration.LookForAbandoned.Value,

View File

@ -33,6 +33,7 @@ public class Configuration
public string[] JLinks { init; get; }
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
public bool LoadPhotoPrismLocations { init; get; }
public int LocationDigits { init; get; }
public int LocationFactor { init; get; }
public bool LookForAbandoned { init; get; }
@ -112,6 +113,7 @@ public class Configuration
string[] jLinks,
string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions,
string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions,
bool loadPhotoPrismLocations,
int locationDigits,
int locationFactor,
bool lookForAbandoned,
@ -190,6 +192,7 @@ public class Configuration
JLinks = jLinks;
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
LoadPhotoPrismLocations = loadPhotoPrismLocations;
LocationDigits = locationDigits;
LocationFactor = locationFactor;
LookForAbandoned = lookForAbandoned;

View File

@ -71,6 +71,7 @@
"FocusDirectory": "",
"FocusModel": "",
"GenealogicalDataCommunicationFile": "",
"LoadPhotoPrismLocations": false,
"LocationDigits": 9,
"LocationFactor": 10000,
"LookForAbandoned": true,

View File

@ -607,7 +607,7 @@ internal abstract class MapLogic
return results;
}
private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List<LocationContainer<MetadataExtractor.Directory>> collection, long personKey, string file)
private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, long personKey, string file)
{
const string lnk = ".lnk";
int? id, wholePercentages;
@ -623,29 +623,29 @@ internal abstract class MapLogic
directories = new List<MetadataExtractor.Directory>();
else
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
Rectangle? rectangle = ILocation.GetWholePercentages(configuration.LocationDigits, wholePercentages.Value);
lock (collection)
collection.Add(new(fromDistanceContent, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null));
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
lock (locationContainers)
locationContainers.Add(new(fromDistanceContent, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null));
}
private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, double?)> duplicates)
private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, float?)> duplicates)
{
string personKeyFormatted;
foreach ((long personKey, int id, string file, double? percent) in duplicates)
foreach ((long personKey, int id, string file, float? percent) in duplicates)
{
if (percent is null)
continue;
_ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\""));
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey);
}
foreach ((long personKey, int id, string file, double? percent) in duplicates)
foreach ((long personKey, int id, string file, float? percent) in duplicates)
{
if (percent is not null && percent.Value == 0)
continue;
_ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\""));
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey);
}
foreach ((long personKey, int id, string file, double? percent) in duplicates)
foreach ((long personKey, int id, string file, float? percent) in duplicates)
{
if (percent is not null && percent.Value > 0)
continue;
@ -654,35 +654,30 @@ internal abstract class MapLogic
}
}
private static void LookForPossibleDuplicates(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> collection)
private static void LookForPossibleDuplicates(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
string key;
double? percent;
Rectangle? rectangle;
float? percent;
float itemPercentagesArea;
List<string> delete = new();
Rectangle intersectRectangle;
RectangleF? itemPercentagesRectangle;
(string File, int WholePercentages) item;
Dictionary<string, (string, int)> distinct = new();
List<(long, int, string, double?)> duplicates = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in collection)
List<(long, int, string, float?)> duplicates = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
key = string.Concat(locationContainer.PersonKey, locationContainer.Id);
if (distinct.TryGetValue(key, out item))
{
if (item.WholePercentages == locationContainer.WholePercentages)
continue;
if (locationContainer.Rectangle is null)
itemPercentagesRectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, item.WholePercentages);
if (itemPercentagesRectangle is null || locationContainer.Rectangle is null)
percent = null;
else
{
rectangle = ILocation.GetWholePercentages(configuration.LocationDigits, item.WholePercentages);
if (locationContainer.Rectangle is null || rectangle is null)
percent = null;
else
{
intersectRectangle = Rectangle.Intersect(locationContainer.Rectangle.Value, rectangle.Value);
percent = intersectRectangle.Width * intersectRectangle.Height;
}
itemPercentagesArea = itemPercentagesRectangle.Value.Width * itemPercentagesRectangle.Value.Height;
percent = ILocation.GetIntersectPercent(itemPercentagesRectangle.Value, itemPercentagesArea, locationContainer.Rectangle.Value);
}
delete.Add(item.File);
delete.Add(locationContainer.File);

View File

@ -72,6 +72,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -22,6 +22,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],
@ -137,6 +139,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -30,7 +30,7 @@ public record Marker(
internal static Shared.Models.Marker Map(Marker marker)
{
Shared.Models.Marker result;
(double x, double y, double w, double h, double score) = (double.Parse(marker.X), double.Parse(marker.Y), double.Parse(marker.W), double.Parse(marker.H), double.Parse(marker.Score));
(float x, float y, float w, float h, float score) = (float.Parse(marker.X), float.Parse(marker.Y), float.Parse(marker.W), float.Parse(marker.H), float.Parse(marker.Score));
result = new(
F_PhotoPrism.HexStringToString(marker.MarkerUid),
F_PhotoPrism.HexStringToString(marker.FileUid),

View File

@ -1,3 +1,4 @@
using System.Drawing;
using System.Text;
using System.Text.Json;
using View_by_Distance.Shared.Models;
@ -139,14 +140,14 @@ public class F_PhotoPrism
return results;
}
private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List<string> subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection)
private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List<string> subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection)
{
long? personKey;
string personName;
const int zero = 0;
string personKeyFormatted;
PersonBirthday personBirthday;
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Shared.Models.Marker marker, double percent) in sortedCollection)
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Shared.Models.Marker marker, float percent) in sortedCollection)
{
foreach (PersonContainer personContainer in personContainers)
{
@ -173,18 +174,22 @@ public class F_PhotoPrism
{
string file;
string text;
double percent;
float dlibArea;
float? percent;
string directory;
int width, height;
int? wholePercentages;
RectangleF? prismRectangle;
List<string> subjects = new();
DateTime dateTime = new(ticks);
int dlibLocationWholePercentages;
PersonContainer[]? personContainers;
StringBuilder stringBuilder = new();
System.Drawing.Rectangle dlibRectangle;
System.Drawing.Rectangle? prismRectangle;
System.Drawing.Rectangle intersectRectangle;
RectangleF? dlibPercentagesRectangle;
float rectangleIntersectMinimum = rectangleIntersectMinimums.Min();
Dictionary<int, PersonContainer[]>? wholePercentagesToPersonContainers;
(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection;
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)> collection = new();
(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection;
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)> collection = new();
foreach (Face face in distinctFilteredFaces)
{
collection.Clear();
@ -198,21 +203,23 @@ public class F_PhotoPrism
(_, wholePercentagesToPersonContainers) = mapLogic.GetWholePercentagesToPersonContainers(face.Mapping.MappingFromItem.Id);
if (wholePercentagesToPersonContainers is null || !wholePercentagesToPersonContainers.TryGetValue(wholePercentages.Value, out personContainers))
continue;
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
(width, height) = IOutputResolution.Get(face.OutputResolution);
dlibLocationWholePercentages = ILocation.GetWholePercentages(height, face.Location, Shared.Models.Stateless.ILocation.Digits, width);
dlibPercentagesRectangle = ILocation.GetPercentagesRectangle(Shared.Models.Stateless.ILocation.Digits, dlibLocationWholePercentages);
if (dlibPercentagesRectangle is null)
continue;
dlibArea = dlibPercentagesRectangle.Value.Width * dlibPercentagesRectangle.Value.Height;
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
{
foreach (Shared.Models.Marker marker in mappingFromPhotoPrism.Markers)
{
prismRectangle = ILocation.GetRectangle(mappingFromPhotoPrism.DatabaseFile, marker, face.OutputResolution);
prismRectangle = ILocation.GetPercentagesRectangle(mappingFromPhotoPrism.DatabaseFile, marker, face.OutputResolution);
if (prismRectangle is null)
continue;
intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
percent = ILocation.GetIntersectPercent(dlibPercentagesRectangle.Value, dlibArea, prismRectangle.Value);
if (percent is null || percent < rectangleIntersectMinimum)
continue;
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
if (percent < rectangleIntersectMinimum)
continue;
collection.Add(new(mappingFromPhotoPrism, marker, percent));
collection.Add(new(mappingFromPhotoPrism, marker, percent.Value));
}
}
if (!collection.Any())
@ -222,10 +229,13 @@ public class F_PhotoPrism
}
if (subjects.Any())
{
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-subject_alias_update.sql");
directory = Path.Combine(fPhotoPrismContentDirectory, dateTime.ToString("yyyy-MM-dd"));
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
file = Path.Combine(directory, $"{ticks}-{rectangleIntersectMinimum}-subject_alias_update.sql");
text = string.Join(Environment.NewLine, subjects.Distinct());
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-marker_name_update.sql");
file = Path.Combine(directory, $"{ticks}-{rectangleIntersectMinimum}-marker_name_update.sql");
text = stringBuilder.ToString();
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}

View File

@ -63,6 +63,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -73,6 +73,8 @@
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],

View File

@ -37,7 +37,9 @@ public class FacePoint : Properties.IFacePoint
return result;
}
#pragma warning disable IDE0070
public override int GetHashCode()
#pragma warning restore IDE0070
{
int hashCode = 1861411795;
hashCode = hashCode * -1521134295 + _Point.GetHashCode();

View File

@ -74,7 +74,9 @@ public class Location : Properties.ILocation, IEquatable<Location>
return result;
}
#pragma warning disable IDE0070
public override int GetHashCode()
#pragma warning restore IDE0070
{
int hashCode = -773114317;
hashCode = hashCode * -1521134295 + Bottom.GetHashCode();

View File

@ -2,5 +2,5 @@ using System.Drawing;
namespace View_by_Distance.Shared.Models;
public record LocationContainer<T>(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, Rectangle? Rectangle, Location? Location)
public record LocationContainer<T>(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, RectangleF? Rectangle, Location? Location)
{ }

View File

@ -12,13 +12,13 @@ public record Marker(
string? SubjSrc,
string? FaceId,
string FaceDist,
double X,
double Y,
double W,
double H,
float X,
float Y,
float W,
float H,
string Q,
string Size,
double Score,
float Score,
string? Thumb,
string MatchedAt,
string CreatedAt,

View File

@ -31,9 +31,7 @@ internal abstract class Face
private static JsonElement[] GetJsonElements(string jsonFileFullName)
{
string json = GetJson(jsonFileFullName);
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json);
if (jsonElements is null)
throw new Exception();
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json) ?? throw new Exception();
return jsonElements;
}

View File

@ -15,25 +15,25 @@ public interface ILocation
static List<Models.Face> FilterByIntersect(Models.Face[] faces, float rectangleIntersectMinimum, int wholePercentages) =>
Location.FilterByIntersect(faces, rectangleIntersectMinimum, wholePercentages);
Rectangle? TestStatic_GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
GetRectangle(databaseFile, marker, outputResolution);
static Rectangle? GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
Location.GetRectangle(databaseFile, marker, outputResolution);
RectangleF? TestStatic_GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
GetPercentagesRectangle(databaseFile, marker, outputResolution);
static RectangleF? GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
Location.GetPercentagesRectangle(databaseFile, marker, outputResolution);
Models.Location? TestStatic_GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
GetLocation(databaseFile, marker, outputResolution);
static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
Location.GetLocation(databaseFile, marker, outputResolution);
List<Models.Location> TestStatic_GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers) =>
GetLocations(mappingFromPhotoPrismCollection, faces, containers);
static List<Models.Location> GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers) =>
Location.GetLocations(mappingFromPhotoPrismCollection, faces, containers);
List<Models.Location> TestStatic_GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
Location.GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
Rectangle? TestStatic_GetWholePercentages(int locationDigits, int wholePercentages) =>
GetWholePercentages(locationDigits, wholePercentages);
static Rectangle? GetWholePercentages(int locationDigits, int wholePercentages) =>
Location.GetWholePercentages(locationDigits, wholePercentages.ToString());
RectangleF? TestStatic_GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
GetPercentagesRectangle(locationDigits, wholePercentages);
static RectangleF? GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
Location.GetPercentagesRectangle(locationDigits, wholePercentages.ToString());
Rectangle? TestStatic_GetRectangle(int locationDigits, Models.OutputResolution outputResolution, int wholePercentages) =>
GetRectangle(locationDigits, outputResolution, wholePercentages);
@ -90,6 +90,11 @@ public interface ILocation
static int GetWholePercentages(int locationDigits) =>
Location.GetWholePercentages(1, 1, 0, locationDigits, 1, 0, 1, zCount: 1);
int TestStatic_GetWholePercentages(int height, Models.Location location, int locationDigits, int width) =>
GetWholePercentages(height, location, locationDigits, width);
static int GetWholePercentages(int height, Models.Location location, int locationDigits, int width) =>
Location.GetWholePercentages(height, location, locationDigits, width);
int TestStatic_GetWholePercentages(int bottom, int height, int left, int locationDigits, int right, int top, int width) =>
GetWholePercentages(bottom, height, left, locationDigits, right, top, width);
static int GetWholePercentages(int bottom, int height, int left, int locationDigits, int right, int top, int width) =>
@ -109,4 +114,9 @@ public interface ILocation
width,
facesCount);
float? TestStatic_GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB) =>
GetIntersectPercent(rectangleA, areaA, rectangleB);
static float? GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB) =>
Location.GetIntersectPercent(rectangleA, areaA, rectangleB);
}

View File

@ -3,6 +3,11 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IOutputResolution
{ // ...
(int, int) TestStatic_Get(Models.OutputResolution outputResolution) =>
Get(outputResolution);
static (int, int) Get(Models.OutputResolution outputResolution) =>
OutputResolution.Get(outputResolution);
int TestStatic_GetHeight(Models.OutputResolution outputResolution) =>
GetHeight(outputResolution);
static int GetHeight(Models.OutputResolution outputResolution) =>

View File

@ -108,15 +108,21 @@ internal abstract class Location
return result;
}
internal static int GetWholePercentages(int height, Models.Location location, int locationDigits, int width)
{
int result = GetWholePercentages(location.Bottom, height, location.Left, locationDigits, location.Right, location.Top, width, zCount: 1);
return result;
}
internal static int GetConfidencePercent(int faceConfidencePercent, float[] rangeFaceConfidence, double confidence)
{
int result = (int)(confidence / rangeFaceConfidence[1] * faceConfidencePercent);
return result;
}
internal static Rectangle? GetWholePercentages(int locationDigits, string wholePercentages)
internal static RectangleF? GetPercentagesRectangle(int locationDigits, string wholePercentages)
{
Rectangle? result;
RectangleF? result;
int length = (locationDigits - 1) / 4;
string[] segments = new string[]
{
@ -133,7 +139,10 @@ internal abstract class Location
if (!int.TryParse(segments[1], out int xWholePercent) || !int.TryParse(segments[2], out int yWholePercent) || !int.TryParse(segments[3], out int wWholePercent) || !int.TryParse(segments[4], out int hWholePercent))
result = null;
else
result = new(xWholePercent, yWholePercent, wWholePercent, hWholePercent);
{
float factor = 100;
result = new(xWholePercent / factor, yWholePercent / factor, wWholePercent / factor, hWholePercent / factor);
}
}
return result;
}
@ -143,14 +152,13 @@ internal abstract class Location
Rectangle? result;
if (wholePercentages.Length != locationDigits || wholePercentages[0] is not '4' and not '8')
throw new NotSupportedException("Old way has been removed!");
(int width, int height) = OutputResolution.Get(outputResolution);
Rectangle? rectangle = GetWholePercentages(locationDigits, wholePercentages);
(int width, int height) = OutputResolution.Get(outputResolution);
RectangleF? rectangle = GetPercentagesRectangle(locationDigits, wholePercentages);
if (rectangle is null)
result = null;
else
{
decimal factor = 100;
result = new((int)(rectangle.Value.X / factor * width), (int)(rectangle.Value.Y / factor * height), (int)(rectangle.Value.Width / factor * width), (int)(rectangle.Value.Height / factor * height));
result = new((int)(rectangle.Value.X * width), (int)(rectangle.Value.Y * height), (int)(rectangle.Value.Width * width), (int)(rectangle.Value.Height * height));
}
if (result is null)
throw new NullReferenceException(nameof(result));
@ -163,25 +171,29 @@ internal abstract class Location
return result;
}
internal static Rectangle? GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
internal static RectangleF? GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
{
Rectangle? result;
RectangleF? result;
bool matches = Matches(outputResolution, databaseFile);
if (!matches)
result = null;
else
result = new((int)Math.Ceiling(marker.X * databaseFile.FileWidth), (int)Math.Ceiling(marker.Y * databaseFile.FileHeight), (int)Math.Ceiling(marker.W * databaseFile.FileWidth), (int)Math.Ceiling(marker.H * databaseFile.FileHeight));
result = new(marker.X, marker.Y, marker.W, marker.H);
return result;
}
private static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Rectangle rectangle)
private static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, RectangleF rectangle)
{
Models.Location? result;
bool verified = Check(rectangle.Bottom, databaseFile.FileHeight, rectangle.Left, rectangle.Right, rectangle.Top, databaseFile.FileWidth, zCount: 1, throwException: false);
int top = (int)Math.Ceiling(rectangle.Top * databaseFile.FileHeight);
int left = (int)Math.Ceiling(rectangle.Left * databaseFile.FileWidth);
int right = (int)Math.Ceiling(rectangle.Right * databaseFile.FileWidth);
int bottom = (int)Math.Ceiling(rectangle.Bottom * databaseFile.FileHeight);
bool verified = Check(bottom, databaseFile.FileHeight, left, right, top, databaseFile.FileWidth, zCount: 1, throwException: false);
if (!verified)
result = null;
else
result = new(rectangle.Bottom, marker.Score / 100, rectangle.Left, rectangle.Right, rectangle.Top);
result = new(bottom, marker.Score / 100, left, right, top);
return result;
}
@ -200,7 +212,7 @@ internal abstract class Location
internal static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
{
Models.Location? result;
Rectangle? rectangle = GetRectangle(databaseFile, marker, outputResolution);
RectangleF? rectangle = GetPercentagesRectangle(databaseFile, marker, outputResolution);
if (rectangle is null)
result = null;
else
@ -208,15 +220,43 @@ internal abstract class Location
return result;
}
internal static List<Models.Location> GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers)
internal static float? GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB)
{
float? result;
if (rectangleA.Equals(rectangleB))
result = 1;
else
{
float intersectArea;
RectangleF intersectRectangle;
areaA ??= rectangleA.Width * rectangleA.Height;
float areaB = rectangleB.Width * rectangleB.Height;
bool check = areaA > areaB;
if (check)
intersectRectangle = RectangleF.Intersect(rectangleB, rectangleA);
else
intersectRectangle = RectangleF.Intersect(rectangleA, rectangleB);
intersectArea = intersectRectangle.Width * intersectRectangle.Height;
if (check)
result = intersectArea / areaA;
else
result = intersectArea / areaB;
}
return result;
}
internal static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
{
List<Models.Location> results = new();
bool any;
bool matches;
Rectangle dlibRectangle;
Rectangle? prismRectangle;
float? percent;
float prismArea;
int width, height;
Models.Location? location;
Rectangle intersectRectangle;
RectangleF? prismRectangle;
int dlibLocationWholePercentages;
RectangleF? dlibPercentagesRectangle;
Models.OutputResolution? outputResolution = null;
foreach (Models.Face face in faces)
{
@ -226,7 +266,7 @@ internal abstract class Location
outputResolution ??= face.OutputResolution;
}
int before = results.Count;
foreach (LocationContainer<T> locationContainer in containers)
foreach (LocationContainer<T> locationContainer in locationContainers)
{
if (locationContainer.Location is null)
continue;
@ -242,23 +282,24 @@ internal abstract class Location
foreach (Marker marker in mappingFromPhotoPrism.Markers)
{
any = false;
prismRectangle = GetRectangle(mappingFromPhotoPrism.DatabaseFile, marker, outputResolution);
prismRectangle = GetPercentagesRectangle(mappingFromPhotoPrism.DatabaseFile, marker, outputResolution);
if (prismRectangle is null)
break;
prismArea = prismRectangle.Value.Width * prismRectangle.Value.Height;
location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value);
if (location is null)
break;
foreach (LocationContainer<T> locationContainer in containers)
foreach (LocationContainer<T> locationContainer in locationContainers)
{
if (any)
continue;
if (locationContainer.Location is null)
if (locationContainer.Rectangle is null)
continue;
dlibRectangle = new(locationContainer.Location.Left, locationContainer.Location.Top, locationContainer.Location.Right - locationContainer.Location.Left, locationContainer.Location.Bottom - locationContainer.Location.Top);
intersectRectangle = Rectangle.Intersect(prismRectangle.Value, dlibRectangle);
if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0)
percent = GetIntersectPercent(prismRectangle.Value, prismArea, locationContainer.Rectangle.Value);
if (percent is null || percent < rectangleIntersectMinimum)
continue;
any = true;
if (!any)
any = true;
break;
}
foreach (Models.Face face in faces)
@ -267,11 +308,16 @@ internal abstract class Location
continue;
if (face.Location is null || face.OutputResolution is null)
continue;
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
intersectRectangle = Rectangle.Intersect(prismRectangle.Value, dlibRectangle);
if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0)
(width, height) = OutputResolution.Get(face.OutputResolution);
dlibLocationWholePercentages = GetWholePercentages(height, face.Location, Stateless.ILocation.Digits, width);
dlibPercentagesRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, dlibLocationWholePercentages.ToString());
if (dlibPercentagesRectangle is null)
continue;
any = true;
percent = GetIntersectPercent(prismRectangle.Value, prismArea, dlibPercentagesRectangle.Value);
if (percent is null || percent < rectangleIntersectMinimum)
continue;
if (!any)
any = true;
break;
}
if (!any)
@ -283,31 +329,28 @@ internal abstract class Location
return results;
}
// private static double GP(OutputResolution outputResolution,Location location, ){
// double result;
// return result;
// }
internal static List<Models.Face> FilterByIntersect(Models.Face[] faces, float rectangleIntersectMinimum, int wholePercentages)
{
List<Models.Face> results = new();
double? percent;
Rectangle checkRectangle;
Rectangle? sourceRectangle;
Rectangle intersectRectangle;
float? percent;
int width, height;
int faceLocationWholePercentages;
RectangleF? facePercentagesRectangle;
RectangleF? sourceRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, wholePercentages.ToString());
float? sourceArea = sourceRectangle is null ? null : sourceRectangle.Value.Width * sourceRectangle.Value.Height;
foreach (Models.Face face in faces)
{
if (sourceRectangle is null || sourceArea is null)
continue;
if (face.Location is null || face.OutputResolution is null)
continue;
checkRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
sourceRectangle = GetRectangle(Stateless.ILocation.Digits, face.OutputResolution, wholePercentages.ToString());
if (sourceRectangle is null)
(width, height) = OutputResolution.Get(face.OutputResolution);
faceLocationWholePercentages = GetWholePercentages(height, face.Location, Stateless.ILocation.Digits, width);
facePercentagesRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, faceLocationWholePercentages.ToString());
if (facePercentagesRectangle is null)
continue;
intersectRectangle = Rectangle.Intersect(checkRectangle, sourceRectangle.Value);
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
continue;
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);
if (percent < rectangleIntersectMinimum)
percent = GetIntersectPercent(sourceRectangle.Value, sourceArea.Value, facePercentagesRectangle.Value);
if (percent is null || percent < rectangleIntersectMinimum)
continue;
results.Add(face);
}

View File

@ -4,6 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
@ -307,4 +308,74 @@ public partial class UnitTestCalculations
NonThrowTryCatch();
}
[TestMethod]
public void TestMethodIntersect()
{
float? percent;
float? areaA = null;
RectangleF rectangleA;
RectangleF rectangleB;
rectangleA = new(0, 0, 4, 4);
rectangleB = new(0, 0, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == 1);
rectangleA = new(0, 0, 4, 4);
rectangleB = new(0, 0, 2, 2);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .25);
rectangleA = new(0, 0, 4, 4);
rectangleB = new(0, 0, 4, 2);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .5);
rectangleA = new(0, 0, 4, 4);
rectangleB = new(2, 2, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .25);
rectangleA = new(0, 0, 4, 4);
rectangleB = new(2, 0, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .5);
rectangleA = new(0, 0, 4, 4);
rectangleB = new(2, 4, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == 0);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(0, 0, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == 1);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(0, 0, 2, 2);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .25);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(0, 0, 4, 2);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .5);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(2, 2, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .25);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(2, 0, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == .5);
rectangleB = new(0, 0, 4, 4);
rectangleA = new(2, 4, 4, 4);
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
Assert.IsNotNull(percent);
Assert.IsTrue(percent.Value == 0);
NonThrowTryCatch();
}
}