-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performances for computational intensive loops #391
Comments
Performance hasn't seemed to be an issue in typical use cases. What performance bottlenecks are affecting users, for which particular methods, with what inputs? |
This is the code where I have performances issues (don't worry about how I get to the curves construction) increment = 1.0;
/// Create the alignment
foreach (var entity in alignment.Entities)
{
switch (entity.EntityType)
{
case EntityType.Tangent:
crvs.Add(new Line(
entity.StartPoint.ToGShark(),
entity.EndPoint.ToGShark()
));
break;
case EntityType.Arc:
crvs.Add(new Arc(
entity.StartPoint.ToGShark(),
entity.MidPoint.ToGShark(),
entity.EndPoint.ToGShark()
));
break;
case EntityType.Spiral:
var prev = alignment.Entities.Where(w => w.Id == entity.Prev).First();
var next = alignment.Entities.Where(w => w.Id == entity.Next).First();
crvs.Add(entity.ToSpiral(prev, next, increment));
break;
}
}
var alCurve = new PolyCurve(crvs);
Console.WriteLine("-------- Alignment --------");
Console.WriteLine($"Point at 0.0: ${alCurve.PointAtNormalizedLength(0.0)}");
Console.WriteLine($"Point at 0.5: ${alCurve.PointAtNormalizedLength(0.5)}");
Console.WriteLine($"Point at 1.0: ${alCurve.PointAtNormalizedLength(1.0)}");
Console.WriteLine($"Alignment 2D Length: ${alCurve.Length}");
///Create the profile
var profile = alignment.Profiles.First();
List<Point3> crvPts = new List<Point3>();
int paraCurveSub = 2;
foreach (var entity in profile.Entities)
{
switch (entity.EntityType)
{
case EntityType.PVI:
crvPts.Add(entity.PVI.ToGShark());
break;
case EntityType.Tangent:
crvPts.AddRange(new List<Point3> {entity.StartPoint.ToGShark(), entity.EndPoint.ToGShark()});
break;
case EntityType.ParabolaAsymmetric:
throw new NotImplementedException("Parabola Asymmetryc not implemented!");
case EntityType.ParabolaSymmetric:
var pts = entity.GetParabolaSymmetricPoints(paraCurveSub);
crvPts.AddRange(entity.GetParabolaSymmetricPoints(paraCurveSub).Select(pt => pt.ToGShark()).ToList());
break;
}
}
var prCurve = new PolyLine(crvPts);
Console.WriteLine("\n-------- Profile --------");
Console.WriteLine($"Point at 0.0: {prCurve.PointAtNormalizedLength(0.0)}");
Console.WriteLine($"Point at 0.5: {prCurve.PointAtNormalizedLength(0.5)}");
Console.WriteLine($"Point at 1.0: {prCurve.PointAtNormalizedLength(1.0)}");
Console.WriteLine($"Profile 2D Length: {prCurve.Length}");
/// Generate 3D alignment curve
List<double> allStations = new List<double>();
Stopwatch sw = new Stopwatch();
sw.Start();
double alEndSStation = alignment.Stations.Last();
double prStartStation = profile.Stations.First();
double prEndStation = profile.Stations.Last();
var profileStations = profile.Stations.Select(s => s -= alignment.StartStation).ToList();
var alignmentStations = alignment.Stations.Select(s => s -= alignment.StartStation).ToList();
double start = profileStations.First() > alignmentStations.First() ? profileStations.First() : alignmentStations.First();
double end = profileStations.Last() > alignmentStations.Last() ? alignmentStations.Last() : profileStations.Last();
allStations.AddRange(alignmentStations);
allStations.AddRange(profileStations);
double xs = start;
while (xs <= end)
{
allStations.Add(xs);
xs += increment;
}
allStations = allStations.Distinct().ToList(); /// remove duplicates
allStations.Sort(); // order list
List<Point3> pts3d = new List<Point3>();
Console.WriteLine("\n-------- 3D Curve --------");
Console.WriteLine($"{allStations.Count} points to be evaluated evaluated...");
Console.WriteLine($"Start evaluation...");
sw.Reset();
sw.Start();
foreach (double s in allStations)
{
var ptOnAl = alCurve.PointAtLength(s);
var pl = new Plane(new Point3(s + alignment.StartStation, 0, 0), GShark.Geometry.Vector3.XAxis);
var inters = Intersect.CurvePlane(prCurve, pl);
if (inters.Count > 0 ){
pts3d.Add(new Point3(ptOnAl.X, ptOnAl.Y, inters.First().Point.Y));
}
}
Console.WriteLine($"{pts3d.Count} points evaluated in {sw.Elapsed.TotalSeconds} seconds");
var crv3d = new PolyLine(pts3d);
Console.WriteLine("\n-------- 3D Curve point test--------");
Console.WriteLine($"Curve 3D Length: {crv3d.Length}");
sw.Reset();
Console.WriteLine($"Point at 0.0: {crv3d.PointAtLength(0.0)} evaluated in {sw.Elapsed.TotalMilliseconds} ms");
sw.Reset();
Console.WriteLine($"Point at 0.5: {crv3d.PointAtLength(crv3d.Length/2.0)} evaluated in {sw.Elapsed.TotalMilliseconds} ms");
sw.Reset();
Console.WriteLine($"Point at 1.0: {crv3d.PointAtLength(crv3d.Length)} evaluated in {sw.Elapsed.TotalMilliseconds} ms");
Console.ReadLine(); Now this basically takes XY from one curve (this curve is the alignment and is located on the XY plane) and the Z from another curve (this curve is the vertical profile and is a curve on XY plane). The resultant point is a 3D point that is then used to create a 3D curve.
As you can see 120'' (sometimes even more) to calculate 1500 points are probably not ideal (Dynamo takes a fraction of second) |
We can write individual performance tests to benchmark some of the more computationally intensive methods. I set up a quick test with a similar use case to check and I'm not getting the same results as you, so there's something else going on here... Not that 1.8s is fast in terms of performance, but it's certainly not 120s! Possible causes that come to mind are:
|
We have to think on a strategy to improve performances when we have an high number of computations to be performed (i.e.
PointAt
,PointAtLenght
, etc.) along a curve.The text was updated successfully, but these errors were encountered: