void IFeedBack.PaintTo3D(IPaintTo3D paintTo3D) { paintTo3D.UseZBuffer(true); paintTo3D.Blending(true); paintTo3D.SetColor(color); GeoPoint[] pnts = new GeoPoint[4]; pnts[0] = pln.ToGlobal(new GeoPoint2D(-width / 2, -height / 2)); pnts[1] = pln.ToGlobal(new GeoPoint2D(width / 2, -height / 2)); pnts[2] = pln.ToGlobal(new GeoPoint2D(width / 2, height / 2)); pnts[3] = pln.ToGlobal(new GeoPoint2D(-width / 2, height / 2)); GeoVector[] norm = new GeoVector[4]; norm[0] = pln.Normal; norm[1] = pln.Normal; norm[2] = pln.Normal; norm[3] = pln.Normal; int[] ind = new int[6]; ind[0] = 0; ind[1] = 1; ind[2] = 2; ind[3] = 0; ind[4] = 2; ind[5] = 3; paintTo3D.Triangle(pnts, norm, ind); paintTo3D.Blending(false); paintTo3D.UseZBuffer(true); }
public ParametricsDistanceActionOld(Edge fromHere, Edge toHere, Line feedback, Plane plane, IFrame frame) { distanceFromHere = fromHere; distanceToHere = toHere; offsetStartPoint = feedback.StartPoint; offsetFeedBack = frame.ActiveView.Projection.MakeArrow(feedback.StartPoint, feedback.EndPoint, plane, Projection.ArrowMode.circleArrow); feedbackPlane = plane; originalOffset = feedback.EndPoint - feedback.StartPoint; shell = fromHere.PrimaryFace.Owner as Shell; facesToMove = new List <Face>(); facesToKeep = new List <Face>(); if (toHere != null) { if (!toHere.PrimaryFace.Surface.IsExtruded(originalOffset)) { facesToMove.Add(toHere.PrimaryFace); } if (!toHere.SecondaryFace.Surface.IsExtruded(originalOffset)) { facesToMove.Add(toHere.SecondaryFace); } facesToMoveIsFixed = true; } if (fromHere != null) { if (!fromHere.PrimaryFace.Surface.IsExtruded(originalOffset)) { facesToKeep.Add(fromHere.PrimaryFace); } if (!fromHere.SecondaryFace.Surface.IsExtruded(originalOffset)) { facesToKeep.Add(fromHere.SecondaryFace); } } }
private void Point1(GeoPoint p) { // elliPoint1 = p; GeoVector dir = p - ellipse.Center; if (!dir.IsNullVector()) { // dir1 als senkrechte zu dir in der ActiveDrawingPlane erzeugen: GeoVector dir1 = ellipse.Plane.Normal ^ dir; dir1.Norm(); dir1 = ellipse.MinorRadius * dir1; // nun daraus neue ellipse, in der Orientierung dir ist der Winkel enthalten ellipse.SetEllipseArcCenterAxis(ellipse.Center, dir, dir1, ellipse.StartParameter, ellipse.SweepParameter); // für die Mauseingabe des 2.Radius wird hier die Referenzlinie ellipse.Center,p angegeben elliMinRad.SetDistanceFromLine(ellipse.Center, p); } /* * if (!dir.IsNullVector()) * { * ellipse.MajorRadius = Geometry.dist(ellipse.Center,p); * // dir1 als senkrechte zu dir in der ActiveDrawingPlane erzeugen: * GeoVector dir1 = base.ActiveDrawingPlane.Normal ^ dir; * // nun daraus neue ellipse.plane, in der Orientierung dir ist der Winkel enthalten * ellipse.Plane = new Plane(ellipse.Center,dir,dir1); * // für die Mauseingabe des 2.Radius wird hier die Referenzlinie ellipse.Center,p angegeben * elliMinRad.SetDistanceFromLine(ellipse.Center,p); * elliAngle = new Angle(ActiveDrawingPlane.DirectionX,dir); * } */ }
} // for JSON public void SetObjectData(IJsonReadData data) { location = data.GetProperty <GeoPoint>("Location"); xAxis = data.GetProperty <GeoVector>("XAxis"); yAxis = data.GetProperty <GeoVector>("YAxis"); zAxis = data.GetProperty <GeoVector>("ZAxis"); }
public PlaneSurface(GeoPoint location, GeoVector uDirection, GeoVector vDirection) { GeoVector zDirection = uDirection ^ vDirection; fromUnitPlane = new ModOp(uDirection, vDirection, zDirection, location); toUnitPlane = fromUnitPlane.GetInverse(); }
public override void DerivationAt(GeoPoint2D uv, out GeoPoint location, out GeoVector du, out GeoVector dv) { periodicSurface.DerivationAt(toPeriodic(uv), out GeoPoint ploc, out GeoVector pdu, out GeoVector pdv); location = ploc; double l = uv.x * uv.x + uv.y * uv.y; double sl = Math.Sqrt(l); double dsdu, dsdv, dtdu, dtdv; if (l > 0) { dsdu = toPeriodicBounds[0, 1] * uv.x / sl - toPeriodicBounds[0, 0] * uv.y / l; dsdv = toPeriodicBounds[0, 1] * uv.y / sl + toPeriodicBounds[0, 0] * uv.x / l; dtdu = toPeriodicBounds[1, 1] * uv.x / sl - toPeriodicBounds[1, 0] * uv.y / l; dtdv = toPeriodicBounds[1, 1] * uv.y / sl + toPeriodicBounds[1, 0] * uv.x / l; du = dsdu * pdu + dtdu * pdv; dv = dsdv * pdu + dtdv * pdv; } else { // toPeriodic at (0,0) did return toPeriodicBounds * (0,0), but we also need toPeriodicBounds * (pi/2,0), because at (0,0) there is the pole GeoPoint2D pole1 = toPeriodicBounds * new GeoPoint2D(Math.PI / 2.0, 0.0); periodicSurface.DerivationAt(pole1, out GeoPoint ploc1, out GeoVector pdu1, out GeoVector pdv1); dsdu = toPeriodicBounds[0, 1] - toPeriodicBounds[0, 0]; dsdv = toPeriodicBounds[0, 1] + toPeriodicBounds[0, 0]; dtdu = toPeriodicBounds[1, 1] - toPeriodicBounds[1, 0]; dtdv = toPeriodicBounds[1, 1] + toPeriodicBounds[1, 0]; du = dsdu * pdu + dtdu * pdv; dv = dsdv * pdu1 + dtdv * pdv1; } }
public override ISurface GetCanonicalForm(double precision, BoundingRect?bounds) { ICurve testWith = basisCurve; if (basisCurve is BSpline bsp) { if (bsp.GetSimpleCurve(precision, out ICurve simpleCurve)) { testWith = simpleCurve; } } if (testWith is Ellipse elli && elli.IsCircle) { double r = (elli).Radius; if (Precision.SameDirection(elli.Plane.Normal, this.direction, false)) { CylindricalSurface cs = new CylindricalSurface(elli.Center, elli.MajorAxis, elli.MinorAxis, elli.Plane.Normal); GeoVector n1 = this.GetNormal(this.PositionOf(elli.StartPoint)); GeoVector n2 = cs.GetNormal(cs.PositionOf(elli.StartPoint)); if (n1 * n2 < 0) { cs.ReverseOrientation(); } return(cs); } }
private bool Radius1(double length) { if (length > Precision.eps) { coneRadius1 = length; coneDirX = coneRadius1 * coneDirX.Normalized; cone = Make3D.MakeCone(coneStartPoint, coneDirX, coneDirZ, coneRadius1, coneRadius2); if (cone == null) { return(false); } cone.CopyAttributes(base.ActiveObject); if (startPointInput.Fixed && !endPointInput.Fixed) { // er will also einen Kegel senkrecht auf der drawingplane endPointInput.Optional = true; height.Optional = false; height.ForwardMouseInputTo = new object[0]; // den forward abschalten coneDirX = coneRadius1 * base.ActiveDrawingPlane.DirectionX; coneDirZ = coneHeight * (base.ActiveDrawingPlane.DirectionX ^ base.ActiveDrawingPlane.DirectionY); } base.ActiveObject = cone; return(true); } return(false); }
private void SetPositionPoint(GeoPoint p) { GeoVector move = p - block.RefPoint; ModOp m = ModOp.Translate(move); block.Modify(m); }
protected SphericalSurfaceNP(SerializationInfo info, StreamingContext context) { center = (GeoPoint)info.GetValue("Center", typeof(GeoPoint)); xAxis = (GeoVector)info.GetValue("XAxis", typeof(GeoVector)); yAxis = (GeoVector)info.GetValue("YAxis", typeof(GeoVector)); zAxis = (GeoVector)info.GetValue("ZAxis", typeof(GeoVector)); }
private void EndPoint(GeoPoint p) { if (!Precision.IsEqual(p, coneStartPoint)) { coneDirZ = new GeoVector(coneStartPoint, p); if (height.Fixed) // die schon bestimmte Höhe benutzen! { coneDirZ = coneHeight * coneDirZ.Normalized; } else { coneHeight = coneDirZ.Length; } // coneDirX muss irgendwie senkrecht auf coneDirZ stehen. Hier: Hilfsvektor definieren mit der kleinsten Komponente von coneDirZ GeoVector vT = new GeoVector(1, 0, 0); // x am kleinsten if (Math.Abs(coneDirZ.y) < Math.Abs(coneDirZ.x)) { vT = new GeoVector(0, 1, 0); // y am kleinsten } if ((Math.Abs(coneDirZ.x) > Math.Abs(coneDirZ.z)) && (Math.Abs(coneDirZ.y) > Math.Abs(coneDirZ.z))) { vT = new GeoVector(0, 0, 1); // z am kleinsten } coneDirX = coneRadius1 * (vT ^ coneDirZ).Normalized; cone = Make3D.MakeCone(coneStartPoint, coneDirX, coneDirZ, coneRadius1, coneRadius2); cone.CopyAttributes(base.ActiveObject); base.ActiveObject = cone; } }
} // for JSON public void SetObjectData(IJsonReadData data) { center = data.GetProperty <GeoPoint>("Center"); xAxis = data.GetProperty <GeoVector>("XAxis"); yAxis = data.GetProperty <GeoVector>("YAxis"); zAxis = data.GetProperty <GeoVector>("ZAxis"); }
public override void Derivation2At(GeoPoint2D uv, out GeoPoint p, out GeoVector du, out GeoVector dv, out GeoVector duu, out GeoVector dvv, out GeoVector duv) { // from maxima and common sub expression double u = uv.x; double v = uv.y; double r = xAxis.Length; double sc16 = exp52(sqr(v) + sqr(u)); double sc15 = exp32(sqr(v) + sqr(u)); double sc14 = sqr(v) + sqr(u) + sqr(r); double sc13 = 2.0 * Math.Atan2(r, Math.Sqrt(sqr(v) + sqr(u))); double sc12 = sqr(sc14); double sc11 = Math.Sin(sc13); double sc10 = Math.Cos(sc13); double sc9 = (sqr(v) + sqr(u)) * sc12; double sc8 = Math.Sqrt(sqr(v) + sqr(u)) * sc14; double sc7 = sc15 * sc14; double sc6 = Math.Sqrt(sqr(v) + sqr(u)) * sc12; double sc5 = 4.0 * r * sc10; double sc4 = 2.0 * r * sc10; double sc3 = sc4 * u; double sc2 = 4.0 * sqr(r) * sc11; GeoVector sc1 = (-(sc4 * zAxis)) / sc8; p = center + sc11 * zAxis + v * yAxis / Math.Sqrt(sqr(v) + sqr(u)) + u * xAxis / Math.Sqrt(sqr(v) + sqr(u)); du = (-(sc3 * zAxis)) / sc8 - u * v * yAxis / sc15 + xAxis / Math.Sqrt(sqr(v) + sqr(u)) - sqr(u) * xAxis / sc15; dv = (-(sc4 * v * zAxis)) / sc8 + yAxis / Math.Sqrt(sqr(v) + sqr(u)) - sqr(v) * yAxis / sc15 - u * v * xAxis / sc15; duu = sc1 + sc4 * sqr(u) * zAxis / sc7 + sc5 * sqr(u) * zAxis / sc6 - sc2 * sqr(u) * zAxis / sc9 - v * yAxis / sc15 + 3.0 * sqr(u) * v * yAxis / sc16 - 3.0 * u * xAxis / sc15 + 3.0 * cube(u) * xAxis / sc16; dvv = sc1 + sc4 * sqr(v) * zAxis / sc7 + sc5 * sqr(v) * zAxis / sc6 - sc2 * sqr(v) * zAxis / sc9 - 3.0 * v * yAxis / sc15 + 3.0 * cube(v) * yAxis / sc16 - u * xAxis / sc15 + 3.0 * u * sqr(v) * xAxis / sc16; duv = sc3 * v * zAxis / sc7 + sc5 * u * v * zAxis / sc6 - sc2 * u * v * zAxis / sc9 - u * yAxis / sc15 + 3.0 * u * sqr(v) * yAxis / sc16 - v * xAxis / sc15 + 3.0 * sqr(u) * v * xAxis / sc16; }
Polynom implicitPolynomial; // will be calculated when needed public SphericalSurfaceNP(GeoPoint center, GeoVector xAxis, GeoVector yAxis, GeoVector zAxis) { this.center = center; this.xAxis = xAxis; this.yAxis = yAxis; this.zAxis = zAxis; }
static public void SpaceDown(GeoObjectList gl, Projection projection, Project pr) { using (pr.Undo.UndoFrame) { IGeoObject[] geoArray = new IGeoObject[gl.Count]; for (int i = 0; i < gl.Count; ++i) // umkopieren auf ein Array, um den Sort machen zu können { geoArray[i] = gl[i]; } // hier nun Sort, der Compare steht oben als lokal class und braucht die Parameter: Sort nach y = false und pm Array.Sort(geoArray, 0, geoArray.Length, new CompareGeoObject(false, projection)); // die Rechtecke des ersten und letzten Objeks für die Gesamtausdehnung BoundingRect reStart = IGeoObjectImpl.GetExtent(geoArray[0], projection, false); BoundingRect reEnd = IGeoObjectImpl.GetExtent(geoArray[geoArray.Length - 1], projection, false); double reTotal = reEnd.Top - reStart.Bottom; // Gesamtausdehnung double distRe = 0; for (int i = 0; i < geoArray.Length; ++i) // Summe der Ausdehnung der Einzelnen: { BoundingRect re = IGeoObjectImpl.GetExtent(geoArray[i], projection, false); distRe = distRe + re.Height; } double space = (reTotal - distRe) / (geoArray.Length - 1); // Gesamt - Summe Einzelne / Zwischenräume double pos = reStart.Top; for (int i = 1; i < geoArray.Length - 1; ++i) // vom zweiten bis zum vorletzten, die Äußeren bleiben unverändert { BoundingRect re = IGeoObjectImpl.GetExtent(geoArray[i], projection, false); GeoVector2D trans2D = new GeoVector2D(0, pos + space - re.Bottom); pos = pos + space + re.Height; // pos hochzählen auf den oberen Rand des aktuellen GeoVector trans = projection.DrawingPlane.ToGlobal(trans2D); ModOp m = ModOp.Translate(trans); geoArray[i].Modify(m); } } }
private bool DirCurve(CurveInput sender, ICurve[] Curves, bool up) { objectPoint = base.CurrentMousePosition; if (up) { if (Curves.Length == 0) { sender.SetCurves(Curves, null); // ...die werden jetzt im ControlCenter dargestellt (nur bei up) } else { sender.SetCurves(Curves, Curves[0]); } } if (Curves.Length > 0) { dirCurve = Curves[0]; selectDir(); return(true); } using (Frame.Project.Undo.ContextFrame(this)) { if (vectorProperty != null) { vectorProperty.SetGeoVector(cancelVector); } } actualVector = cancelVector; return(false); }
private void MakeBlock(int horLeft, int horRight, int verDown, int verUp, double distX, double distY) { // läuft asynchron backgroundBlock = Block.Construct(); for (int i = -horLeft; i <= horRight; ++i) { if (i != 0) // i=0 ist das Original, soll nicht verdoppelt werden! { GeoObjectList li = new GeoObjectList(); // für jede Kopie ein Clone machen li = originals.CloneObjects(); // AbstandX * Kopienwinkel: GeoVector vect = (i * distX) * dirV; ModOp m = ModOp.Translate(vect); li.Modify(m); backgroundBlock.Add(li); } for (int j = -verDown; j <= verUp; ++j) { if (j != 0) // J=0 ist das Original, soll nicht verdoppelt werden! { GeoObjectList liV = new GeoObjectList(); // für jede Kopie ein Clone machen liV = originals.CloneObjects(); // der senkrechte Winkel auf Kopienwinkel dirV GeoVector dirV_Vert = base.ActiveDrawingPlane.Normal ^ dirV; GeoVector vectV = (i * distX) * dirV + (j * distY) * dirV_Vert; ModOp m = ModOp.Translate(vectV); liV.Modify(m); backgroundBlock.Add(liV); } } } }
private GeoVector OnGetDirection(GeoVectorProperty sender) { GeoVector res = line.StartDirection; // res.Norm(); warum? Wenn Start- und Endpunkt identisch sind gibts eine Exception, die nicht gefangen wird return(res); }
/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.GetLineIntersection (GeoPoint, GeoVector)"/> /// </summary> /// <param name="startPoint"></param> /// <param name="direction"></param> /// <returns></returns> public override GeoPoint2D[] GetLineIntersection(GeoPoint startPoint, GeoVector direction) { if (Precision.SameDirection(this.direction, direction, false)) { // Linie parallel zur Auszugsrichtung return(new GeoPoint2D[] { }); } else { // Die Ebene durch Auszugsrichtung und Schnittgerade und Schnittlinien-Startpunkt, schneide // die Basiskurve mit der Ebene. Die Schnittpunkt liefern die richtigen u-Werte // die v-Werte finden wir vom u-Wert auf der basisCurve ausgehen in Auszugsrichtung und mit der Schnittlinie schneiden Plane pln = new Plane(startPoint, direction, this.direction); double[] u = basisCurve.GetPlaneIntersection(pln); GeoPoint2D[] res = new GeoPoint2D[u.Length]; pln = new Plane(startPoint, direction, direction ^ this.direction); // Ebene senkrech zur Auszugsrichtung durch den Linienpunkt for (int i = 0; i < u.Length; ++i) { GeoPoint ip = pln.Intersect(basisCurve.PointAt(u[i]), this.direction); GeoPoint vbasis = basisCurve.PointAt(u[i]); //res[i] = new GeoPoint2D((u[i] - curveStartParameter) / (curveEndParameter - curveStartParameter), Geometry.LinePar(startPoint, this.direction, ip)); res[i] = new GeoPoint2D((u[i] * (curveEndParameter - curveStartParameter) + curveStartParameter), Geometry.LinePar(vbasis, this.direction, ip)); } return(res); } }
public GeneralLengthAction(LengthProperty lengthProperty, GeoPoint linePoint, GeoVector lineDirection) { this.lengthProperty = lengthProperty; this.linePoint = linePoint; this.lineDirection = lineDirection; mode = Mode.fromLine; }
public CylindricalSurfaceNP(GeoPoint center, double radius, GeoVector axis, bool outwardOriented, ICurve[] orientedCurves) { #if DEBUG id = ++idcnt; #endif double minpos = double.MaxValue; double maxpos = double.MinValue; for (int i = 0; i < orientedCurves.Length; i++) { double[] extr = orientedCurves[i].GetExtrema(axis); double lp; for (int j = 0; j < extr.Length; j++) { lp = Geometry.LinePar(center, axis, orientedCurves[i].PointAt(extr[j])); minpos = Math.Min(minpos, lp); maxpos = Math.Max(maxpos, lp); } lp = Geometry.LinePar(center, axis, orientedCurves[i].StartPoint); minpos = Math.Min(minpos, lp); maxpos = Math.Max(maxpos, lp); lp = Geometry.LinePar(center, axis, orientedCurves[i].EndPoint); minpos = Math.Min(minpos, lp); maxpos = Math.Max(maxpos, lp); } location = Geometry.LinePos(center, axis, minpos); axis.ArbitraryNormals(out xAxis, out yAxis); if (!outwardOriented) { xAxis = -xAxis; } zAxis = axis; xAxis.Length = radius; yAxis.Length = radius; zAxis.Length = (maxpos - minpos) * axis.Length; }
private GeoVector OnGetEndAngle(GeoVectorProperty sender) { GeoVector dir = dimension.GetPoint(2) - dimension.GetPoint(0); dir.Norm(); return(dir); }
protected CylindricalSurfaceNP(SerializationInfo info, StreamingContext context) { location = (GeoPoint)info.GetValue("Location", typeof(GeoPoint)); xAxis = (GeoVector)info.GetValue("XAxis", typeof(GeoVector)); yAxis = (GeoVector)info.GetValue("YAxis", typeof(GeoVector)); zAxis = (GeoVector)info.GetValue("ZAxis", typeof(GeoVector)); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// zooms into the unit on the given coordinates until the target type is rendered /// <para>returns value at the center of the zoomed point</para> /// </summary> /// <param name="cameraGeoVector"></param> /// <param name="targetZoomLevel"></param> /// <returns></returns> internal void ZoomTo(GeoVector cameraGeoVector, int targetZoomLevel) { if (targetZoomLevel > cfg.MaxZoomLevel || targetZoomLevel < 0) { Debug.Log("Can't zoom any further"); } else if (targetZoomLevel == ZoomLevel) { //nothing } else if (targetZoomLevel == ZoomLevel + 1) { ExpandAround(cameraGeoVector); } else if (targetZoomLevel > ZoomLevel) { var idx = GetLocalUnitIndex(cameraGeoVector); GetUnit(idx.x, idx.y).ZoomTo(cameraGeoVector, targetZoomLevel); } else { //hide children //HideRendererDownward(); } }
public int WriteAxis1Placement3d(GeoPoint location, GeoVector normal) { int nl = (location as IExportStep).Export(this, false); int n = (normal.Normalized as IExportStep).Export(this, false); return(WriteDefinition("AXIS1_PLACEMENT('',#" + nl.ToString() + ",#" + n.ToString() + ");")); }
private void InsertGeoVector() { string prefix = StringTable.GetString("NamedValues.NewGeoVector.Prefix"); string Name = GetUniqueName(prefix); namedValues[Name] = new GeoVector(0.0, 0.0, 0.0); ReflectNewEntry(Name); }
internal static Plane FromPointsSVD(GeoPoint[] Points, out double MaxDistance, out bool isLinear) { isLinear = false; MaxDistance = double.MaxValue; GeoPoint centroid = new GeoPoint(Points); Matrix m = DenseMatrix.OfArray(new double[Points.Length, 3]); for (int i = 0; i < Points.Length; i++) { GeoVector v = Points[i] - centroid; m[i, 0] = v.x; m[i, 1] = v.y; m[i, 2] = v.z; } try { Svd <double> svd = m.Svd(); GeoVector normal = new GeoVector(svd.U[0, 0], svd.U[0, 1], svd.U[0, 2]); return(new Plane(centroid, normal)); } catch { return(Plane.XYPlane); } }
public override GeoVector DirectionAt(double Position) { if (Math.Abs(startPoint.x - endPoint.x) < Math.Abs(startPoint.y - endPoint.y)) { // also vertikal, da nur horizontal oder vertikal vorkommt GeoVector dir = surface.VDirection(startPoint + Position * (endPoint - startPoint)); if (startPoint.y < endPoint.y) { return(dir); } else { return(-dir); } } else { // horizontal GeoVector dir = surface.UDirection(startPoint + Position * (endPoint - startPoint)); if (startPoint.x < endPoint.x) { return(dir); } else { return(-dir); } } }
public void Add(GeoPoint from, GeoVector dir, double size, System.Drawing.Color color) { Line l = Line.Construct(); l.StartPoint = from; l.EndPoint = from + size * dir.Normalized; ColorDef cd = new ColorDef(color.Name, color); l.ColorDef = cd; toShow.Add(l); GeoVector perp = dir ^ GeoVector.ZAxis; if (Precision.IsNullVector(perp)) { perp = dir ^ GeoVector.XAxis; } GeoPoint p1 = from + size * 0.9 * dir.Normalized + size * 0.1 * perp.Normalized; GeoPoint p2 = from + size * 0.9 * dir.Normalized - size * 0.1 * perp.Normalized; Line l1 = Line.Construct(); l1.StartPoint = l.EndPoint; l1.EndPoint = p1; l1.ColorDef = cd; toShow.Add(l1); Line l2 = Line.Construct(); l2.StartPoint = l.EndPoint; l2.EndPoint = p2; l2.ColorDef = cd; toShow.Add(l2); }
public static bool SameNotOppositeDirection(GeoVector v1, GeoVector v2) { GeoVector cross = v1 ^ v2; double cl = cross.Length; double f; if (Math.Abs(v2.x) > Math.Abs(v2.y)) { if (Math.Abs(v2.x) > Math.Abs(v2.z)) { f = v1.x / v2.x; } else { f = v1.z / v2.z; } } else { if (Math.Abs(v2.y) > Math.Abs(v2.z)) { f = v1.y / v2.y; } else { f = v1.z / v2.z; } } return((f > 0.0) && (cl / (v1.Length * v2.Length) < epsa)); }