1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0028599: Replacement of old Boolean operations with new ones in BRepProj_Projection algorithm

The usage of *BRepAlgo_Section* has been replaced with the usage of *BRepAlgoAPI_Section* in *BRepProj_Projection* algorithm.

The TODO statements have been removed from the failing test case in the "prj" grid as they are working correctly now.

The following changes have been made to improve the performance *BRepAlgoAPI_Section*:
1. Revision of the *IntPolyh_Intersection* class to avoid repeated calculation of the deflection of the same triangulation.
2. Small revision of the Edge/Face intersection algorithm to perform Extrema computation on the whole intersection range of the edge instead of discrete ranges.
3. Implementation of the extrema computation for the Circle and Sphere.
4. Correct computation of the parameter of the point on the Circle.
This commit is contained in:
emv
2017-12-26 14:28:27 +03:00
committed by apn
parent 95f688263d
commit 03cca6f742
50 changed files with 2340 additions and 1978 deletions

View File

@@ -0,0 +1,18 @@
puts "========"
puts "OCC29426"
puts "========"
puts ""
########################################
# Extrema algorithm fails to find minimal distance between Circle and Sphere
########################################
circle c 3.59679185933224e-016 11.6635040382361 -3.23970209548358 -3.67401855705945e-017 -0.943656647634893 0.330926172090505 -2.2723161366922e-016 0.330926172090505 0.943656647634893 1.30000000000039
sphere s 0 2.425 0 0 1 0 1 -0 0 9.876
set log [extrema c s]
if {![regexp "Point" $log]} {
set ext_dist [lindex [length ext_1] end]
checkreal "Circle/Sphere min distance" $ext_dist 0. 1.e-10 1.e-10
}

View File

@@ -0,0 +1,17 @@
puts "========"
puts "OCC29426"
puts "========"
puts ""
########################################
# Extrema algorithm fails to find minimal distance between Circle and Sphere
########################################
circle c 3.53600008984273e-016 11.5073628633636 -3.18494573739955 -3.67401855705945e-017 -0.943656647634893 0.330926172090505 -2.2723161366922e-016 0.330926172090505 0.943656647634893 1.30000000000039
sphere s 0 2.425 0 0 1 0 1 -0 0 9.712
set log [extrema c s]
if {![regexp "Point" $log]} {
set ext_dist [lindex [length ext_1] end]
checkreal "Circle/Sphere min distance" $ext_dist 0. 1.e-10 1.e-10
}

View File

@@ -0,0 +1,127 @@
puts "======================="
puts "Test for Circle/Sphere extrema algorithm"
puts "Intersection case (two intersection points should be found"
puts "======================="
puts ""
# Make sphere
set x0 0.
set y0 0.
set z0 0.
set sph_radius 10.
sphere s $x0 $y0 $z0 $sph_radius
# All circles will be to connect the two points - one inside the sphere, another - outside.
# Such circle will definitely intersect the initial sphere in two points.
# The points to make the circle will taken two spheres - with smaller and bigger radius.
# Set the number of iterations (number of pairs of spheres)
set nbpairs 2
# Set ratio to increase/decrease the radius if additional spheres
set ratio_radius 2.
# Number of sampling points on the spheres
set nbsamples 5
# Number of circles rotations
set nbsteps 5
set angle [expr 180. / $nbsteps]
# Iteration step
set iStep 1
for {set i 1} {$i <= $nbpairs} {incr i} {
# Define the radius for spheres
set s_in_radius [expr $sph_radius / ($i * $ratio_radius)]
set s_out_radius [expr $sph_radius * ($i * $ratio_radius)]
# Make the spheres
sphere s_in $x0 $y0 $z0 $s_in_radius
sphere s_out $x0 $y0 $z0 $s_out_radius
# Make the sampling of the spheres
# spheres are the same, so there is no difference from which one to take the parameters
bounds s_in umin umax vmin vmax
set du [dval (umax-umin)/$nbsteps]
set dv [dval (vmax-vmin)/$nbsteps]
for {set u1 1} {$u1 <= $nbsamples} {incr u1} {
for {set v1 1} {$v1 <= $nbsamples} {incr v1} {
# point on inner sphere
svalue s_in [dval umin+$u1*$du] [dval vmin+$v1*$dv] x1 y1 z1
for {set u2 1} {$u2 <= $nbsamples} {incr u2} {
for {set v2 1} {$v2 <= $nbsamples} {incr v2} {
# point on outer sphere
svalue s_out [dval umin+$u2*$du] [dval vmin+$v2*$dv] x2 y2 z2
# rotation direction
set dx [dval x2-x1]
set dy [dval y2-y1]
set dz [dval z2-z1]
# center of the circle
set xc [dval (x1+x2)/2.]
set yc [dval (y1+y2)/2.]
set zc [dval (z1+z2)/2.]
# compute radius for circle
set cir_radius [expr sqrt($dx*$dx + $dy*$dy + $dz*$dz) / 2.]
# make plane to get its XAxis
plane p $xc $yc $zc $dx $dy $dz
regexp {XAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump p] full dxx dxy dxz
circle c $xc $yc $zc $dxx $dxy $dxz $cir_radius
# make rotation
copy c c_rotated
for {set j 1} {$j <= $nbsteps} {incr j} {
rotate c_rotated $xc $yc $zc $dx $dy $dz $angle
set log [extrema c_rotated s]
# save each circle if necessary
# copy c_rotated c_$iStep
set isfound1 0
set isfound2 0
if {[regexp "ext_1" $log]} {
set ext_dist [lindex [length ext_1] end]
checkreal "Step $iStep, min distance 1" $ext_dist 0 1.e-7 1.e-7
set isfound1 1
}
if {[regexp "ext_2" $log]} {
set ext_dist [lindex [length ext_2] end]
checkreal "Step $iStep, min distance 2" $ext_dist 0 1.e-7 1.e-7
set isfound2 1
}
if {[regexp "Extrema 1 is point" $log]} {
puts "Check of Step $iStep, min distance 1 OK"
set isfound1 1
}
if {[regexp "Extrema 2 is point" $log]} {
puts "Check of Step $iStep, min distance 2 OK"
set isfound2 1
}
if {$isfound1 == 0 || $isfound2 == 0} {
puts "Error: Extrema has not detected the intersection case on step $iStep"
}
incr iStep
}
}
}
}
}
}

View File

