Changeset View
Changeset View
Standalone View
Standalone View
extern/opennurbs/opennurbs_parse_point.cpp
- This file was added.
| /* $NoKeywords: $ */ | |||||
| /* | |||||
| // | |||||
| // Copyright (c) 1993-2013 Robert McNeel & Associates. All rights reserved. | |||||
| // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert | |||||
| // McNeel & Associates. | |||||
| // | |||||
| // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. | |||||
| // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF | |||||
| // MERCHANTABILITY ARE HEREBY DISCLAIMED. | |||||
| // | |||||
| // For complete openNURBS copyright information see <http://www.opennurbs.org>. | |||||
| // | |||||
| //////////////////////////////////////////////////////////////// | |||||
| */ | |||||
| #include "opennurbs.h" | |||||
| #if !defined(ON_COMPILING_OPENNURBS) | |||||
| // This check is included in all opennurbs source .c and .cpp files to insure | |||||
| // ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. | |||||
| // When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined | |||||
| // and the opennurbs .h files alter what is declared and how it is declared. | |||||
| #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs | |||||
| #endif | |||||
| int ON_ParsePointExpression( | |||||
| const wchar_t* str, | |||||
| int str_count, | |||||
| ON::AngleUnitSystem default_str_angle_unit_system, | |||||
| ON::LengthUnitSystem point_value_unit_system, | |||||
| ON_3dPoint* point_value | |||||
| ) | |||||
| { | |||||
| ON_ParseSettings ps(ON_ParseSettings::DefaultSettingsInRadians); | |||||
| ps.SetDefaultAngleUnitSystem(default_str_angle_unit_system); | |||||
| return ON_ParsePointExpression( | |||||
| str,str_count, | |||||
| ps, | |||||
| point_value_unit_system,point_value, | |||||
| 0); | |||||
| } | |||||
| int ON_ParsePointExpression( | |||||
| const wchar_t* str, | |||||
| int str_count, | |||||
| ON::AngleUnitSystem default_str_angle_unit_system, | |||||
| const ON_UnitSystem& point_value_unit_system, | |||||
| ON_3dPoint* point_value | |||||
| ) | |||||
| { | |||||
| ON_ParseSettings ps(ON_ParseSettings::DefaultSettingsInRadians); | |||||
| ps.SetDefaultAngleUnitSystem(default_str_angle_unit_system); | |||||
| return ON_ParsePointExpression( | |||||
| str,str_count, | |||||
| ps, | |||||
| point_value_unit_system,point_value, | |||||
| 0); | |||||
| } | |||||
| int ON_ParsePointExpression( | |||||
| const wchar_t* str, | |||||
| int str_count, | |||||
| ON_ParseSettings parse_settings, | |||||
| const ON_UnitSystem& point_value_unit_system, | |||||
| ON_3dPoint* point_value, | |||||
| ON_ParseSettings* parse_results | |||||
| ) | |||||
| { | |||||
| ON::LengthUnitSystem pt_unit_system; | |||||
| double pt_scale = 1.0; | |||||
| switch(point_value_unit_system.UnitSystem()) | |||||
| { | |||||
| case ON::LengthUnitSystem::CustomUnits: | |||||
| pt_unit_system = ON::LengthUnitSystem::Meters; | |||||
| pt_scale = ON::UnitScale(pt_unit_system,point_value_unit_system); | |||||
| break; | |||||
| default: | |||||
| pt_unit_system = point_value_unit_system.UnitSystem(); | |||||
| pt_scale = 1.0; | |||||
| break; | |||||
| } | |||||
| const int str_index = ON_ParsePointExpression( | |||||
| str, str_count, | |||||
| parse_settings, | |||||
| pt_unit_system, | |||||
| point_value, | |||||
| parse_results | |||||
| ); | |||||
| if ( point_value && str_index > 0 && 1.0 != pt_scale ) | |||||
| { | |||||
| if ( ON_IsValid(point_value->x) ) | |||||
| point_value->x *= pt_scale; | |||||
| if ( ON_IsValid(point_value->y) ) | |||||
| point_value->y *= pt_scale; | |||||
| if ( ON_IsValid(point_value->z) ) | |||||
| point_value->z *= pt_scale; | |||||
| } | |||||
| return str_index; | |||||
| } | |||||
| ON_2dVector CosineAndSine(double a) | |||||
| { | |||||
| ON_2dVector v; | |||||
| if ( ON_IsValid(a) ) | |||||
| { | |||||
| v.x = cos(a); | |||||
| v.y = sin(a); | |||||
| if ( fabs(v.x) >= ON_EPSILON || fabs(v.y) <= ON_EPSILON ) | |||||
| { | |||||
| v.x = (v.x < 0.0) ? -1.0 : 1.0; | |||||
| v.y = 0.0; | |||||
| } | |||||
| else if ( fabs(v.y) >= ON_EPSILON || fabs(v.x) <= ON_EPSILON ) | |||||
| { | |||||
| v.y = (v.y < 0.0) ? -1.0 : 1.0; | |||||
| v.x = 0.0; | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| v = ON_2dVector::NanVector; | |||||
| } | |||||
| return v; | |||||
| } | |||||
| int ON_ParsePointExpression( | |||||
| const wchar_t* str, | |||||
| int str_count, | |||||
| ON_ParseSettings parse_settings, | |||||
| ON::LengthUnitSystem point_value_unit_system, | |||||
| ON_3dPoint* point_value, | |||||
| ON_ParseSettings* parse_results | |||||
| ) | |||||
| { | |||||
| ON_2dVector cos_sin_a0, cos_sin_a1; | |||||
| double x = ON_UNSET_VALUE, y = ON_UNSET_VALUE, z = 0.0; | |||||
| double r = ON_UNSET_VALUE, polar_angle = ON_UNSET_VALUE, spherical_angle = ON_UNSET_VALUE; | |||||
| if ( point_value ) | |||||
| *point_value = ON_3dPoint::Origin; | |||||
| if ( parse_results) | |||||
| *parse_results = ON_ParseSettings::FalseSettings; | |||||
| ON_ParseSettings prx(ON_ParseSettings::FalseSettings); | |||||
| ON_ParseSettings pry(ON_ParseSettings::FalseSettings); | |||||
| ON_ParseSettings prz(ON_ParseSettings::FalseSettings); | |||||
| int str_index = 0; | |||||
| bool bPolarAngle = false; | |||||
| for(;;) | |||||
| { | |||||
| if ( -1 == str_count ) | |||||
| str_count = ON_ParseSettings::max_expression_str_count; | |||||
| if ( str_count <= 0 ) | |||||
| break; | |||||
| int i0 = 0; | |||||
| if ( parse_settings.ParseLeadingWhiteSpace() ) | |||||
| { | |||||
| while ( i0 < str_count && parse_settings.IsLeadingWhiteSpace(str[i0]) ) | |||||
| i0++; | |||||
| if ( i0 >= str_count ) | |||||
| break; | |||||
| parse_settings.SetParseLeadingWhiteSpace(false); | |||||
| } | |||||
| int i1 = ON_ParseLengthExpression( | |||||
| str+i0, str_count-i0, | |||||
| parse_settings, | |||||
| point_value_unit_system, | |||||
| &x, | |||||
| &prx, | |||||
| 0 | |||||
| ); | |||||
| if ( i1 < 1) | |||||
| break; | |||||
| i1 += i0; | |||||
| if ( i1 == str_count && i0+1 == i1 && '0' == str[i0] && 0.0 == x ) | |||||
| { | |||||
| // world origin specified as a single zero. | |||||
| y = 0.0; | |||||
| z = 0.0; | |||||
| str_index = i0+i1; | |||||
| break; | |||||
| } | |||||
| if ( i1 >= str_count ) | |||||
| break; | |||||
| if ( i1+2 <= str_count && str[i1] == ',' && str[i1+1] == '<' ) | |||||
| { | |||||
| // It is a common for people to type "d,<a" instead of "d<a" | |||||
| // and this clause allows them to do it. | |||||
| i1++; | |||||
| if ( i1 >= str_count) | |||||
| break; | |||||
| } | |||||
| int i2; | |||||
| if ( str[i1] != ',' ) | |||||
| { | |||||
| i1++; | |||||
| if ( i1 >= str_count ) | |||||
| break; | |||||
| i2 = ON_ParseLengthExpression( | |||||
| str+i1, str_count-i1, | |||||
| parse_settings, | |||||
| point_value_unit_system, | |||||
| &y, | |||||
| &pry, | |||||
| 0 | |||||
| ); | |||||
| if ( i2 > 0 && i1+i0 <= str_count && ON_IsValid(x) && ON_IsValid(y) ) | |||||
| { | |||||
| r = ON_2dVector(x,y).Length(); | |||||
| } | |||||
| } | |||||
| else if ( str[i1] == '<' ) | |||||
| { | |||||
| bPolarAngle = true; | |||||
| r = x; | |||||
| x = ON_UNSET_VALUE; | |||||
| i1++; | |||||
| if ( i1 >= str_count ) | |||||
| break; | |||||
| i2 = ON_ParseAngleExpression( | |||||
| str+i1, str_count-i1, | |||||
| parse_settings, | |||||
| ON::AngleUnitSystem::Radians, | |||||
| &polar_angle, | |||||
| &pry, | |||||
| 0 | |||||
| ); | |||||
| if ( i2 > 0 && i1+i0 <= str_count && ON_IsValid(polar_angle) && ON_IsValid(r) ) | |||||
| { | |||||
| cos_sin_a0 = CosineAndSine(polar_angle); | |||||
| x = r*cos_sin_a0.x; | |||||
| y = r*cos_sin_a0.y; | |||||
| } | |||||
| else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| else if ( i0+1 == i1 && '0' == str[i0] && 0.0 == x ) | |||||
| { | |||||
| // single 0 for origin | |||||
| y = 0.0; | |||||
| str_index = i1; | |||||
| pry = ON_ParseSettings::FalseSettings; | |||||
| break; | |||||
| } | |||||
| else | |||||
| { | |||||
| i2 = 0; | |||||
| } | |||||
| if ( i2 <= 0 ) | |||||
| break; | |||||
| i2 += i1; | |||||
| if ( i2 >= str_count ) | |||||
| { | |||||
| // 2d point | |||||
| str_index = i2; | |||||
| break; | |||||
| } | |||||
| if ( i2+2 <= str_count && str[i2] == ',' && str[i2+1] == '<' ) | |||||
| { | |||||
| // It is a common for people to type "x,y,<a" instead of "x,y<a" | |||||
| // and this clause allows them to do it. | |||||
| i2++; | |||||
| if ( i2 >= str_count ) | |||||
| break; | |||||
| } | |||||
| int i3; | |||||
| if ( str[i2] == ',' ) | |||||
| { | |||||
| i2++; | |||||
| if ( i2 >= str_count ) | |||||
| break; | |||||
| i3 = ON_ParseLengthExpression( | |||||
| str+i2, str_count-i2, | |||||
| parse_settings, | |||||
| point_value_unit_system, | |||||
| &z, | |||||
| &prz, | |||||
| 0 | |||||
| ); | |||||
| } | |||||
| else if ( str[i2] == '<' ) | |||||
| { | |||||
| // spherical angle | |||||
| i3 = ON_ParseAngleExpression( | |||||
| str+i2, str_count-i2, | |||||
| parse_settings, | |||||
| ON::AngleUnitSystem::Radians, | |||||
| &spherical_angle, | |||||
| &prz, | |||||
| 0 | |||||
| ); | |||||
| if ( i3 <= 0 || i2+i3 > str_count ) | |||||
| break; | |||||
| if ( !ON_IsValid(spherical_angle) || !ON_IsValid(r) || !(r >= 0.0) ) | |||||
| break; | |||||
| cos_sin_a1 = CosineAndSine(spherical_angle); | |||||
| if ( bPolarAngle ) | |||||
| { | |||||
| // spherical coordinates (r<a<e) | |||||
| if ( cos_sin_a1.x >= 0.0 ) | |||||
| { | |||||
| x = r*cos_sin_a1.x; | |||||
| y = r*cos_sin_a1.x; | |||||
| z = r*cos_sin_a1.y; | |||||
| } | |||||
| else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| else if ( cos_sin_a1.x > 0.0 ) | |||||
| { | |||||
| // elevation (x,y<e) | |||||
| double tan_a = tan(spherical_angle); | |||||
| if ( ON_IsValid(tan_a) ) | |||||
| z = r*tan_a; | |||||
| else | |||||
| break; | |||||
| } | |||||
| else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| // 2d point | |||||
| str_index = i2; | |||||
| break; | |||||
| } | |||||
| if ( i3 <= 0 ) | |||||
| break; | |||||
| i3 += i2; | |||||
| if ( i3 > str_count ) | |||||
| break; | |||||
| str_index = i3; | |||||
| break; | |||||
| } | |||||
| if ( str_index > 0 ) | |||||
| { | |||||
| if ( point_value ) | |||||
| { | |||||
| point_value->x = x; | |||||
| point_value->y = y; | |||||
| point_value->z = z; | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| if ( !prx.ParseError() ) | |||||
| prx = ON_ParseSettings::FalseSettings; | |||||
| if ( !pry.ParseError() ) | |||||
| pry = ON_ParseSettings::FalseSettings; | |||||
| if ( !prz.ParseError() ) | |||||
| prz = ON_ParseSettings::FalseSettings; | |||||
| } | |||||
| if ( parse_results ) | |||||
| { | |||||
| *parse_results = (prx || pry || prz); | |||||
| } | |||||
| return str_index; | |||||
| } | |||||