@@ -2265,3 +2265,207 @@ def test_mixed_constraint_types_export(self, adapter):
22652265
22662266 assert horizontal_line is not None , "Should have a horizontal line"
22672267 assert vertical_line is not None , "Should have a vertical line"
2268+
2269+
2270+ class TestSolidWorksExportRegression :
2271+ """Regression tests for export edge cases discovered via SketchBridge demo.
2272+
2273+ These tests verify fixes for issues found when exporting the comprehensive
2274+ SketchBridge demo sketch to SolidWorks.
2275+ """
2276+
2277+ def test_arc_270_degrees_not_circle (self , adapter ):
2278+ """Test that a 270-degree arc is exported as Arc, not Circle.
2279+
2280+ Regression test for: Large arcs (>180°) being incorrectly identified
2281+ as full circles due to arc length comparison tolerance issues.
2282+ """
2283+ sketch = SketchDocument (name = "Arc270Test" )
2284+ # 270 degree CCW arc (from right going up and around to bottom)
2285+ # This is similar to the tangent arc in the demo that was incorrectly exported
2286+ sketch .add_primitive (Arc (
2287+ center = Point2D (95 , 12.5 ),
2288+ start_point = Point2D (82 , 12.5 ), # Left of center (180°)
2289+ end_point = Point2D (95 , 25.5 ), # Top of center (90°)
2290+ ccw = True # Going CCW from 180° to 90° = 270° sweep
2291+ ))
2292+
2293+ adapter .create_sketch (sketch .name )
2294+ adapter .load_sketch (sketch )
2295+ exported = adapter .export_sketch ()
2296+
2297+ assert len (exported .primitives ) == 1 , "Should have exactly 1 primitive"
2298+ prim = list (exported .primitives .values ())[0 ]
2299+ assert isinstance (prim , Arc ), f"Should be Arc, not { type (prim ).__name__ } "
2300+ assert not isinstance (prim , Circle ), "Should not be a Circle"
2301+
2302+ def test_multiple_lines_correct_endpoints (self , adapter ):
2303+ """Test that multiple lines preserve their correct endpoints.
2304+
2305+ Regression test for: Line export matching wrong point pairs when
2306+ multiple lines exist in the sketch, especially with similar lengths.
2307+ """
2308+ sketch = SketchDocument (name = "MultipleLinesTest" )
2309+
2310+ # Create lines similar to the demo - rectangle plus angled lines
2311+ # Rectangle
2312+ sketch .add_primitive (Line (start = Point2D (0 , 0 ), end = Point2D (40 , 0 )))
2313+ sketch .add_primitive (Line (start = Point2D (40 , 0 ), end = Point2D (40 , 25 )))
2314+ sketch .add_primitive (Line (start = Point2D (40 , 25 ), end = Point2D (0 , 25 )))
2315+ sketch .add_primitive (Line (start = Point2D (0 , 25 ), end = Point2D (0 , 0 )))
2316+
2317+ # Angled line at 30 degrees (similar to demo's line_angled1)
2318+ angle_rad = math .radians (30 )
2319+ end_x = 110 + 25 * math .cos (angle_rad )
2320+ end_y = 25 * math .sin (angle_rad )
2321+ sketch .add_primitive (Line (start = Point2D (110 , 0 ), end = Point2D (end_x , end_y )))
2322+
2323+ adapter .create_sketch (sketch .name )
2324+ adapter .load_sketch (sketch )
2325+ exported = adapter .export_sketch ()
2326+
2327+ lines = [p for p in exported .primitives .values () if isinstance (p , Line )]
2328+ assert len (lines ) == 5 , f"Expected 5 lines, got { len (lines )} "
2329+
2330+ # Find the angled line (should have start at 110, 0)
2331+ angled_line = None
2332+ for ln in lines :
2333+ if abs (ln .start .x - 110 ) < 0.1 and abs (ln .start .y - 0 ) < 0.1 :
2334+ angled_line = ln
2335+ break
2336+
2337+ assert angled_line is not None , "Should find angled line starting at (110, 0)"
2338+ # End point should be near (131.65, 12.5), not (0, 25) or other wrong point
2339+ assert angled_line .end .x > 120 , \
2340+ f"Angled line end X should be > 120, got { angled_line .end .x } "
2341+ assert angled_line .end .y > 10 , \
2342+ f"Angled line end Y should be > 10, got { angled_line .end .y } "
2343+
2344+ def test_no_degenerate_zero_length_lines (self , adapter ):
2345+ """Test that no zero-length (degenerate) lines are exported.
2346+
2347+ Regression test for: SolidWorks creating internal degenerate segments
2348+ that get incorrectly exported as zero-length lines.
2349+ """
2350+ sketch = SketchDocument (name = "DegenerateLineTest" )
2351+
2352+ # Create a simple rectangle - should not produce any degenerate lines
2353+ sketch .add_primitive (Line (start = Point2D (0 , 0 ), end = Point2D (50 , 0 )))
2354+ sketch .add_primitive (Line (start = Point2D (50 , 0 ), end = Point2D (50 , 30 )))
2355+ sketch .add_primitive (Line (start = Point2D (50 , 30 ), end = Point2D (0 , 30 )))
2356+ sketch .add_primitive (Line (start = Point2D (0 , 30 ), end = Point2D (0 , 0 )))
2357+
2358+ adapter .create_sketch (sketch .name )
2359+ adapter .load_sketch (sketch )
2360+ exported = adapter .export_sketch ()
2361+
2362+ lines = [p for p in exported .primitives .values () if isinstance (p , Line )]
2363+
2364+ for ln in lines :
2365+ length = math .sqrt ((ln .end .x - ln .start .x )** 2 + (ln .end .y - ln .start .y )** 2 )
2366+ assert length > 0.01 , \
2367+ f"Found degenerate line from ({ ln .start .x } , { ln .start .y } ) to ({ ln .end .x } , { ln .end .y } )"
2368+
2369+ def test_ellipse_no_extra_standalone_points (self , adapter ):
2370+ """Test that ellipse export doesn't create extra standalone points.
2371+
2372+ Regression test for: SolidWorks internal ellipse vertex points being
2373+ incorrectly exported as standalone Point primitives.
2374+ """
2375+ sketch = SketchDocument (name = "EllipsePointsTest" )
2376+ sketch .add_primitive (Ellipse (
2377+ center = Point2D (30 , - 25 ),
2378+ major_radius = 18 ,
2379+ minor_radius = 10 ,
2380+ rotation = math .radians (15 )
2381+ ))
2382+
2383+ adapter .create_sketch (sketch .name )
2384+ adapter .load_sketch (sketch )
2385+ exported = adapter .export_sketch ()
2386+
2387+ # Should have only 1 primitive (the ellipse)
2388+ ellipses = [p for p in exported .primitives .values () if isinstance (p , Ellipse )]
2389+ points = [p for p in exported .primitives .values () if isinstance (p , Point )]
2390+
2391+ assert len (ellipses ) == 1 , f"Expected 1 ellipse, got { len (ellipses )} "
2392+ assert len (points ) == 0 , \
2393+ f"Expected 0 standalone points, got { len (points )} (ellipse vertex points leaked)"
2394+
2395+ def test_elliptical_arc_no_extra_standalone_points (self , adapter ):
2396+ """Test that elliptical arc export doesn't create extra standalone points.
2397+
2398+ Regression test for: SolidWorks internal elliptical arc vertex points
2399+ being incorrectly exported as standalone Point primitives.
2400+ """
2401+ sketch = SketchDocument (name = "EllipticalArcPointsTest" )
2402+ sketch .add_primitive (EllipticalArc (
2403+ center = Point2D (85 , - 25 ),
2404+ major_radius = 15 ,
2405+ minor_radius = 8 ,
2406+ rotation = math .radians (- 10 ),
2407+ start_param = math .radians (30 ),
2408+ end_param = math .radians (240 ),
2409+ ccw = True
2410+ ))
2411+
2412+ adapter .create_sketch (sketch .name )
2413+ adapter .load_sketch (sketch )
2414+ exported = adapter .export_sketch ()
2415+
2416+ # Should have only 1 primitive (the elliptical arc)
2417+ arcs = [p for p in exported .primitives .values () if isinstance (p , EllipticalArc )]
2418+ points = [p for p in exported .primitives .values () if isinstance (p , Point )]
2419+
2420+ assert len (arcs ) == 1 , f"Expected 1 elliptical arc, got { len (arcs )} "
2421+ assert len (points ) == 0 , \
2422+ f"Expected 0 standalone points, got { len (points )} (arc vertex points leaked)"
2423+
2424+ def test_line_with_negative_coordinates (self , adapter ):
2425+ """Test that lines with negative Y coordinates are correctly exported.
2426+
2427+ Regression test for: Potential issues with negative coordinate handling
2428+ in the line export logic.
2429+ """
2430+ sketch = SketchDocument (name = "NegativeCoordLineTest" )
2431+ # Line in negative Y region (like the midpoint_line in demo)
2432+ sketch .add_primitive (Line (start = Point2D (55 , - 15 ), end = Point2D (75 , - 15 )))
2433+
2434+ adapter .create_sketch (sketch .name )
2435+ adapter .load_sketch (sketch )
2436+ exported = adapter .export_sketch ()
2437+
2438+ lines = [p for p in exported .primitives .values () if isinstance (p , Line )]
2439+ assert len (lines ) == 1 , f"Expected 1 line, got { len (lines )} "
2440+
2441+ ln = lines [0 ]
2442+ # Check coordinates are preserved
2443+ assert abs (ln .start .x - 55 ) < 0.1 , f"Start X should be 55, got { ln .start .x } "
2444+ assert abs (ln .start .y - (- 15 )) < 0.1 , f"Start Y should be -15, got { ln .start .y } "
2445+ assert abs (ln .end .x - 75 ) < 0.1 , f"End X should be 75, got { ln .end .x } "
2446+ assert abs (ln .end .y - (- 15 )) < 0.1 , f"End Y should be -15, got { ln .end .y } "
2447+
2448+ def test_multiple_standalone_points_preserved (self , adapter ):
2449+ """Test that multiple standalone points are all preserved.
2450+
2451+ Regression test for: Some standalone points being lost during export
2452+ when multiple points exist in the sketch.
2453+ """
2454+ sketch = SketchDocument (name = "MultiplePointsTest" )
2455+ # Three points at different locations (like the demo's symmetric points)
2456+ sketch .add_primitive (Point (position = Point2D (5 , - 15 )))
2457+ sketch .add_primitive (Point (position = Point2D (35 , - 15 )))
2458+ sketch .add_primitive (Point (position = Point2D (65 , - 15 )))
2459+
2460+ adapter .create_sketch (sketch .name )
2461+ adapter .load_sketch (sketch )
2462+ exported = adapter .export_sketch ()
2463+
2464+ points = [p for p in exported .primitives .values () if isinstance (p , Point )]
2465+ assert len (points ) == 3 , f"Expected 3 points, got { len (points )} "
2466+
2467+ # Verify the specific positions are preserved
2468+ point_xs = sorted ([p .position .x for p in points ])
2469+ assert abs (point_xs [0 ] - 5 ) < 0.1 , f"First point X should be 5, got { point_xs [0 ]} "
2470+ assert abs (point_xs [1 ] - 35 ) < 0.1 , f"Second point X should be 35, got { point_xs [1 ]} "
2471+ assert abs (point_xs [2 ] - 65 ) < 0.1 , f"Third point X should be 65, got { point_xs [2 ]} "
0 commit comments