@@ -0,0 +1,160 @@
puts "======================="
puts "Test for Circle/Sphere extrema algorithm"
puts "No intersection cases - one minimum solution should be found"
puts "======================="
puts ""
# Make sphere
set x0 0.
set y0 0.
set z0 0.
set sph_radius 10.
sphere s $x0 $y0 $z0 $sph_radius
# The circles will be made on the distance from the surface
# as intersection of pairs of inner and outer spheres with the plane
# Set the number of iterations
set nbstep 5
# Rotation angle
set angle [expr 180. / $nbstep]
# Set the number of Inner/Outer spheres in one direction
set nbpairs 1
# Set the delta for the radius of inner circle
set delta_radius [expr $sph_radius * 0.9 / (2 * $nbpairs)]
# Step for sampling of the circle
set dt [expr [dval 2*pi] / $nbstep]
# Iteration step
set iStep 1
for {set i 1} {$i <= $nbpairs} {incr i} {
# Define the inner circle
set circ_radius [expr $i * $delta_radius]
circle c $x0 $y0 $z0 0 0 1 $circ_radius
set diff [expr $sph_radius - $circ_radius]
# Distance between inner sphere on circle and initial sphere
set real_dist [expr $sph_radius - 2*$circ_radius]
# Circle will be rotated around the line
line rotation_line $x0 $y0 $z0 1 0 0
# Line rotation
for {set j 1} {$j <= $nbstep} {incr j} {
rotate rotation_line $x0 $y0 $z0 0 0 1 $angle
# Get direction for circle's rotation
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz
# Circle rotation
copy c c_rotated
for {set k 1} {$k <= $nbstep} {incr k} {
rotate c_rotated 0 0 0 $dx $dy $dz $angle
# Sampling of the circle
for {set n 1} {$n <= $nbstep} {incr n} {
cvalue c_rotated $n*$dt x1 y1 z1
set x1 [dval x1]
set y1 [dval y1]
set z1 [dval z1]
# Normalize the vector
set dtx [expr ($x1 - $x0) / $circ_radius]
set dty [expr ($y1 - $y0) / $circ_radius]
set dtz [expr ($z1 - $z0) / $circ_radius]
# Create inner and outer spheres
set iC 1
repeat 2 {
sphere s_to_int $x1 $y1 $z1 $circ_radius
# Define the point closest to the initial sphere
set x_sol [expr $x1 + $iC * $circ_radius * $dtx]
set y_sol [expr $y1 + $iC * $circ_radius * $dty]
set z_sol [expr $z1 + $iC * $circ_radius * $dtz]
# Intersect the sphere with the plane originated in closes point
# Make the sampling of the sphere to define section plane's direction
bounds s_to_int umin umax vmin vmax
set du [dval (umax-umin)/$nbstep]
set dv [dval (vmax-vmin)/$nbstep]
for {set u 1} {$u <= $nbstep} {incr u} {
for {set v 1} {$v <= $nbstep} {incr v} {
# Get point on surface
svalue s_to_int [dval umin+$u*$du] [dval vmin+$v*$dv] xs ys zs
# Check that it is not the same point
set sqdist [dval (xs-$x_sol)*(xs-$x_sol)+(ys-$y_sol)*(ys-$y_sol)+(zs-$z_sol)*(zs-$z_sol)]
if {$sqdist < 1.e-16} {
# Skip the sampling point
continue;
}
# Create the intersection plane
plane p_int $x_sol $y_sol $z_sol [dval xs-$x_sol] [dval ys-$y_sol] [dval zs-$z_sol]
# Intersect the sphere by plane to obtain the circle
foreach c_int [intersect c_inter s_to_int p_int] {
# Check if the circle contains the point
if {![regexp "Point on curve" [proj $c_int $x_sol $y_sol $z_sol]]} {
if {[lindex [length ext_1] end] >= 1.e-7} {
# run extrema - one of the ends of the curve should be the solution
set log [extrema $c_int s 1]
if {[regexp "prm_1_1" $log]} {
# get parameters of the curve
bounds $c_int fp lp
if {[dval prm_1_1-fp] > 1.e-7 && [dval lp-prm_1_1] > 1.e-7} {
puts "Error: Extrema has failed to find the minimal distance on step $iStep"
}
} else {
puts "Error: Extrema has failed to find the minimal distance on step $iStep"
}
# save each circle if necessary
# copy $c_int c_$iStep
incr iStep
continue
}
}
# Make extrema computation
set log [extrema $c_int s]
# save each circle if necessary
# copy $c_int c_$iStep
if {![regexp "ext_1" $log]} {
puts "Error: Extrema has failed to find the minimal distance on step $iStep"
} else {
set ext_dist [lindex [length ext_1] end]
checkreal "Step $iStep, min distance " $ext_dist $real_dist 1.e-7 1.e-7
}
incr iStep
}
}
}
# prepare for the outer sphere
set x1 [expr $x1 + 2 * $diff * $dtx]
set y1 [expr $y1 + 2 * $diff * $dty]
set z1 [expr $z1 + 2 * $diff * $dtz]
set iC -1
}
}
}
}
}

View File

