Skip to content
This repository has been archived by the owner on Oct 11, 2023. It is now read-only.

Commit

Permalink
[2022/04/19]
Browse files Browse the repository at this point in the history
* Added more GTE classes. See the Samples for GTE classes
* Deleted the SplineVertex class. Now the Spline constructors take two lists: a Vector3 to define the controls points and a double array to define the weights.
* PolygonMesh entities are now capable to handle closed in U and/or V surfaces.
  • Loading branch information
haplokuon committed Apr 19, 2022
1 parent efb6f22 commit 5144bff
Show file tree
Hide file tree
Showing 42 changed files with 6,849 additions and 1,092 deletions.
712 changes: 624 additions & 88 deletions TestDxfDocument/Program.cs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions doc/Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Change history

### [2022/04/19]
* Added more GTE classes. See the Samples for GTE classes
* Deleted the SplineVertex class. Now the Spline constructors take two lists: a Vector3 to define the controls points and a double array to define the weights.
* PolygonMesh entities are now capable to handle closed in U and/or V surfaces.

### [2022/04/10]
* Added CalculateTangent for Quadratic and Cubic Bezier curves.
* Added PolygonMesh entity. See PolygonMesh() sample.
Expand Down
Binary file removed doc/netDxf Documentation.chm
Binary file not shown.
2 changes: 0 additions & 2 deletions netDxf.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
Expand All @@ -17,7 +16,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{6B14C525-B
ProjectSection(SolutionItems) = preProject
doc\Changelog.txt = doc\Changelog.txt
LICENSE = LICENSE
doc\netDxf Documentation.chm = doc\netDxf Documentation.chm
EndProjectSection
EndProject
Global
Expand Down
36 changes: 16 additions & 20 deletions netDxf/DxfDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,26 +468,6 @@ public DrawingEntities Entities

#endregion

#region public entity methods

/// <summary>
/// Gets a DXF object by its handle.
/// </summary>
/// <param name="objectHandle">DxfObject handle.</param>
/// <returns>The DxfObject that has the provided handle, null otherwise.</returns>
public DxfObject GetObjectByHandle(string objectHandle)
{
if (string.IsNullOrEmpty(objectHandle))
{
return null;
}

this.AddedObjects.TryGetValue(objectHandle, out DxfObject o);
return o;
}

#endregion

#region public methods

/// <summary>
Expand Down Expand Up @@ -776,6 +756,22 @@ public static DxfVersion CheckDxfFileVersion(Stream stream, out bool isBinary)
return StringEnum<DxfVersion>.Parse(value, StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Gets a DXF object by its handle.
/// </summary>
/// <param name="objectHandle">DxfObject handle.</param>
/// <returns>The DxfObject that has the provided handle, null otherwise.</returns>
public DxfObject GetObjectByHandle(string objectHandle)
{
if (string.IsNullOrEmpty(objectHandle))
{
return null;
}

this.AddedObjects.TryGetValue(objectHandle, out DxfObject o);
return o;
}

#endregion

#region internal methods
Expand Down
3 changes: 1 addition & 2 deletions netDxf/DxfObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected virtual void OnXDataRemoveAppRegEvent(ApplicationRegistry item)
private string codename;
private string handle;
private DxfObject owner;
private XDataDictionary xData;
private readonly XDataDictionary xData;

#endregion

Expand Down Expand Up @@ -125,7 +125,6 @@ public DxfObject Owner
public XDataDictionary XData
{
get { return this.xData; }
internal set { this.xData = value; }
}

#endregion
Expand Down
4 changes: 2 additions & 2 deletions netDxf/Entities/Hatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ private static Polyline2D ProcessLwPolyline(Polyline2D polyline2D, Vector3 norma

private static Spline ProcessSpline(Spline spline, Matrix3 trans, Vector3 pos)
{
foreach (SplineVertex vertex in spline.ControlPoints)
for (int i = 0; i < spline.ControlPoints.Length; i++)
{
vertex.Position = trans * vertex.Position + pos;
spline.ControlPoints[i] = trans * spline.ControlPoints[i] + pos;
}
spline.Normal = trans * spline.Normal;
return spline;
Expand Down
20 changes: 12 additions & 8 deletions netDxf/Entities/HatchBoundaryPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -592,18 +592,18 @@ public Spline(EntityObject entity)
this.Degree = spline.Degree;
this.IsRational = true;
this.IsPeriodic = spline.IsClosedPeriodic;
if (spline.ControlPoints.Count == 0)
if (spline.ControlPoints.Length == 0)
{
throw new ArgumentException("The HatchBoundaryPath spline edge requires a spline entity with control points.", nameof(entity));
}

Matrix3 trans = MathHelper.ArbitraryAxis(entity.Normal).Transpose();

this.ControlPoints = new Vector3[spline.ControlPoints.Count];
for (int i = 0; i < spline.ControlPoints.Count; i++)
this.ControlPoints = new Vector3[spline.ControlPoints.Length];
for (int i = 0; i < spline.ControlPoints.Length; i++)
{
Vector3 point = trans * spline.ControlPoints[i].Position;
this.ControlPoints[i] = new Vector3(point.X, point.Y, spline.ControlPoints[i].Weight);
Vector3 point = trans * spline.ControlPoints[i];
this.ControlPoints[i] = new Vector3(point.X, point.Y, spline.Weights[i]);
}

this.Knots = new double[spline.Knots.Length];
Expand All @@ -628,12 +628,16 @@ public static Spline ConvertFrom(EntityObject entity)
/// <returns>An <see cref="EntityObject">entity</see> equivalent to the actual edge.</returns>
public override EntityObject ConvertTo()
{
List<SplineVertex> ctrl = new List<SplineVertex>(this.ControlPoints.Length);
List<Vector3> ctrl = new List<Vector3>();
List<double> weights = new List<double>();
List<double> knots = new List<double>(this.Knots);

foreach (Vector3 point in this.ControlPoints)
{
ctrl.Add(new SplineVertex(point.X, point.Y, 0.0, point.Z));
ctrl.Add(new Vector3(point.X, point.Y, 0.0));
weights.Add(point.Z);
}
return new Entities.Spline(ctrl, new List<double>(this.Knots), this.Degree, this.IsPeriodic);
return new Entities.Spline(ctrl, weights, knots, this.Degree, this.IsPeriodic);
}

/// <summary>
Expand Down
119 changes: 106 additions & 13 deletions netDxf/Entities/PolygonMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,35 @@ public Vector3[] Vertexes
get { return this.vertexes; }
}

/// <summary>
/// Set a PolygonMesh vertex by its indexes.
/// </summary>
/// <param name="i0">Index of the vertex in the U direction.</param>
/// <param name="i1">Index of the vertex in the V direction.</param>
/// <param name="vertex">A Vector3.</param>
public void SetVertex(int i0, int i1, Vector3 vertex)
{
if (0 <= i0 && i0 < this.u && 0 <= i1 && i1 < this.v)
{
this.vertexes[i0 + this.u * i1] = vertex;
}
}

/// <summary>
/// Gets a PolygonMesh vertex by its indexes.
/// </summary>
/// <param name="i0">Index of the vertex in the U direction.</param>
/// <param name="i1">Index of the vertex in the V direction.</param>
public Vector3 GetVertex(int i0, int i1)
{
if (0 <= i0 && i0 < this.u && 0 <= i1 && i1 < this.v)
{
return this.vertexes[i0 + this.u * i1];
}

return this.vertexes[0];
}

/// <summary>
/// Gets the number of vertexes along the U direction (local X axis).
/// </summary>
Expand Down Expand Up @@ -327,24 +356,88 @@ public List<Vector3> MeshVertexes(int precisionU, int precisionV)
return new List<Vector3>(this.vertexes);
}

GTE.BasisFunctionInput bfU = new GTE.BasisFunctionInput(this.u, degree);
GTE.BasisFunctionInput bfV = new GTE.BasisFunctionInput(this.v, degree);
List<Vector3> controlsUV = new List<Vector3>();
int numU = this.u;
int numV = this.v;

// duplicate vertexes to handle periodic BSpline surfaces
if (this.IsClosedInU)
{
numU += degree;
for (int i = 0; i < this.v; i++)
{
for (int j = 0; j < this.u + degree; j++)
{
if (j < this.u)
{
controlsUV.Add(this.vertexes[i * this.u + j]);
}
else
{
for (int k = 0; k < degree; k++, j++)
{
controlsUV.Add(this.vertexes[i * this.u + k]);
}
}
}
}
if (this.IsClosedInV)
{
numV += degree;
for (int i = 0; i < degree; i++)
{
for (int j = 0; j < numU; j++)
{
controlsUV.Add(controlsUV[i * numU + j]);
}
}
}
}
else if (this.IsClosedInV)
{
controlsUV.AddRange(this.vertexes);
numV += degree;
for (int i = 0; i < degree; i++)
{
for (int j = 0; j < this.u; j++)
{
controlsUV.Add(this.vertexes[i * this.u + j]);
}
}
}
else
{
controlsUV.AddRange(this.vertexes);
}

GTE.BasisFunctionInput bfU = new GTE.BasisFunctionInput(numU, degree);
GTE.BasisFunctionInput bfV = new GTE.BasisFunctionInput(numV, degree);

GTE.BSplineSurface surface = new GTE.BSplineSurface(new []{bfU, bfV}, this.vertexes);
GTE.BSplineSurface surface = new GTE.BSplineSurface(bfU, bfV, controlsUV.ToArray());

// TODO: handle closed periodic surfaces in U and/or V
// use this knot vector and repeat "degree" vertexes at the end of U and/or V
//double fFactor = 1.0/(curve.NumControls-curve.BasisFunction.Degree);
//for (int i = 0; i < curve.BasisFunction.NumKnots; i++)
//{
// curve.BasisFunction.Knots[i] = (i - curve.BasisFunction.Degree) * fFactor;
//}
//change the knot vector to handle periodic BSplines
if (this.IsClosedInU)
{
double factor = 1.0 / this.u;
for (int i = 0; i < surface.BasisFunction(0).NumKnots; i++)
{
surface.BasisFunction(0).Knots[i] = (i - surface.BasisFunction(0).Degree) * factor;
}
}

double stepU = 1.0 / (precisionU - 1.0);
double stepV = 1.0 / (precisionV - 1.0);
if (this.IsClosedInV)
{
double factor = 1.0 / this.v;
for (int i = 0; i < surface.BasisFunction(1).NumKnots; i++)
{
surface.BasisFunction(1).Knots[i] = (i - surface.BasisFunction(1).Degree) * factor;
}
}

double stepU = this.IsClosedInU ? 1.0 / precisionU : 1.0 / (precisionU - 1);
double stepV = this.IsClosedInV ? 1.0 / precisionV : 1.0 / (precisionV - 1);
double tU = 0.0;
double tV = 0.0;

List<Vector3> ocsVertexes = new List<Vector3>(precisionU * precisionV);
for (int i = 0; i < precisionV; i++)
{
Expand Down
21 changes: 11 additions & 10 deletions netDxf/Entities/Polyline2D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,19 +421,18 @@ public List<EntityObject> Explode()
return entities;
}

List<SplineVertex> wcsVertexes = new List<SplineVertex>();
Vector3[] wcsVertexes = new Vector3[this.vertexes.Count];
Matrix3 trans = MathHelper.ArbitraryAxis(this.Normal);

foreach (Polyline2DVertex vertex in this.vertexes)
for (int i = 0; i < this.vertexes.Count; i++)
{
Vector3 wcsVertex = trans * new Vector3(vertex.Position.X, vertex.Position.Y, this.elevation);
wcsVertexes.Add(new SplineVertex(wcsVertex));
Vector3 wcsVertex = trans * new Vector3(this.vertexes[i].Position.X, this.vertexes[i].Position.Y, this.elevation);
wcsVertexes[i] = wcsVertex;
}

int degree = this.smoothType == PolylineSmoothType.Quadratic ? 2 : 3;
int splineSegs = this.Owner == null ? DefaultSplineSegs : this.Owner.Record.Owner.Owner.DrawingVariables.SplineSegs;
int precision = this.IsClosed ? splineSegs * this.Vertexes.Count : splineSegs * (this.Vertexes.Count - 1);
List<Vector3> splinePoints = Spline.NurbsEvaluator(wcsVertexes, null, degree, false, this.IsClosed, precision);
List<Vector3> splinePoints = Spline.NurbsEvaluator(wcsVertexes, null, null, degree, false, this.IsClosed, precision);

for (int i = 1; i < splinePoints.Count; i++)
{
Expand Down Expand Up @@ -595,14 +594,16 @@ public List<Vector2> PolygonalVertexes(int precision, double weldThreshold, doub
{
precision = 2;
}
List<SplineVertex> ctrlPoints = new List<SplineVertex>();
foreach (Polyline2DVertex vertex in this.vertexes)

Vector3[] ctrlPoints = new Vector3[this.vertexes.Count];
for (int i = 0; i < this.vertexes.Count; i++)
{
ctrlPoints.Add(new SplineVertex(vertex.Position));
Vector2 position = this.vertexes[i].Position;
ctrlPoints[i] = new Vector3(position.X, position.Y, 0.0);
}

// closed polylines will be considered as closed and periodic
List<Vector3> points = Spline.NurbsEvaluator(ctrlPoints, null, degree, false, this.IsClosed, precision);
List<Vector3> points = Spline.NurbsEvaluator(ctrlPoints, null, null, degree, false, this.IsClosed, precision);
foreach (Vector3 point in points)
{
ocsVertexes.Add(new Vector2(point.X, point.Y));
Expand Down
20 changes: 13 additions & 7 deletions netDxf/Entities/Polyline2DVertex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ public Polyline2DVertex(Vector2 position, double bulge)
this.endWidth = 0.0;
}

/// <summary>
/// Copy constructor.
/// </summary>
/// <param name="vertex">A Polyline2D vertex.</param>
public Polyline2DVertex(Polyline2DVertex vertex)
{
this.position = vertex.Position;
this.bulge = vertex.Bulge;
this.startWidth = vertex.startWidth;
this.endWidth = vertex.EndWidth;
}

#endregion

#region public properties
Expand Down Expand Up @@ -173,13 +185,7 @@ public override string ToString()
/// <returns>A new Polyline2DVertex that is a copy of this instance.</returns>
public object Clone()
{
return new Polyline2DVertex
{
Position = this.position,
Bulge = this.bulge,
StartWidth = this.startWidth,
EndWidth = this.endWidth
};
return new Polyline2DVertex(this);
}

#endregion
Expand Down
16 changes: 2 additions & 14 deletions netDxf/Entities/Polyline3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,10 @@ public List<EntityObject> Explode()
return entities;
}

List<SplineVertex> wcsVertexes = new List<SplineVertex>();
foreach (Vector3 vertex in this.vertexes)
{
wcsVertexes.Add(new SplineVertex(vertex));
}

int degree = this.smoothType == PolylineSmoothType.Quadratic ? 2 : 3;
int splineSegs = this.Owner == null ? DefaultSplineSegs : this.Owner.Record.Owner.Owner.DrawingVariables.SplineSegs;
int precision = this.IsClosed ? splineSegs * this.Vertexes.Count : splineSegs * (this.Vertexes.Count - 1);
List<Vector3> splinePoints = Spline.NurbsEvaluator(wcsVertexes, null, degree, false, this.IsClosed, precision);
List<Vector3> splinePoints = Spline.NurbsEvaluator(this.vertexes.ToArray(), null, null, degree, false, this.IsClosed, precision);

for (int i = 1; i < splinePoints.Count; i++)
{
Expand Down Expand Up @@ -331,14 +325,8 @@ public List<Vector3> PolygonalVertexes(int precision)
precision = 2;
}

List<SplineVertex> ctrlPoints = new List<SplineVertex>();
foreach (Vector3 vertex in this.vertexes)
{
ctrlPoints.Add(new SplineVertex(vertex));
}

// closed polylines will be considered as closed and periodic
return Spline.NurbsEvaluator(ctrlPoints, null, degree, false, this.IsClosed, precision);
return Spline.NurbsEvaluator(this.vertexes.ToArray(), null, null, degree, false, this.IsClosed, precision);
}

/// <summary>
Expand Down
Loading

0 comments on commit 5144bff

Please sign in to comment.