Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs =================================================================== diff -u -r6404 -r6525 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 6525) @@ -809,7 +809,6 @@ lock (Surfaces) { - SynchronizeLoops(); RemoveDoublesFromNewlyEffectedPointsAndCurves(); Points.AddRange(NewlyEffectedPoints); Curves.AddRange(NewlyEffectedCurves); Index: DamEngine/trunk/doc/Dam Engine - Technical Design/CreatingCalculationProfiles.tex =================================================================== diff -u -r6524 -r6525 --- DamEngine/trunk/doc/Dam Engine - Technical Design/CreatingCalculationProfiles.tex (.../CreatingCalculationProfiles.tex) (revision 6524) +++ DamEngine/trunk/doc/Dam Engine - Technical Design/CreatingCalculationProfiles.tex (.../CreatingCalculationProfiles.tex) (revision 6525) @@ -84,6 +84,7 @@ For merging a surface line geometry with a 1D subsoil profile, the surface line geometry is leading. This determines the left boundary (X-coordinate of the first point in the surface line geometry) of the 2D calculation profile to be created. It also determines its right boundary (X-coordinate of the last point in the surface line geometry). +Finally, the surface line geometry defines the top of the new 2D profile. The process consists of: \begin{itemize} @@ -119,12 +120,13 @@ In both cases, a calculation cannot be made for this situation, and an error message will follow. This error message will not interrupt the entire DAM process; the message will be recorded in the log file. -For merging a surface line geometry with a 2D subsoil profile, the surface line geometry is leading. -This determines the left boundary (X-coordinate of the first point in the surface line geometry) of the 2D calculation profile to be created. -It also determines its right boundary (X-coordinate of the last point in the surface line geometry). +Here too, the surface line geometry is leading in the combination process. +It determines the left boundary, the right boundary and the top of the 2D calculation profile to be created. When the 2D subsoil profile lies entirely to the left or to the right of the surface line geometry, -a combination cannot be made and an error message will follow. Again this error message will not interrupt the entire DAM process; the message will be recorded in the log file. +a combination cannot be made and an error message will follow. +Again this error message will not interrupt the entire DAM process; +the message will be recorded in the log file. The process consists of: \begin{itemize} @@ -137,36 +139,83 @@ \item Then perform all subsequent steps on the copies. \item Round all coordinates from both the 2D subsoil profile as well as from the surface line geometry. \item Create a new 2D profile as place holder for the resulting calculation profile. - \item Create a new 2D geometry by combining the surface line geometry with the subsoil profile (see below) + \item Create a new 2D geometry by combining the surface line geometry with the subsoil profile (see \autoref{sec:Creating2DGeometry}). \item Add the generated 2D geometry to the 2D profile. \item Remove all geometry data (points, curves, loops, surface) from the genrated geometry that ly above the surface line geometry. \item Reconstruct the surfaces, i.e. find which new surfaces are equal to the "old" surfaces as these were part of the subsoil profile. Copy the soil, IsAquifer and WaterpressureInterpolationModel properties from the "old" surfaces when found else set default values for them - (IsAquifer = false, WaterpressureInterpolationModel = Automat5ic, soil = filling material). + (IsAquifer = false, WaterpressureInterpolationModel = Automatic, soil = filling material). \item Copy the pre-consolidation stresses from the original 2D subsoil profile to the new 2D profile. - \item Rebox the geometry of the new 2D profile to set the proper limit values for theat geometry + \item Rebox the geometry of the new 2D profile to set the proper limit values for that geometry \item Update the surfaceline property of the geometry of the new 2D profile. \item Finally, Round all coordinates from both the geometry of the new 2D profile. \end{itemize} +\subsection{Creating the new 2D Geometry} +\label{sec:Creating2DGeometry} Creating the new 2D geometry involves: \begin{itemize} \item Clone the given original geometry. - \ item perform all further actions on the cloned geometry + \item Perform all further actions on the cloned geometry. \item Check that the geometry contains at least 3 points and 3 curves. - \item Rebox the geometry to ensure proper limits + \item Rebox the geometry to ensure proper limits. \item Make sure that there is not already some sort of generation going on by checking that there are no newly effected points and/or curves. \item Adapt the geometry to the limits as defined by the surface line geometry Do this by either cutting exiting surfaces and/or extending the geometry with new surfaces where needed. - \item Add the surface line geometry (i.e. points and curves) to the geometry. Note that when needed extra curves can be added when the startpoint and/or endpoint of the surface line are above the geometry. + \item Add the surface line geometry (i.e. points and curves) to the geometry. Note that when needed extra curves can be added when the start-point and/or endpoint of the surface line are above the geometry. \item Add all the points and curves from the geometry as Newly Effected point/curves to the geometry. - \item Remove all surfaces, loops, curves and points form the geometry. - \item Regenerate the geometry (see below) - \item Delete all loose points and curves + \item Remove all surfaces, loops, curves and points from the geometry. + \item Regenerate the geometry (see \autoref{sec:Regenerating2DGeometry}). + \item Delete all loose points and curves. \end{itemize} +\subsection{Regenerating the new 2D Geometry} +\label{sec:Regenerating2DGeometry} Regenerating the geometry involves: \begin{itemize} - \item Clone the given original geometry. + \item Locking the surfaces so asynchronous calls do not mess up the generation. + \item Remove all double points and curves from the Newly Effected points/curves. + \item Add the Newly Effected Points to Points. + \item Add the Newly Effected Curves to Curves. + \item Set up the curve-surfaces associations, i.e. whether a curve has a surface on the left and/or on the right of it. + Note that this is not required when the full combination procedure is used but it can be required when the "GenerateGeometry" procedure is used directly with an existing full geometry. + \item In a loop perform the next actions untile the generation is ready + \item - Break up all curves at any intersection even when they partially coincide whilst making sure the geometry stays correct whenever a curve needed to be split (see \autoref{sec:EnsuringCorrectGeometry}). + \item Merge coinciding points that may be the result of the step above. Note that any obsolete curve (due to the merge) is removed too. + \item - Delete invalid and duplicated curves that may be the result of breaking the intersections. + \item - Initialise the geometryCurveForwardsIsUsed and geometryCurveBackwardsIsUsed dictionaries with false. + \item - Start detecting surfaces using the Plaxis algorithm (see \autoref{sec:DetectingSurfaces}). + The result of that algorithm signals whether the loop/generation is ready. + \item Clear the Newly Effected Points. + \item Clear the Newly Effected Curves. + \item Update the surface line property from the geometry. \end{itemize} - + +\subsection{Ensuring a correct geometry} +\label{sec:EnsuringCorrectGeometry} +A correct geometry is obtained by: +\begin{itemize} + \item Make sure that all points that are used by Curves are in the Points list. + \item Find all double points (by location) in Points and store these in a list. + \item Replace all the double points as references in Curves and Newly Effected Curves. + \item Remove all Curves and Newly Effected Curves that have no length (head-point = endpoint) from their lists and from all (inner and outer) loops (and thus surfaces). + \item Remove all invalid surfaces (i.e. a surface that has no area) that might be the result of curve deletion. + \item Finally, remove all double points from Points and Newly Effected Points. +\end{itemize} + +\subsection{Detecting surfaces} +\label{sec:DetectingSurfaces} +Detecting surfaces involves: +\begin{itemize} + \item Create a list to store new loops. + \item Create a list of direction curves (a direction curve is a curve that holds the direction of the curve next to the curve itself; it offers head and endpoint based on the direction, i.e. head-point becomes endpoint when the direction is backward) + \item Start looping through the existing curves with curve 1 as current curve. This is the outer method loop to check all relevant curves which could become loops. + \item create a new geometry loop and add the current curve. + \item remember curve 1 and its direction so you can check whether the inner method loop (started next) is finished, i.e. when the next connected curve equals curve 1 and its direction. + \item start the inner method loop to gather all relevant curves for the geometry loop. + \item Find all curves connected to the endpoint of the current curve. + \item If there is more than 1 connected curve, select the one that turns clockwise most and add it to the new geometry loop. If there is only 1, just add that to the new geometry loop. If there is no connected curve, something is wrong and an exception is raised. + \item replace the current curve and its direction by the just found connected curve and its direction. + \item continue the inner method loop with the adapted current curve to find the next connected one. Keep doing this until the found next connected curve equals curve 1 which means the new geometry loop is ready. Add that new loop to the new loop list and continue the outer method loop with the next curve until all curve are checked. + \item Now the all new geometry loops are known and these are used to create surfaces. The number of created surfaces is used as result for the method DetectSurfaces. A number > 0 indicates success, < 0 failure due to error(s), 0 signifies that no surface could be found. +\end{itemize} \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs =================================================================== diff -u -r6404 -r6525 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 6525) @@ -52,8 +52,6 @@ /// public void GenerateGeometry() { - FilterOutDoublePoints(); - SetupCurveSurfaceAssociations(); var firstRegeneration = true; @@ -348,10 +346,13 @@ } /// - /// Removes all double points, replaces them in curves and newlyeffectedpoints. - /// Also deletes "zero" curves (beginpoint = endpoint) also from surface loops and newlyeffectedcurrves + /// Makes sure that the geometry is correct by removing all double points from Points and + /// NewlyEffectedPoints list, replaces their references in curves and NewlyEffectedCurves + /// and by adding missing points to the Points list when needed. + /// Also deletes "zero" curves (begin-point = endpoint) also from surface loops and newlyeffectedcurrves. + /// Finally it removes invalid surfaces, i.e. surface that do not have a proper area. /// - private void FilterOutDoublePoints() + private void EnsureCorrectGeometry() { var doublePoints = new Dictionary(); @@ -494,7 +495,7 @@ continue; } - // check the direction + // get the direction of the current curve CurveDirection currentCurveDirection; if (index % 2 == 0) { @@ -503,7 +504,7 @@ continue; } - currentCurveDirection = CurveDirection.Forward; // get the direction of the current curve + currentCurveDirection = CurveDirection.Forward; } else { @@ -512,13 +513,11 @@ continue; } - currentCurveDirection = CurveDirection.Reverse; // get the direction of the current curve + currentCurveDirection = CurveDirection.Reverse; } // create aValue1 new loop var newLoop = new GeometryLoop(); - - //this.geometryData.Loops.Add(newLoop); newLoopList.Add(newLoop); // initialise LoopBeginCurve @@ -535,14 +534,7 @@ { // the curve wasn't added bcos the curve-direction pair was already present in loop. // problem case - break here, else we'd get aValue1 hang! - // Todo: Solve this problem - if (!firstRegeneration) - { - //TODO:Show error message box - break; - } - - return -1; + throw new Exception("The curve could not be added to the loop"); } Point2D curveEndPoint = currentCurve.GetEndPoint(currentCurveDirection); @@ -571,15 +563,7 @@ if (attachedCurveList.Count == 0) // no curves found { - CurveDirection oppCurrentDirection = currentCurveDirection == CurveDirection.Forward ? CurveDirection.Reverse : CurveDirection.Forward; - // if the current curve is not used in the opposite direction, it is considered in the opposite direction - if (!GetIsUsed(currentCurve, oppCurrentDirection)) - { - currentCurveDirection = oppCurrentDirection; - continue; - } - - break; + throw new Exception("No connected Curve found"); } // we have aValue1 set of curves, find the one that turns right the most @@ -1039,7 +1023,6 @@ /// private void RegenerateAllCurvesIntersection() { - MergePoints(); var isCurveInserted = false; var hasCurveBeenSplit = true; while (hasCurveBeenSplit) @@ -1054,13 +1037,11 @@ isCurveInserted = FindAndProcessCurveIntersections(geometryCurve1, geometryCurve2, isCurveInserted, ref hasCurveBeenSplit); } } - - FilterOutDoublePoints(); + EnsureCorrectGeometry(); } - geometryData.NewlyEffectedCurves.Clear(); MergePoints(); - DeleteDuplicateCurves(); + DeleteInvalidAndDuplicateCurves(); } private bool FindAndProcessCurveIntersections(GeometryCurve geometryCurve1, GeometryCurve geometryCurve2, bool isCurveInserted, @@ -1385,7 +1366,7 @@ } } - private void DeleteDuplicateCurves() + private void DeleteInvalidAndDuplicateCurves() { List curvesToDelete = geometryData.Curves.Where((Func) (curve => curve.HeadPoint == curve.EndPoint)).ToList(); foreach (GeometryCurve aCurve in curvesToDelete)