@@ -0,0 +1,82 @@
puts "======================="
puts "Test for Circle/Sphere extrema algorithm"
puts "Parallel case (center of sphere is on the circle's axis)"
puts "======================="
puts ""
# Make sphere
set x0 0.
set y0 0.
set z0 0.
set sph_radius 10.
sphere s $x0 $y0 $z0 $sph_radius
# Initially the circle will be made at the same place as sphere with different radius
# and will be rotated and shifted many times.
# The distance between circle and sphere is a Abs(sqrt(centers_dist^2 + circ_radius^2) - sph_radius)
# Number of different radius of initial circle
set nb_radius 7
# Number of circle's rotations
set nbstep 8
set angle [expr 180. / $nbstep]
# Define the shift
set shift_start -3
set shift_end 3
set shift 4
# Iteration step
set iStep 1
for {set i 1} {$i < $nb_radius} {incr i} {
set circ_radius [expr $i*2.]
circle c $x0 $y0 $z0 0 0 1 $circ_radius
# Circle will be rotated around the line
line rotation_line $x0 $y0 $z0 1 0 0
# Line rotation
for {set j 1} {$j <= $nbstep} {incr j} {
rotate rotation_line $x0 $y0 $z0 0 0 1 $angle
# Get direction for circle's rotation
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz
# Circle rotation
copy c c_rotated
for {set k 1} {$k <= $nbstep} {incr k} {
rotate c_rotated $x0 $y0 $z0 $dx $dy $dz $angle
# Add shift of the circle along its own axis
# Get shift direction
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dcx dcy dcz
set dcx [expr $shift*$dcx]
set dcy [expr $shift*$dcy]
set dcz [expr $shift*$dcz]
# Make the shift
for {set t $shift_start} {$t <= $shift_end} {incr t} {
copy c_rotated c_shifted
translate c_shifted $t*$dcx $t*$dcy $t*$dcz
set log [extrema c_shifted s]
# save each circle if necessary
# copy c_shifted c_$iStep
if {![regexp "Infinite number of extremas" $log]} {
puts "Error: Extrema has not detected the parallel case on step $iStep"
} else {
regexp {Center :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_shifted] full x y z
set centers_dist [expr sqrt($x*$x + $y*$y + $z*$z)]
set real_dist [expr abs(sqrt($centers_dist*$centers_dist + $circ_radius*$circ_radius) - $sph_radius)]
set ext_dist [lindex $log end]
checkreal "Step $iStep, min distance " $ext_dist $real_dist 1.e-7 1.e-7
}
incr iStep
}
}
}
}

View File

@@ -0,0 +1,93 @@
puts "======================="
puts "Test for Circle/Sphere extrema algorithm"
puts "Touch case (circle is just touching the sphere)"
puts "======================="
puts ""
# Make sphere
set x0 0.
set y0 0.
set z0 0.
set sph_radius 10.
sphere s $x0 $y0 $z0 $sph_radius
# Initially the circle will be made at the same place as sphere with different radius
# and will shifted many times to touch the sphere.
# The distance should always be close to zero.
# Number of different radius of initial circle
set nb_radius 7
# Number of circle's rotations
set nbstep 8
set angle [expr 180. / $nbstep]
# Iteration step
set iStep 1
for {set i 1} {$i < $nb_radius} {incr i} {
set circ_radius [expr $i*2.]
if {$circ_radius == $sph_radius} {
set circ_radius [expr $circ_radius + 0.1]
}
circle c $x0 $y0 $z0 0 0 1 $circ_radius
# Circle will be rotated around the line
line rotation_line $x0 $y0 $z0 1 0 0
# Line rotation
for {set j 1} {$j <= $nbstep} {incr j} {
rotate rotation_line $x0 $y0 $z0 0 0 1 $angle
# Get direction for circle's rotation
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz
# Circle rotation
copy c c_rotated
for {set k 1} {$k <= $nbstep} {incr k} {
rotate c_rotated $x0 $y0 $z0 $dx $dy $dz $angle
# Get translation axis for the circle
regexp {XAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dxx dxy dxz
# Get rotation plane for translation line
regexp {YAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dyx dyy dyz
line translation_line $x0 $y0 $z0 $dxx $dxy $dxz
for {set n 1} {$n <= $nbstep} {incr n} {
rotate translation_line $x0 $y0 $z0 $dyx $dyy $dyz $angle
# Get direction for circle's translation
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump translation_line] full dtx dty dtz
# Circle's translation
copy c_rotated c_shifted
translate c_shifted $sph_radius*$dtx $sph_radius*$dty $sph_radius*$dtz
# Shift circle to touch sphere
set shift -1
repeat 2 {
copy c_shifted c_touch
translate c_touch $shift*$circ_radius*$dxx $shift*$circ_radius*$dxy $shift*$circ_radius*$dxz
set log [extrema c_touch s]
# save each circle if necessary
# copy c_touch c_$iStep
if {![regexp "ext_1" $log]} {
if {![regexp "Extrema 1 is point" $log]} {
puts "Error: Extrema has not detected the touching case on step $iStep"
} else {
puts "Check of Step $iStep, min distance OK"
}
} else {
set ext_dist [lindex [length ext_1] end]
checkreal "Step $iStep, min distance " $ext_dist 0 1.e-7 1.e-7
}
incr iStep
set shift 1
}
}
}
}
}