public static List <NestPath> polygonOffset(NestPath polygon, double offset) { List <NestPath> result = new List <NestPath>(); if (offset == 0 || GeometryUtil.almostEqual(offset, 0)) { /** * return EmptyResult */ return(result); } Path p = new Path(); foreach (Segment s in polygon.getSegments()) { ClipperCoor cc = toClipperCoor(s.getX(), s.getY()); p.Add(new IntPoint(cc.getX(), cc.getY())); } int miterLimit = 2; ClipperOffset co = new ClipperOffset(miterLimit, Config.CURVE_TOLERANCE * Config.CLIIPER_SCALE); co.AddPath(p, JoinType.jtRound, EndType.etClosedPolygon); Paths newpaths = new Paths(); co.Execute(ref newpaths, offset * Config.CLIIPER_SCALE); /** * 这里的length是1的话就是我们想要的 */ for (int i = 0; i < newpaths.Count; i++) { result.Add(CommonUtil.clipperToNestPath(newpaths[i])); } if (offset > 0) { NestPath from = result[0]; if (GeometryUtil.polygonArea(from) > 0) { from.reverse(); } from.add(from.get(0)); from.getSegments().RemoveAt(0); } return(result); }
private void QueryTask_ExecuteCompleted(object sender, QueryEventArgs args) { if (_originPoint == null) { return; } double searchDistance = (double)args.UserState; double x = _originPoint.X; double y = _originPoint.Y; Int32 id = 0; if (args.FeatureSet.Features.Count > 0) { foreach (Graphic feature in args.FeatureSet.Features) { // test type of feature, and test it's end points. if (feature.Geometry is ESRI.ArcGIS.Client.Geometry.Polygon) { ESRI.ArcGIS.Client.Geometry.Polygon featurePolygon = feature.Geometry as ESRI.ArcGIS.Client.Geometry.Polygon; foreach (ESRI.ArcGIS.Client.Geometry.PointCollection pointCollection in featurePolygon.Rings) { AddLineSegmentToCache(pointCollection, x, y, searchDistance, ref id); } } else if (feature.Geometry is ESRI.ArcGIS.Client.Geometry.Polyline) { ESRI.ArcGIS.Client.Geometry.Polyline featurePolyline = feature.Geometry as ESRI.ArcGIS.Client.Geometry.Polyline; foreach (ESRI.ArcGIS.Client.Geometry.PointCollection pointCollection in featurePolyline.Paths) { AddLineSegmentToCache(pointCollection, x, y, searchDistance, ref id); } } else if (feature.Geometry is ESRI.ArcGIS.Client.Geometry.MapPoint) { ESRI.ArcGIS.Client.Geometry.MapPoint featurePoint = feature.Geometry as ESRI.ArcGIS.Client.Geometry.MapPoint; double distance = GeometryUtil.LineLength(x, y, featurePoint); if (distance < searchDistance) { _snapObjects[id++] = feature.Geometry; } } } } System.Diagnostics.Debug.WriteLine("Async: Number of objects cached: " + args.FeatureSet.Features.Count.ToString()); CalculateAndAddLineGraphics(); // We need to redraw, so we get the right snap marker }
/// <inheritdoc/> /// <summary> /// </summary> /// <param name="particles"></param> public void Calculate(IReadOnlyList<IBody> particles) { // implementation ref https://www.cs.cmu.edu/~kmcrane/Projects/DDG/paper.pdf (p.64) GeometryUtil.GetTriAreaGradients( particles[_h0].Position, particles[_h1].Position, particles[_h2].Position, out Vec3d g0, out Vec3d g1, out Vec3d g2); _h0.Delta = -g0; _h1.Delta = -g1; _h2.Delta = -g2; }
/// <summary> /// Constructor /// </summary> /// <param name="items">Partitioning items</param> /// <param name="maxDepth">Maximum depth</param> public PickingQuadTree(IEnumerable <T> items, int maxDepth) { var bbox = GeometryUtil.CreateBoundingBox(items); this.BoundingBox = bbox; this.Root = PickingQuadTreeNode <T> .CreatePartitions( this, null, bbox, items, maxDepth, 0); this.Root.ConnectNodes(); }
public void RemovePoint() { if (vertices2D.Count <= 4) { Debug.LogWarning("To small points count"); return; } int indxMinDist = GeometryUtil.FindClosest(vertices2D, MapCreatorLoader.Pointer2d); UpdateSelfShape(); vertices2D.RemoveAt(indxMinDist); ReDraw(); }
/// <summary> /// Create the "Body" IfcRepresentation for a beam if it is representable by an extrusion, possibly with clippings and openings. /// </summary> /// <param name="exporterIFC">The exporterIFC class.</param> /// <param name="element">The beam element.T</param> /// <param name="catId">The category id.</param> /// <param name="geomObjects">The list of solids and meshes representing the beam's geometry. /// <param name="axisInfo">The beam axis information.</param> /// <returns>The BeamBodyAsExtrusionInfo class which contains the created handle (if any) and other information, or null.</returns> private static BeamBodyAsExtrusionInfo CreateBeamGeometryAsExtrusion(ExporterIFC exporterIFC, Element element, ElementId catId, IList <GeometryObject> geomObjects, BeamAxisInfo axisInfo) { // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (geomObjects == null || geomObjects.Count != 1 || (!(geomObjects[0] is Solid)) || axisInfo == null || !(axisInfo.Axis is Line)) { return(null); } Solid solid = geomObjects[0] as Solid; BeamBodyAsExtrusionInfo info = new BeamBodyAsExtrusionInfo(); info.DontExport = false; info.Materials = new HashSet <ElementId>(); info.Slope = 0.0; Transform orientTrf = axisInfo.LCSAsTransform; bool completelyClipped; XYZ beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); info.RepresentationHandle = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solid, beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) { info.DontExport = true; return(null); } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(info.RepresentationHandle)) { // This is used by the BeamSlopeCalculator. This should probably be generated automatically by // CreateExtrusionWithClipping. IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ? IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY; info.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis); ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solid, exporterIFC, element); if (materialId != ElementId.InvalidElementId) { info.Materials.Add(materialId); } } return(info); }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a structural member objects, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The structural member element.</param> /// <param name="catId">The structural member category id.</param> /// <param name="axisInfo">The optional structural member axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> public static IFCAnyHandle CreateStructuralMemberAxis(ExporterIFC exporterIFC, Element element, ElementId catId, StructuralMemberAxisInfo axisInfo, Transform newTransformLCS) { if (axisInfo == null) { return(null); } // This Axis should have been transformed into its ECS position previously (in GetStructuralMemberAxisTransform()) Curve curve = axisInfo.Axis; Transform offset = Transform.Identity; if (newTransformLCS != null) { // We need to flip the Left-handed transform to the right-hand one as IFC only support right-handed coordinate system if (newTransformLCS.Determinant < 0) { XYZ orig = newTransformLCS.Origin; newTransformLCS.Origin = XYZ.Zero; offset = FlipYTrf().Multiply(newTransformLCS); offset.Origin = orig; } else { offset = newTransformLCS; } } // Calculate the transformation matrix to tranform the original Axis Curve at its ECS into the new ECS assigned in the offset curve = curve.CreateTransformed(offset.Inverse.Multiply(axisInfo.LCSAsTransform)); IDictionary <IFCFuzzyXYZ, IFCAnyHandle> cachePoints = new Dictionary <IFCFuzzyXYZ, IFCAnyHandle>(); IFCAnyHandle ifcCurveHnd = GeometryUtil.CreateIFCCurveFromRevitCurve(exporterIFC.GetFile(), exporterIFC, curve, true, cachePoints); IList <IFCAnyHandle> axis_items = new List <IFCAnyHandle>(); if (!(IFCAnyHandleUtil.IsNullOrHasNoValue(ifcCurveHnd))) { axis_items.Add(ifcCurveHnd); } if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. string representationTypeOpt = "Curve3D"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// 获取凸出部分的圆所有坐标 /// </summary> /// <param name="CenterVector"></param> /// <param name="edgeEnum"></param> /// <param name="bulgeEnum"></param> /// <returns></returns> private List <Vector3> getCircleVertices(Vector3 centerVector, float bulgeR, JigsawStyleNormalEdgeEnum edgeEnum, JigsawBulgeEnum bulgeEnum) { if (edgeEnum == JigsawStyleNormalEdgeEnum.Left) { if (bulgeEnum == JigsawBulgeEnum.Bulge) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, true, CircleStartVectorEnum.Below)); } else if (bulgeEnum == JigsawBulgeEnum.Sunken) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, false, CircleStartVectorEnum.Below)); } } else if (edgeEnum == JigsawStyleNormalEdgeEnum.Above) { if (bulgeEnum == JigsawBulgeEnum.Bulge) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, true, CircleStartVectorEnum.Left)); } else if (bulgeEnum == JigsawBulgeEnum.Sunken) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, false, CircleStartVectorEnum.Left)); } } else if (edgeEnum == JigsawStyleNormalEdgeEnum.Right) { if (bulgeEnum == JigsawBulgeEnum.Bulge) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, true, CircleStartVectorEnum.Above)); } else if (bulgeEnum == JigsawBulgeEnum.Sunken) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, false, CircleStartVectorEnum.Above)); } } else if (edgeEnum == JigsawStyleNormalEdgeEnum.Below) { if (bulgeEnum == JigsawBulgeEnum.Bulge) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, true, CircleStartVectorEnum.Right)); } else if (bulgeEnum == JigsawBulgeEnum.Sunken) { return(GeometryUtil.getCircleVertices(centerVector, bulgeR, m_JigsawTriangleNumber, false, CircleStartVectorEnum.Right)); } } return(new List <Vector3>()); }
/// <summary> /// Returns the planar deviation of this face /// </summary> /// <typeparam name="V"></typeparam> /// <typeparam name="E"></typeparam> /// <typeparam name="F"></typeparam> /// <param name="face"></param> /// <param name="getPosition"></param> /// <returns></returns> public static double GetPlanarity <V, E, F>(this IHeFace <V, E, F> face, Func <V, Vec3d> getPosition) where V : IHeVertex <V, E, F> where E : IHalfedge <V, E, F> where F : IHeFace <V, E, F> { var he0 = face.First; var he1 = he0; var p0 = getPosition(he1.Start); he1 = he1.NextInFace; var p1 = getPosition(he1.Start); he1 = he1.NextInFace; var p2 = getPosition(he1.Start); he1 = he1.NextInFace; // tri case if (ReferenceEquals(he1, he0)) { return(0.0); } var p3 = getPosition(he1.Start); he1 = he1.NextInFace; // quad case if (ReferenceEquals(he1, he0)) { return(GeometryUtil.GetQuadPlanarity(p0, p1, p2, p3)); } // general case double sum = 0.0; int count = 0; foreach (var he in he1.CirculateFace) { sum += GeometryUtil.GetQuadPlanarity(p0, p1, p2, p3); p0 = p1; p1 = p2; p2 = p3; p3 = getPosition(he.Start); } return(sum / count); }
/// <summary> /// Performs the pharmacophore matching. /// </summary> /// <param name="atomContainer">The target molecule. Must have 3D coordinates</param> /// <param name="initializeTarget">If <see langword="true"/>, the target molecule specified in the /// first argument will be analyzed to identify matching pharmacophore groups. If <see langword="false"/> /// this is not performed. The latter case is only useful when dealing with conformers /// since for a given molecule, all conformers will have the same pharmacophore groups /// and only the constraints will change from one conformer to another.</param> /// <returns><see langword="true"/> is the target molecule contains the query pharmacophore</returns> /// <exception cref="CDKException"> /// if the query pharmacophore was not set or the query is invalid or if the molecule /// does not have 3D coordinates</exception> public bool Matches(IAtomContainer atomContainer, bool initializeTarget) { if (!GeometryUtil.Has3DCoordinates(atomContainer)) { throw new CDKException("Molecule must have 3D coordinates"); } if (pharmacophoreQuery == null) { throw new CDKException("Must set the query pharmacophore before matching"); } if (!CheckQuery(pharmacophoreQuery)) { throw new CDKException("A problem in the query. Make sure all pharmacophore groups of the same symbol have the same same SMARTS"); } var title = atomContainer.Title; if (initializeTarget) { pharmacophoreMolecule = GetPharmacophoreMolecule(atomContainer); } else { // even though the atoms comprising the pcore groups are // constant, their coords will differ, so we need to make // sure we get the latest set of effective coordinates foreach (var iAtom in pharmacophoreMolecule.Atoms) { var patom = PharmacophoreAtom.Get(iAtom); var tmpList = new List <int>(); foreach (var idx in patom.GetMatchingAtoms()) { tmpList.Add(idx); } var coords = GetEffectiveCoordinates(atomContainer, tmpList); patom.Point3D = coords; } } if (pharmacophoreMolecule.Atoms.Count < pharmacophoreQuery.Atoms.Count) { Debug.WriteLine($"Target [{title}] did not match the query SMARTS. Skipping constraints"); return(false); } mappings = Pattern.FindSubstructure(pharmacophoreQuery).MatchAll(pharmacophoreMolecule); // XXX: doing one search then discarding return(mappings.AtLeast(1)); }
private void decomposeAnim() { if (mListObj == null) { return; } int listCount = mListObj.Count; float radius = 0; if (mGameStartControl == null) { return; } if (mGameStartControl.picAllWith > mGameStartControl.picAllHigh) { radius = mGameStartControl.picAllHigh; } else { radius = mGameStartControl.picAllWith; } List <Vector3> listCircleVec = GeometryUtil.getCircleVertices(startPosition, radius * 1.9f, listCount, true, CircleStartVectorEnum.Left); for (int i = 0; i < listCount; i++) { GameObject itemObj = mListObj[i]; Transform itemTF = itemObj.transform; //设置层级 JigsawContainerCpt containerCpt = itemTF.GetComponent <JigsawContainerCpt>(); if (containerCpt == null) { continue; } containerCpt.setSortingOrder(listCount - i); //设置动画 Tweener tweener = itemTF .DOMove(listCircleVec[i], moveTime) .SetDelay(mPrependTime); if (i.Equals(listCount - 1)) { tweener.OnComplete(rotateAnim); } } }
/// <summary> /// Calculates net volume. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="extrusionCreationData"> /// The IFCExtrusionCreationData. /// </param> /// <param name="element"> /// The element to calculate the value. /// </param> /// <param name="elementType"> /// The element type. /// </param> /// <returns> /// True if the operation succeed, false otherwise. /// </returns> public override bool Calculate(ExporterIFC exporterIFC, IFCExtrusionCreationData extrusionCreationData, Element element, ElementType elementType) { double vol = 0; GeometryElement geomElem = element.get_Geometry(GeometryUtil.GetIFCExportGeometryOptions()); SolidMeshGeometryInfo geomInfo = GeometryUtil.GetSolidMeshGeometry(geomElem, Transform.Identity); if (geomInfo.SolidsCount() > 0) { for (int ii = 0; ii < geomInfo.SolidsCount(); ++ii) { vol += geomInfo.GetSolids()[ii].Volume; } } if (geomInfo.MeshesCount() > 0) { for (int jj = 0; jj < geomInfo.MeshesCount(); ++jj) { Mesh geomMesh = geomInfo.GetMeshes()[jj]; XYZ arbitraryOrig = geomMesh.Vertices[0]; for (int i = 0; i < geomMesh.NumTriangles; ++i) { MeshTriangle meshTri = geomMesh.get_Triangle(i); XYZ v1 = meshTri.get_Vertex(0) - arbitraryOrig; XYZ v2 = meshTri.get_Vertex(1) - arbitraryOrig; XYZ v3 = meshTri.get_Vertex(2) - arbitraryOrig; vol += v1.DotProduct(v2.CrossProduct(v3)) / 6.0f; } } } m_Volume = UnitUtil.ScaleVolume(vol); if (m_Volume < MathUtil.Eps() * MathUtil.Eps() || m_Volume < MathUtil.Eps()) { ParameterUtil.GetDoubleValueFromElementOrSymbol(element, "IfcQtyNetVolume", out m_Volume); if (m_Volume < MathUtil.Eps()) { return(false); } else { return(true); } } else { return(true); } }
/// <summary> /// Calculates net surface area. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="extrusionCreationData">The IFCExtrusionCreationData.</param> /// <param name="element">The element to calculate the value.</param> /// <param name="elementType">The element type.</param> /// <returns>True if the operation succeeded, false otherwise.</returns> public override bool Calculate(ExporterIFC exporterIFC, IFCExtrusionCreationData extrusionCreationData, Element element, ElementType elementType, EntryMap entryMap) { double areaEps = MathUtil.Eps() * MathUtil.Eps(); if ((ParameterUtil.GetDoubleValueFromElementOrSymbol(element, entryMap.RevitParameterName, out m_Area) != null) || (ParameterUtil.GetDoubleValueFromElementOrSymbol(element, entryMap.CompatibleRevitParameterName, out m_Area) != null) || (ParameterUtil.GetDoubleValueFromElementOrSymbol(element, "IfcQtyNetSurfaceArea", out m_Area) != null)) { m_Area = UnitUtil.ScaleArea(m_Area); if (m_Area > areaEps) { return(true); } } double areaSum = 0; SolidMeshGeometryInfo geomInfo = GeometryUtil.GetSolidMeshGeometry(element); if (geomInfo.SolidsCount() > 0) { for (int ii = 0; ii < geomInfo.SolidsCount(); ++ii) { foreach (Face f in geomInfo.GetSolids()[ii].Faces) { areaSum += f.Area; } } } if (geomInfo.MeshesCount() > 0) { for (int jj = 0; jj < geomInfo.MeshesCount(); ++jj) { Mesh geomMesh = geomInfo.GetMeshes()[jj]; XYZ arbitraryOrig = geomMesh.Vertices[0]; for (int ii = 0; ii < geomMesh.NumTriangles; ++ii) { MeshTriangle meshTri = geomMesh.get_Triangle(ii); double a = meshTri.get_Vertex(1).DistanceTo(meshTri.get_Vertex(0)); double b = meshTri.get_Vertex(2).DistanceTo(meshTri.get_Vertex(1)); double c = meshTri.get_Vertex(0).DistanceTo(meshTri.get_Vertex(2)); areaSum += (a + b + c) / 2.0; } } } m_Area = UnitUtil.ScaleArea(areaSum); return(m_Area > areaEps); }
/// <summary> /// Finds parent handle from opening CurveLoop and parent CurveLoops. /// </summary> /// <param name="elementHandles">The parent handles.</param> /// <param name="curveLoops">The parent CurveLoops.</param> /// <param name="openingLoop">The opening CurveLoop.</param> /// <returns>The parent handle.</returns> private static IFCAnyHandle FindParentHandle(IList<IFCAnyHandle> elementHandles, IList<CurveLoop> curveLoops, CurveLoop openingLoop) { // first one is roof handle, others are slabs if (elementHandles.Count != curveLoops.Count + 1) return null; for (int ii = 0; ii < curveLoops.Count; ii++) { if (GeometryUtil.CurveLoopsInside(openingLoop, curveLoops[ii]) || GeometryUtil.CurveLoopsIntersect(openingLoop, curveLoops[ii])) { return elementHandles[ii + 1]; } } return elementHandles[0]; }
/// <summary> /// Gets the triangle list /// </summary> /// <returns></returns> public IEnumerable <Triangle> GetTriangles() { if (getTrianglesFnc != null) { var tris = getTrianglesFnc(); BoundingBox = GeometryUtil.CreateBoundingBox(tris); return(tris ?? new Triangle[] { }); } else { return(new Triangle[] { }); } }
public void TestGetClosestAtomIAtomContainerIAtom() { var atom1 = builder.NewAtom("C"); atom1.Point2D = new Vector2(-1, -1); var atom2 = builder.NewAtom("C"); atom2.Point2D = new Vector2(1, 0); var acont = builder.NewAtomContainer(); acont.Atoms.Add(atom1); acont.Atoms.Add(atom2); Assert.AreEqual(atom2, GeometryUtil.GetClosestAtom(acont, atom1)); Assert.AreEqual(atom1, GeometryUtil.GetClosestAtom(acont, atom2)); }
public void TestGetLength2DIBondHashMap() { var atom1 = builder.NewAtom("C"); atom1.Point2D = new Vector2(-1, -1); var atom2 = builder.NewAtom("C"); atom2.Point2D = new Vector2(1, 0); var bond = builder.NewBond(atom1, atom2); var ac = builder.NewAtomContainer(); ac.Atoms.Add(atom1); ac.Atoms.Add(atom2); Assert.AreEqual(GeometryUtil.GetLength2D(bond), 2.23, 0.01); }
public void Quadratic() { GeometryUtil.QuadraticRoots(1, 0, 0).AssertSequenceApproximates(0); GeometryUtil.QuadraticRoots(0, 1, 0).AssertSequenceApproximates(0); GeometryUtil.QuadraticRoots(0, 0, 1).AssertSequenceApproximates(); GeometryUtil.QuadraticRoots(1, 1, 0).AssertSequenceApproximates(-1, 0); GeometryUtil.QuadraticRoots(0, 1, 1).AssertSequenceApproximates(-1); GeometryUtil.QuadraticRoots(1, 0, 1).AssertSequenceApproximates(); GeometryUtil.QuadraticRoots(1, 0, -1).AssertSequenceApproximates(-1, 1); GeometryUtil.QuadraticRoots(1, 2, 1).AssertSequenceApproximates(-1); GeometryUtil.QuadraticRoots(0, 0, 0).Any().AssertIsTrue(); }
/// <summary> /// 凸頂点か? /// </summary> /// <param name="node"></param> /// <returns></returns> protected bool IsConvex(LinkedListNode <int> node) { // 凸頂点/反射頂点チェック int prevIndex = (node.Previous == null) ? indices.Last.Value : node.Previous.Value; // 一つ前の頂点 int nextIndex = (node.Next == null) ? indices.First.Value : node.Next.Value; // 次の頂点 int nowIndex = node.Value; Vector3 prevVertex = vertices[prevIndex]; Vector3 nextVertex = vertices[nextIndex]; Vector3 nowVertex = vertices[nowIndex]; // 内角が180度以内か? return(GeomUtil.IsAngleLessPI(nowVertex, prevVertex, nextVertex)); }
/// <summary> /// 面積の計算 /// </summary> /// <returns></returns> public float CalcArea() { float area = 0; for (int i = 0; i < vertices.Length; i++) { int next = (i + 1) % vertices.Length; Vector3 v1 = vertices[i]; Vector3 v2 = vertices[next]; area += GeomUtil.Cross2D(v1, v2); } return(area * 0.5f); }
public void OverlapYTest() { var r1 = new Rectangle(100, 200, 300, 400); for (var x = r1.Left - 200; x < r1.Right + 200; x++) { for (var y = r1.Top - 200; y < r1.Bottom + 200; y++) { var r2 = new Rectangle(x, y, 10, 10); var actual = GeometryUtil.OverlapY(r1, r2); var expected = ((r2.Bottom > r1.Top) && (r2.Top < r1.Bottom)); Assert.AreEqual(expected, actual); } } }
public void RemoveNode() { ExitNodeConnectionMode(); Vector2 p2d = MapCreatorLoader.Pointer2d; int id = GeometryUtil.FindClosest(nodes, p2d); if (id < 0) { return; } PathNode removingNode = nodes[id]; RemoveNode(removingNode); }
/// <summary> /// Splits any solid volumes which consist of multiple closed bodies into individual solids (and updates the storage accordingly). /// </summary> public void SplitSolidsList() { IList <SolidInfo> splitSolidsList = new List <SolidInfo>(); foreach (SolidInfo solidInfo in m_SolidInfoList) { Element element = solidInfo.OwnerElement; IList <Solid> splitSolids = GeometryUtil.SplitVolumes(solidInfo.Solid); foreach (Solid splitSolid in splitSolids) { splitSolidsList.Add(new SolidInfo(splitSolid, element)); } } m_SolidInfoList = splitSolidsList; }
public void TestGet2DCenterArrayIAtom() { var container = builder.NewAtomContainer(); var atom1 = builder.NewAtom("C"); atom1.Point2D = new Vector2(1, 1); var atom2 = builder.NewAtom("C"); atom2.Point2D = new Vector2(1, 0); container.Atoms.Add(atom1); container.Atoms.Add(atom2); var p = GeometryUtil.Get2DCenter(container.Atoms); Assert.AreEqual(p.X, 1.0, .1); Assert.AreEqual(p.Y, 0.5, .1); }
public void OutsideDirectionTest() { var rect = new Rectangle(100, 200, 300, 400); for (var x = rect.Left - 200; x < rect.Right + 200; x++) { for (var y = rect.Top - 200; y < rect.Bottom + 200; y++) { var p = new Point(x, y); var expected = GeometryUtil.Sign(GeometryUtil.OutsideDistance(rect, p)); var actual = GeometryUtil.OutsideDirection(rect, p); Assert.AreEqual(expected, actual, $"{x}, {y}"); } } }
/// <summary> /// Returns the planar deviation of this face /// </summary> /// <typeparam name="V"></typeparam> /// <typeparam name="E"></typeparam> /// <typeparam name="F"></typeparam> /// <param name="face"></param> /// <param name="getPosition"></param> /// <returns></returns> public static double GetPlanarity <V, E, F>(this IHeFace <V, E, F> face, Func <V, Vec3d> getPosition) where V : IHeVertex <V, E, F> where E : IHalfedge <V, E, F> where F : IHeFace <V, E, F> { var he0 = face.First; var he1 = he0; var p0 = getPosition(he1.Start); he1 = he1.NextInFace; var p1 = getPosition(he1.Start); he1 = he1.NextInFace; var p2 = getPosition(he1.Start); he1 = he1.NextInFace; // tri case if (ReferenceEquals(he1, he0)) { return(0.0); } // quad case if (ReferenceEquals(he1.NextInFace, he0)) { return(GeometryUtil.LineLineShortestVector(p0, p2, p1, getPosition(he1.Start)).Length); } // general case var he2 = he1; double max = 0.0; do { var p3 = getPosition(he2.Start); max = Math.Max(GeometryUtil.LineLineShortestVector(p0, p2, p1, p3).Length, max); he2 = he2.NextInFace; p0 = p1; p1 = p2; p2 = p3; } while (!ReferenceEquals(he2, he1)); return(max); }
/// <inheritdoc/> public IRenderingElement Generate(IAtomContainer container, RendererModel model) { ElementGroup group = new ElementGroup(); // TODO : put into RendererModel const double ScreenRadius = 2.0; Color RadicalColor = WPF.Media.Colors.Black; // XXX : is this the best option? double AtomRadius = model.GetAtomRadius() / model.GetScale(); double modelRadius = ScreenRadius / model.GetScale(); double modelSpacing = modelRadius * 2.5; var singleElectronsPerAtom = new Dictionary <IAtom, int>(); foreach (var electron in container.SingleElectrons) { IAtom atom = electron.Atom; if (!singleElectronsPerAtom.ContainsKey(atom)) { singleElectronsPerAtom[atom] = 0; } Vector2 point = atom.Point2D.Value; int align = GeometryUtil.GetBestAlignmentForLabelXY(container, atom); var center = ToPoint(point); if (align == 1) { center.X += AtomRadius * 4 + singleElectronsPerAtom[atom] * modelSpacing; } else if (align == -1) { center.X -= AtomRadius * 4 + singleElectronsPerAtom[atom] * modelSpacing; } else if (align == 2) { center.Y += AtomRadius * 4 + singleElectronsPerAtom[atom] * modelSpacing; } else if (align == -2) { center.Y -= AtomRadius * 4 + singleElectronsPerAtom[atom] * modelSpacing; } singleElectronsPerAtom[atom] = singleElectronsPerAtom[atom] + 1; group.Add(new OvalElement(center, modelRadius, true, RadicalColor)); } return(group); }
private void RepositionWindowToNode() { if (ToolWindow == null || SelectedNodeId == 0) { return; } Vector3 nodePos = Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position; // Cast to screen and center the window on node GeometryUtil.WorldToScreenPoint(nodePos, out Vector3 screenPixelPos); Vector2 guiPosition = UIScaler.ScreenPointToGuiPoint(screenPixelPos); ToolWindow.absolutePosition = guiPosition - new Vector2(ToolWindow.size.x * 0.5f, ToolWindow.size.y * 0.5f); }
/// <summary> /// Calculates the normal as the sum of triangle area gradients /// </summary> /// <returns></returns> private Vec3d ComputeNormal(IReadOnlyList <IBody> bodies) { var p = bodies[_handle].Position; var sum = new Vec3d(); var n = _neighbors.Count; for (int i = 0; i < n; i++) { int j = (i + 1) % n; var p0 = bodies[_neighbors[i]].Position; var p1 = bodies[_neighbors[j]].Position; sum += GeometryUtil.GetTriAreaGradient(p, p0, p1); } return(sum); }
public static NFP cleanPolygon2(NFP polygon) { var p = svgToClipper(polygon); // remove self-intersections and find the biggest polygon that's left var simple = ClipperLib.Clipper.SimplifyPolygon(p.ToList(), ClipperLib.PolyFillType.pftNonZero); if (simple == null || simple.Count == 0) { return(null); } var biggest = simple[0]; var biggestarea = Math.Abs(ClipperLib.Clipper.Area(biggest)); for (var i = 1; i < simple.Count; i++) { var area = Math.Abs(ClipperLib.Clipper.Area(simple[i])); if (area > biggestarea) { biggest = simple[i]; biggestarea = area; } } // clean up singularities, coincident points and edges var clean = ClipperLib.Clipper.CleanPolygon(biggest, 0.01 * Config.curveTolerance * Config.clipperScale); if (clean == null || clean.Count == 0) { return(null); } var cleaned = clipperToSvg(clean); // remove duplicate endpoints var start = cleaned[0]; var end = cleaned[cleaned.length - 1]; if (start == end || (GeometryUtil._almostEqual(start.x, end.x) && GeometryUtil._almostEqual(start.y, end.y))) { cleaned.Points = cleaned.Points.Take(cleaned.Points.Count() - 1).ToArray(); } return(cleaned); }