public bool TryProjectOnto(HoleInstanceMetadata instanceMetadata, SectorNodeDescription sectorNodeDescription, out IReadOnlyList <Polygon2> projectedHoleIncludedContours, out IReadOnlyList <Polygon2> projectedHoleExcludedContours) { // transformation matrix from hole-local space to sector-local space var transformHoleToSector = instanceMetadata.WorldTransform * sectorNodeDescription.WorldTransformInv; // compute projected poly's bounds in sector-local space. var boundsWorld = ComputeExtrudedBoundsLocal().Map(p => Vector3.Transform(p, transformHoleToSector)); // test if projected poly is within sector-local space. var intersects = Enumerable.Any <Vector3>(boundsWorld, p => sectorNodeDescription.StaticMetadata.LocalBoundary.Contains((int)p.X, (int)p.Y)); var withinHeight = Enumerable.Any <Vector3>(boundsWorld, p => p.Z >= -1E-3 && p.Z <= Height); // if (false && () !intersects || !withinHeight) { // projectedHoleIncludedContours = null; // projectedHoleExcludedContours = null; // return false; // } // Project rest of points into sector-local space. projectedHoleIncludedContours = LocalIncludedContours.Map(contour => new Polygon2( contour.Points.Map(p => DotNetVector4ToIV2XY(Vector4.Transform(IV2ToDotNetVector4(p, Height), transformHoleToSector))).ToList())); projectedHoleExcludedContours = LocalExcludedContours.Map(contour => new Polygon2( contour.Points.Map(p => DotNetVector4ToIV2XY(Vector4.Transform(IV2ToDotNetVector4(p, Height), transformHoleToSector))).ToList())); return(true); }
public bool TryProjectOnto(HoleInstanceMetadata instanceMetadata, SectorNodeDescription sectorNodeDescription, out IReadOnlyList <Polygon2> projectedHoleIncludedContours, out IReadOnlyList <Polygon2> projectedHoleExcludedContours) { Trace.Assert(Matrix4x4.Decompose(instanceMetadata.WorldTransform, out var scale, out var rotation, out var translation)); Trace.Assert(Math.Abs(scale.X - scale.Y) < 1E-9 && Math.Abs(scale.X - scale.Z) < 1E-9); var effectiveRadiusWorld = scale.X * Radius; var normalSectorWorld = Vector3.TransformNormal(new Vector3(0, 0, 1), sectorNodeDescription.WorldTransform).ToOpenMobaVector(); var normalSectorWorldUnit = normalSectorWorld / normalSectorWorld.Norm2D(); var sectorOriginWorld = Vector3.Transform(new Vector3(0, 0, 0), sectorNodeDescription.WorldTransform).ToOpenMobaVector(); var distanceWorld = Math.Abs((sectorOriginWorld - translation.ToOpenMobaVector()).Dot(normalSectorWorldUnit)); var c2MinusA2 = effectiveRadiusWorld * effectiveRadiusWorld - distanceWorld * distanceWorld; if (c2MinusA2 <= 0) { projectedHoleIncludedContours = null; projectedHoleExcludedContours = null; return(false); } var effectiveRadiusWorldOnSectorPlane = (float)Math.Sqrt(c2MinusA2); var effectiveRadiusSector = Vector3.TransformNormal( new Vector3(0, 0, effectiveRadiusWorldOnSectorPlane), sectorNodeDescription.InstanceMetadata.WorldTransformInv ).Length(); // if (effectiveRadiusSector < 200) { // projectedHoleIncludedContours = null; // projectedHoleExcludedContours = null; // return false; // } else { // projectedHoleIncludedContours = new List<Polygon2> { // Polygon2.CreateCircle(0, 0, 20) // }; // projectedHoleExcludedContours = new List<Polygon2>(); // return true; // } var centerSector = Vector3.Transform( translation, sectorNodeDescription.InstanceMetadata.WorldTransformInv ); projectedHoleIncludedContours = new List <Polygon2> { Polygon2.CreateCircle((int)centerSector.X, (int)centerSector.Y, (int)effectiveRadiusSector) }; projectedHoleExcludedContours = new List <Polygon2>(); return(true); }