public IEnumerable <ICoordinateOperationCrsPathInfo> Generate(EpsgCrs from, EpsgCrs to) { Contract.Requires(from != null); Contract.Requires(to != null); Contract.Ensures(Contract.Result <IEnumerable <ICoordinateOperationCrsPathInfo> >() != null); if (from.Kind == EpsgCrsKind.Compound || from.Kind == EpsgCrsKind.Engineering || from.Kind == EpsgCrsKind.Vertical) { throw new NotImplementedException(String.Format("Support for the from CRS kind {0} is not yet implemented.", from.Kind)); } if (to.Kind == EpsgCrsKind.Compound || to.Kind == EpsgCrsKind.Engineering || to.Kind == EpsgCrsKind.Vertical) { throw new NotImplementedException(String.Format("Support for the to CRS kind {0} is not yet implemented.", to.Kind)); } if (from.Code == to.Code) { throw new NotImplementedException("Empty conversion not yet handled."); } var startNode = new EpsgCrsPathSearchNode(from); Contract.Assume(to is EpsgCrsGeodetic); var searchRestrictions = new SearchOptions { SourceArea = from.Area, TargetArea = to.Area }; var corePaths = FindAllCorePaths(startNode, (EpsgCrsGeodetic)to, searchRestrictions); return(corePaths.Select(node => node.BuildCoordinateOperationCrsPathInfo())); }
private IEnumerable <EpsgCrsPathSearchNode> FindAllCorePaths(EpsgCrsPathSearchNode fromNode, EpsgCrsGeodetic toCrs, SearchOptions searchOptions) { Contract.Requires(fromNode != null); Contract.Requires(fromNode.Crs is EpsgCrsGeodetic); Contract.Requires(toCrs != null); var earlyResults = new List <EpsgCrsPathSearchNode>(); var fromCrs = (EpsgCrsGeodetic)fromNode.Crs; // construct the hierarchy based on the from CRS var fromStack = new List <EpsgCrsPathSearchNode>(); var fromStackConstructionNode = fromNode; do { fromStack.Add(fromStackConstructionNode); var currentCrs = (EpsgCrsGeodetic)fromStackConstructionNode.Crs; if (!currentCrs.HasBaseOperation) { break; } var baseCrs = currentCrs.BaseCrs; var fromBaseEdge = currentCrs.GetBaseOperation(); Contract.Assume(baseCrs != null); Contract.Assume(fromBaseEdge != null); if (!fromBaseEdge.HasInverse) { break; // we have to invert the edge to traverse up the stack } var toBaseEdge = fromBaseEdge.GetInverse(); fromStackConstructionNode = new EpsgCrsPathSearchNode(baseCrs, toBaseEdge, fromStackConstructionNode); } while (true /*fromStackSearchNode != null*/); // construct the hierarchy based on the to CRS var toStack = new List <GeodeticCrsStackItem>(); var toStackConstructionCrs = toCrs; do { toStack.Add(new GeodeticCrsStackItem { Crs = toStackConstructionCrs }); toStackConstructionCrs = toStackConstructionCrs.BaseCrs; } while (toStackConstructionCrs != null); var lowestStackIntersection = FindLowestStackIntersection(fromStack, toStack); if (lowestStackIntersection != null) { earlyResults.Add(lowestStackIntersection); } var directResults = FindDirectTransformations(fromStack, toStack, searchOptions); var indirectResults = FindIndirectTransformations(fromStack, toStack, searchOptions); return(earlyResults.Concat(directResults).Concat(indirectResults)); }
public EpsgCrsPathSearchNode(EpsgCrs crs, ICoordinateOperationInfo edgeFromParent, EpsgCrsPathSearchNode parent) { Contract.Requires(crs != null); Contract.Requires(edgeFromParent != null); Contract.Requires(parent != null); Crs = crs; EdgeFromParent = edgeFromParent; Parent = parent; }
private EpsgCrsPathSearchNode AppendBacktrackingToStack(EpsgCrsPathSearchNode fromNode, List <GeodeticCrsStackItem> toStack, int startIndex) { var node = fromNode; for (int backtrackIndex = startIndex; backtrackIndex >= 0; backtrackIndex--) { var crs = toStack[backtrackIndex].Crs; Contract.Assume(crs.HasBaseOperation); var edge = crs.GetBaseOperation(); node = new EpsgCrsPathSearchNode(crs, edge, node); } return(node); }
private IEnumerable <OperationNodeCandidate> CreateNodeCandidates(IEnumerable <ushort> forwardOperationCodes, IEnumerable <ushort> inverseOperationCodes, EpsgCrs targetCrs, EpsgCrsPathSearchNode parentNode) { IEnumerable <OperationNodeCandidate> nodeCandidates = null; if (forwardOperationCodes != null) { Contract.Assume(nodeCandidates == null); nodeCandidates = CreateForwardNodeCandidates(forwardOperationCodes, targetCrs, parentNode); } if (inverseOperationCodes != null) { var inverseOpNodes = CreateInverseNodeCandidates(inverseOperationCodes, targetCrs, parentNode); nodeCandidates = nodeCandidates == null ? inverseOpNodes : nodeCandidates.Concat(inverseOpNodes); } if (nodeCandidates == null) { return(Enumerable.Empty <OperationNodeCandidate>()); } return(nodeCandidates .OrderBy(x => x.CoreOp.Deprecated) .ThenByDescending(x => x.Accuracy.HasValue) .ThenBy(x => x.Accuracy.GetValueOrDefault())); }
private IEnumerable <OperationNodeCandidate> CreateInverseNodeCandidates(IEnumerable <ushort> inverseOperationCodes, EpsgCrs targetCrs, EpsgCrsPathSearchNode parentNode) { Contract.Requires(inverseOperationCodes != null); Contract.Ensures(Contract.Result <IEnumerable <OperationNodeCandidate> >() != null); return(inverseOperationCodes .Select(code => EpsgMicroDatabase.Default.GetCoordinateTransformOrConcatenatedInfo(code)) .Where(op => op != null && op.HasInverse) .Select(op => new OperationNodeCandidate { CoreOp = op, Accuracy = op.Accuracy, Node = new EpsgCrsPathSearchNode(targetCrs, op.GetInverse(), parentNode) })); }