/SketchModeller/SketchModeller.Modelling/Services/AnnotationInference/ParallelismInferer.cs

https://bitbucket.org/alexshtf/sketchmodeller · C# · 83 lines · 68 code · 14 blank · 1 comment · 2 complexity · e4f053f6de40e98dfc7b13f5646afffe MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SketchModeller.Infrastructure.Data;
  6. using SketchModeller.Infrastructure.Shared;
  7. using Utils;
  8. using Enumerable = System.Linq.Enumerable;
  9. using UtilsEnumerable = Utils.Enumerable;
  10. using System.Windows.Media.Media3D;
  11. namespace SketchModeller.Modelling.Services.AnnotationInference
  12. {
  13. class ParallelismInferer: IInferrer
  14. {
  15. public const double DEFAULT_ANGLE_THRESHOLD = 20 * Math.PI / 180;
  16. private SessionData sessionData;
  17. private double angleThreshold;
  18. public ParallelismInferer(SessionData sessionData,
  19. double angleThreshold = DEFAULT_ANGLE_THRESHOLD)
  20. {
  21. this.sessionData = sessionData;
  22. this.angleThreshold = angleThreshold;
  23. }
  24. public IEnumerable<Annotation> InferAnnotations(NewPrimitive toBeSnapped, SnappedPrimitive toBeAnnotated)
  25. {
  26. // we skip orthogonality inference for spheres
  27. if (toBeSnapped is NewSphere)
  28. return Enumerable.Empty<Annotation>();
  29. var curvesToSkip = toBeAnnotated.FeatureCurves.Concat(GetSphereFeatureCurves()).ToArray();
  30. var candidates =
  31. from firstCurve in toBeAnnotated.FeatureCurves
  32. from secondCurve in sessionData.FeatureCurves.Except(curvesToSkip)
  33. where AreGoodCandidates(firstCurve, secondCurve)
  34. select Tuple.Create(firstCurve, secondCurve);
  35. if (candidates.Any())
  36. {
  37. var bestCandidate = candidates.Minimizer(pair => DistanceBetweenCurves(pair.Item1, pair.Item2));
  38. var newFeatureCurve = bestCandidate.Item1;
  39. var existingFeatureCurve = bestCandidate.Item2;
  40. Annotation parallelism = new Parallelism { Elements = new FeatureCurve[] { newFeatureCurve, existingFeatureCurve } };
  41. return UtilsEnumerable.Singleton(parallelism);
  42. }
  43. else
  44. return Enumerable.Empty<Annotation>();
  45. }
  46. private bool AreGoodCandidates(FeatureCurve firstCurve, FeatureCurve secondCurve)
  47. {
  48. bool angleCondition = IsAngleBelowThreshold(firstCurve, secondCurve);
  49. return angleCondition;
  50. }
  51. private bool IsAngleBelowThreshold(FeatureCurve firstCurve, FeatureCurve secondCurve)
  52. {
  53. var crossLength = Vector3D.CrossProduct(firstCurve.NormalResult.Normalized(), secondCurve.NormalResult.Normalized()).Length;
  54. var angle = Math.Asin(crossLength);
  55. return angle <= angleThreshold;
  56. }
  57. private double DistanceBetweenCurves(FeatureCurve first, FeatureCurve second)
  58. {
  59. return (first.CenterResult - second.CenterResult).Length;
  60. }
  61. private IEnumerable<FeatureCurve> GetSphereFeatureCurves()
  62. {
  63. return from primitive in sessionData.SnappedPrimitives
  64. where primitive is SnappedSphere
  65. from curve in primitive.FeatureCurves
  66. select curve;
  67. }
  68. }
  69. }