// MargYantra – Road Design Tool // IRC standards-based calculations for superelevation, camber, and transition curves interface RoadDesignInput { road_type: 'highway' | 'arterial' | 'collector' | 'local' | 'expressway'; design_speed: number; // km/h curve_radius: number; // meters cross_slope: number; // percentage terrain: 'plain' | 'rolling' | 'mountainous'; pavement_type: 'flexible' | 'rigid' | 'composite'; } interface RoadDesignOutput { superelevation: number; // percentage camber: number; // percentage transition_length: number; // meters sight_distance: number; // meters widening_required: number; // meters banking_angle: number; // degrees design_considerations: string[]; irc_references: string[]; safety_warnings: string[]; confidence: number; } class RoadDesignCalculator { private readonly MAX_SUPERELEVATION = 7.0; // IRC standard maximum private readonly MIN_CURVE_RADIUS = 30; // minimum for any road private readonly MAX_DESIGN_SPEED = 120; // km/h for highways // IRC standard values for different road types private roadStandards = new Map([ ['highway', { max_speed: 100, min_radius: 230, camber_flexible: 2.5, camber_rigid: 2.0, lane_width: 3.5 }], ['arterial', { max_speed: 80, min_radius: 120, camber_flexible: 2.5, camber_rigid: 2.0, lane_width: 3.5 }], ['collector', { max_speed: 65, min_radius: 80, camber_flexible: 3.0, camber_rigid: 2.5, lane_width: 3.25 }], ['local', { max_speed: 50, min_radius: 50, camber_flexible: 3.0, camber_rigid: 2.5, lane_width: 3.0 }], ['expressway', { max_speed: 120, min_radius: 360, camber_flexible: 2.0, camber_rigid: 1.7, lane_width: 3.75 }] ]); calculateRoadDesign(input: RoadDesignInput): RoadDesignOutput { try { // Validate inputs this.validateInputs(input); const roadStd = this.roadStandards.get(input.road_type); if (!roadStd) { throw new Error(`Unknown road type: ${input.road_type}`); } // Calculate superelevation const superelevation = this.calculateSuperelevation(input.design_speed, input.curve_radius); // Determine camber const camber = this.calculateCamber(input.pavement_type, input.road_type); // Calculate transition curve length const transitionLength = this.calculateTransitionLength(input.design_speed, input.curve_radius, superelevation); // Calculate sight distance const sightDistance = this.calculateSightDistance(input.design_speed, input.curve_radius); // Calculate mechanical widening const widening = this.calculateWidening(input.curve_radius, roadStd.lane_width); // Convert superelevation to banking angle const bankingAngle = Math.atan(superelevation / 100) * (180 / Math.PI); // Generate design considerations and warnings const designConsiderations = this.getDesignConsiderations(input, superelevation, transitionLength); const safetyWarnings = this.getSafetyWarnings(input, superelevation, sightDistance); const ircReferences = this.getIRCReferences(input.road_type); // Calculate confidence based on design adequacy const confidence = this.calculateConfidence(input, superelevation, sightDistance); return { superelevation: Math.round(superelevation * 100) / 100, camber: camber, transition_length: Math.round(transitionLength), sight_distance: Math.round(sightDistance), widening_required: Math.round(widening * 100) / 100, banking_angle: Math.round(bankingAngle * 100) / 100, design_considerations: designConsiderations, irc_references: ircReferences, safety_warnings: safetyWarnings, confidence: confidence }; } catch (error) { throw new Error(`Road design calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } private validateInputs(input: RoadDesignInput): void { if (!input.road_type || !this.roadStandards.has(input.road_type)) { throw new Error('Invalid road type. Must be one of: highway, arterial, collector, local, expressway'); } if (!input.design_speed || input.design_speed <= 0 || input.design_speed > this.MAX_DESIGN_SPEED) { throw new Error(`Design speed must be between 1 and ${this.MAX_DESIGN_SPEED} km/h`); } if (!input.curve_radius || input.curve_radius < this.MIN_CURVE_RADIUS) { throw new Error(`Curve radius must be at least ${this.MIN_CURVE_RADIUS} meters`); } if (input.cross_slope !== undefined && (input.cross_slope < -10 || input.cross_slope > 10)) { throw new Error('Cross slope must be between -10% and +10%'); } if (!input.terrain || !['plain', 'rolling', 'mountainous'].includes(input.terrain)) { throw new Error('Invalid terrain type. Must be one of: plain, rolling, mountainous'); } if (!input.pavement_type || !['flexible', 'rigid', 'composite'].includes(input.pavement_type)) { throw new Error('Invalid pavement type. Must be one of: flexible, rigid, composite'); } } private calculateSuperelevation(speed: number, radius: number): number { // IRC 73-1980 formula for superelevation // e = V²/(127R) - f, where f = lateral friction coefficient const lateralFriction = this.getLateralFrictionCoefficient(speed); const superelevation = (speed * speed) / (127 * radius) - lateralFriction; // Apply IRC limits if (superelevation < 0) return 0; if (superelevation > this.MAX_SUPERELEVATION) return this.MAX_SUPERELEVATION; return superelevation; } private getLateralFrictionCoefficient(speed: number): number { // IRC 73-1980 values for lateral friction if (speed <= 50) return 0.15; if (speed <= 65) return 0.14; if (speed <= 80) return 0.13; if (speed <= 100) return 0.12; return 0.10; } private calculateCamber(pavementType: string, roadType: string): number { const roadStd = this.roadStandards.get(roadType); if (!roadStd) return 2.5; switch (pavementType) { case 'flexible': return roadStd.camber_flexible; case 'rigid': return roadStd.camber_rigid; case 'composite': return (roadStd.camber_flexible + roadStd.camber_rigid) / 2; default: return 2.5; } } private calculateTransitionLength(speed: number, radius: number, superelevation: number): number { // IRC 73-1980 formula for transition curve length // L = 0.0215 * V³ / R (minimum formula) // Also consider superelevation development length const minLength = (0.0215 * speed * speed * speed) / radius; const superelevationLength = speed * superelevation / 0.5; // 0.5% per meter development rate return Math.max(minLength, superelevationLength, 30); // minimum 30m } private calculateSightDistance(speed: number, radius: number): number { // IRC SP 73-2018 stopping sight distance const reactionTime = 2.5; // seconds const brakingEfficiency = 0.35; // for wet roads const grade = 0; // assuming level road const reactionDistance = (speed * 1000 / 3600) * reactionTime; const brakingDistance = (speed * speed) / (254 * (brakingEfficiency + grade / 100)); const stoppingSightDistance = reactionDistance + brakingDistance; // Check if horizontal curve affects sight distance const availableSightDistance = this.calculateHorizontalSightDistance(radius); return Math.min(stoppingSightDistance, availableSightDistance); } private calculateHorizontalSightDistance(radius: number): number { // For horizontal curves, sight distance is limited by curve geometry const middleOrdinate = 1.5; // typical clearance from centerline return 2 * Math.sqrt(2 * radius * middleOrdinate - middleOrdinate * middleOrdinate); } private calculateWidening(radius: number, laneWidth: number): number { // IRC SP 73-2018 mechanical widening formula const vehicleLength = 6; // meters (design vehicle) const wheelBase = 3.5; // meters const widening = (vehicleLength * vehicleLength) / (2 * radius) + (wheelBase * wheelBase) / (2 * radius); return Math.max(0, widening); } private getDesignConsiderations(input: RoadDesignInput, superelevation: number, transitionLength: number): string[] { const considerations: string[] = []; if (superelevation > 5.0) { considerations.push('High superelevation - ensure proper drainage design'); } if (transitionLength > 200) { considerations.push('Long transition curve - check for adequate sight distance'); } if (input.terrain === 'mountainous') { considerations.push('Mountainous terrain - consider additional safety measures and escape ramps'); } if (input.design_speed > 80) { considerations.push('High speed design - implement enhanced safety features'); } considerations.push('Ensure proper signage and pavement markings as per IRC 35'); considerations.push('Consider weather conditions and seasonal variations'); return considerations; } private getSafetyWarnings(input: RoadDesignInput, superelevation: number, sightDistance: number): string[] { const warnings: string[] = []; const roadStd = this.roadStandards.get(input.road_type); if (input.curve_radius < (roadStd?.min_radius || 100)) { warnings.push(`Curve radius below recommended minimum for ${input.road_type} roads`); } if (superelevation === this.MAX_SUPERELEVATION) { warnings.push('Maximum superelevation reached - consider increasing curve radius'); } if (sightDistance < this.getMinimumSightDistance(input.design_speed)) { warnings.push('Inadequate sight distance - reduce design speed or increase radius'); } if (input.design_speed > (roadStd?.max_speed || 50)) { warnings.push('Design speed exceeds recommended maximum for this road type'); } return warnings; } private getMinimumSightDistance(speed: number): number { // IRC minimum sight distance requirements return speed * 2; // simplified minimum requirement } private getIRCReferences(roadType: string): string[] { const references = [ 'IRC 73-1980: Geometric Design Standards for Rural Highways', 'IRC SP 73-2018: Manual of Specifications & Standards for Four Laning of Highways', 'IRC 35-2015: Code of Practice for Road Markings', 'IRC 103-2012: Guidelines for Pedestrian Facilities' ]; if (roadType === 'expressway') { references.push('IRC 5-2015: Standard Specifications and Code of Practice for Road Bridges'); } return references; } private calculateConfidence(input: RoadDesignInput, superelevation: number, sightDistance: number): number { let confidence = 90; const roadStd = this.roadStandards.get(input.road_type); // Reduce confidence for edge cases if (input.curve_radius < (roadStd?.min_radius || 100) * 1.2) { confidence -= 15; } if (superelevation > 6.0) { confidence -= 10; } if (sightDistance < this.getMinimumSightDistance(input.design_speed) * 1.1) { confidence -= 20; } return Math.max(50, confidence); } // Helper method to get design speed recommendations getDesignSpeedRecommendations(): Record { return { 'expressway': { recommended: 100, maximum: 120 }, 'highway': { recommended: 80, maximum: 100 }, 'arterial': { recommended: 65, maximum: 80 }, 'collector': { recommended: 50, maximum: 65 }, 'local': { recommended: 40, maximum: 50 } }; } // Method to check design adequacy checkDesignAdequacy(input: RoadDesignInput): { adequate: boolean; issues: string[] } { const issues: string[] = []; const roadStd = this.roadStandards.get(input.road_type); if (!roadStd) { return { adequate: false, issues: ['Invalid road type'] }; } if (input.design_speed > roadStd.max_speed) { issues.push(`Design speed exceeds maximum for ${input.road_type} (${roadStd.max_speed} km/h)`); } if (input.curve_radius < roadStd.min_radius) { issues.push(`Curve radius below minimum for ${input.road_type} (${roadStd.min_radius}m)`); } return { adequate: issues.length === 0, issues }; } // Generate detailed design report generateDesignReport(input: RoadDesignInput, output: RoadDesignOutput): string { return ` ROAD GEOMETRIC DESIGN REPORT =========================== INPUT PARAMETERS: - Road Type: ${input.road_type} - Design Speed: ${input.design_speed} km/h - Curve Radius: ${input.curve_radius} m - Cross Slope: ${input.cross_slope}% - Terrain: ${input.terrain} - Pavement Type: ${input.pavement_type} DESIGN RESULTS: - Superelevation: ${output.superelevation}% - Camber: ${output.camber}% - Transition Length: ${output.transition_length} m - Sight Distance: ${output.sight_distance} m - Widening Required: ${output.widening_required} m - Banking Angle: ${output.banking_angle}° DESIGN CONSIDERATIONS: ${output.design_considerations.map(c => `- ${c}`).join('\n')} SAFETY WARNINGS: ${output.safety_warnings.map(w => `- ${w}`).join('\n')} IRC REFERENCES: ${output.irc_references.map(ref => `- ${ref}`).join('\n')} Design Confidence: ${output.confidence}% Generated by Prithvi Guardian AI - MargYantra Module Date: ${new Date().toLocaleDateString('en-IN')} `; } } export const roadDesignCalculator = new RoadDesignCalculator(); export { RoadDesignInput, RoadDesignOutput };