draftwright 0.4.10__tar.gz → 0.4.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {draftwright-0.4.10 → draftwright-0.4.11}/CHANGELOG.md +30 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/PKG-INFO +2 -2
- {draftwright-0.4.10 → draftwright-0.4.11}/docs/reference/recogniser-capabilities.md +5 -7
- {draftwright-0.4.10 → draftwright-0.4.11}/pyproject.toml +2 -2
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/_core.py +58 -11
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/_common.py +19 -1
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/from_model.py +2 -1
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/holes.py +65 -3
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/builder.py +335 -30
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/drawing.py +6 -3
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/coverage.py +81 -14
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/hole_coverage.py +6 -7
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/recogniser_contract.py +16 -50
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/sheet_emit.py +71 -8
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/view_plan.py +20 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/conftest.py +0 -2
- draftwright-0.4.11/tests/fixtures/grm04_drive_plate.step +1001 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_add_dimension.py +27 -1
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_adr0018_arrangement_gate.py +6 -3
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_external_recognition_boundary.py +5 -11
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1143_hole_completeness.py +5 -2
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1146_scale_completeness.py +29 -1
- draftwright-0.4.11/tests/test_issue_1155_grm04_sheet_use.py +44 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1187_unroutable_leaders.py +38 -1
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1202_observed_drawing_consumer.py +10 -6
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1217_the_facility_is_shared.py +3 -35
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1219_location_claims_its_own_axis.py +7 -10
- draftwright-0.4.11/tests/test_issue_443_grm03_axial_coverage.py +59 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_make_drawing.py +49 -6
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_note_verb.py +12 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_part_model.py +15 -23
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recogniser_adoption.py +3 -7
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recogniser_capabilities.py +15 -50
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_notes.py +28 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_tables.py +28 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_solve_trace.py +31 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_workflows.py +39 -0
- draftwright-0.4.10/tests/test_cross_repository_delivery_protocol.py +0 -27
- draftwright-0.4.10/tests/test_two_repository_workflow.py +0 -343
- {draftwright-0.4.10 → draftwright-0.4.11}/.gitignore +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/LICENSE +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/README.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/docs/adr/README.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/docs/reference/sheet.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/skills/SKILL.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/_geometry.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/_pmi_part21.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/_warnings.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/analysis.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotate.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/balloons.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/gears.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/leaders.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/orchestrator.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/annotations/sections.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/audit.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/cli.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/compose.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/evaluation/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/evaluation/step_analysis.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/export.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fits.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/intents.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/layout.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/channel_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/evidence.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/flat_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/gear_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/issues.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/pmi_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/polygonal_stock_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/quality.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/slot_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/structural.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/make_drawing.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/callout.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/compiled.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/declare.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/detect.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/ir.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/planner.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/model/pmi_lowering.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/pmi.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/projection.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/py.typed +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/recognition/__init__.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/recognition_cache.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/registry.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/repair.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/score.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/src/draftwright/sheet.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/_kernel.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/_layout_sig.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/README.md +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/blind-hole.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/corpus-v1.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/plain-block.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/topology-a.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/evaluation/topology-b.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/issue_915_case_study_2.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/bracket_section.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/grid_plate.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/grooved_shaft.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/pocketed.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/scattered_plate.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/side_drilled.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_adr0018_view_routing.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_adr0018_view_selection.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_agents_guide.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_api_docs.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_architecture_docs.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_audit_differential.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_balloon_ring_standoff.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_compiled_plan_boundary.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_counting_calls.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_declare.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_declared_recognition_gate.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_deprecation_dates.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_detect_once.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_detect_registry.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_dimension_role_vocabulary.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_drawing_encapsulation.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_e2e_slice.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_e2e_standards.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_export_dxf_curves.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_fits.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_flat_completeness.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_flat_stock_identity.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_flat_stock_opposition.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_gdt_placement.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_grid_lattice_convention.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_import_boundaries.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_iso_nts_caption_placement.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1000_envelope_reuse.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1058_wheel_profile.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1073_cross_body_patterns.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1082_polygonal_stock.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1086_declared_gears.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1130_view_planning_evidence.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1142_hole_leader_labels.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1144_transactional_hole_table.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1166_cross_pass_feature_leaders.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1176_quality_fidelity.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1177_angular_dimensions.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1188_per_view_assignment.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1190_section_decision.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1196_deterministic_view_names.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1204_multiscale_view_issues.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1215_envelope_tolerance.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1216_callout_reservation_measures_ink.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1217_claimed_representations.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1229_ledger_member_keying.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1254_turned_chamfers.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1260_view_constraints.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1276_turned_leader_targets.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_1281_turned_fillets.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_367_leader_ink.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_676_polygonal_boss.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_740_leader_assignment.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_798_floor_cardinality.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_798_material_field.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_798_silhouette_lint.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_885_prismatic_coverage.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_909_sloped_profile.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_915_dense_case.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_916_pocket_leader.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_917_open_channel.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_924_zero_length_shoulders.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_955_height_contingency.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_issue_958_cross_solid_recognition.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_label_provenance.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_layout.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_layout_cleanliness.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_layout_hypothesis.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_layout_property.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_leader_footprint.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_lint_reconciliation.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_lint_structural.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_linting.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_location_vocabulary.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_object_aspects.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_parameter_id.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pitch_dim_footprint.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pmi.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pmi_datum_lowering.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pmi_gtol_lowering.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pmi_part21.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pocket_pattern.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_pocket_pattern_recognition.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_principal_profile_classifier.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_private_test_attr_reads.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_private_test_imports.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_quality_components.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recogniser_contract.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recognition.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recognition_manifest.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_recognition_result.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_refactor_golden.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_registry.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_render_seam.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_repack_geometry_seam.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_score.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_script_detail_parity.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_shared_box_memo.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_emit.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_gdt.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_identity_invariant.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_of.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_sheet_section.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_slanted_blind_step.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_slot_completeness.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_slot_pattern.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_soft_deprecation.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_step_analysis_evaluation.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_strip_layout.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_suppression_ledger.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_suppression_marks.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_tolerances.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_turned_steps.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_view_plan.py +0 -0
- {draftwright-0.4.10 → draftwright-0.4.11}/tests/test_witness_label_reconciliation.py +0 -0
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Recogniser integration now uses only the exact `b123d-recognisers` dependency in
|
|
8
|
+
`pyproject.toml` and `uv.lock`. The separate release-evidence record, dependency-bump workflow,
|
|
9
|
+
candidate-checkout harness, and release-time capability-version rewrites have been removed;
|
|
10
|
+
ordinary compatibility tests validate the installed pinned package.
|
|
11
|
+
- Automatic composition now measures the next larger preferred scale when a conservative
|
|
12
|
+
crowded-detail reservation leaves a sparse sheet. A candidate wins only on the same paper
|
|
13
|
+
size, without the recovery detail, structural errors, or required-placement loss. GRM-04 now
|
|
14
|
+
uses A4 at 5:1 instead of 2:1, re-homes its shared side-hole Y location into the plan-view
|
|
15
|
+
corridor, and retains both the Ø2.4 diameter and location requirements (#1155).
|
|
16
|
+
- Closed the remaining dense-sheet leader cases as deliberate Policy-B behavior: exhaustive
|
|
17
|
+
route sweeps prove there is no route clear of both material and committed sheet ink, so the
|
|
18
|
+
required callout remains with an explicit crossing diagnostic instead of being dropped. A
|
|
19
|
+
fast synthetic release gate complements the retained exhaustive corpus characterization
|
|
20
|
+
(#1187).
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Notes and generic table cells now render U+2300 `⌀` with the established supported drafting
|
|
25
|
+
glyph instead of IBM Plex Mono's missing-glyph square. The substitution happens at the one
|
|
26
|
+
shared measurement/render seam, so source rows remain unchanged and table sizing stays exact
|
|
27
|
+
(#1275).
|
|
28
|
+
- Automatic turned-part composition now gives true shoulder coverage priority over optional
|
|
29
|
+
pictorial content. GRM-03 replans to 5:1 and renders its 0.5, 2, 3, and 18 mm axial lengths;
|
|
30
|
+
`axial_length_missing` disappears because the dimensions are present, not because the
|
|
31
|
+
diagnostic was suppressed (#443).
|
|
32
|
+
|
|
3
33
|
## v0.4.10 — 2026-08-22
|
|
4
34
|
|
|
5
35
|
**A view-set-aware planning and turned-edge-treatment patch.** Authored view constraints now
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.11
|
|
4
4
|
Summary: Automated technical-drawing generation for build123d
|
|
5
5
|
Project-URL: Homepage, https://github.com/pzfreo/draftwright
|
|
6
6
|
Project-URL: Repository, https://github.com/pzfreo/draftwright
|
|
@@ -684,7 +684,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
684
684
|
Classifier: Topic :: Scientific/Engineering
|
|
685
685
|
Requires-Python: <3.15,>=3.10
|
|
686
686
|
Requires-Dist: antlr4-python3-runtime<4.10
|
|
687
|
-
Requires-Dist: b123d-recognisers==0.3.
|
|
687
|
+
Requires-Dist: b123d-recognisers==0.3.1
|
|
688
688
|
Requires-Dist: build123d-drafting-helpers>=0.14.1
|
|
689
689
|
Requires-Dist: build123d<0.11,>=0.9.0; python_full_version < '3.13'
|
|
690
690
|
Requires-Dist: build123d<0.12,>=0.11; python_full_version >= '3.13'
|
|
@@ -49,13 +49,11 @@ Validation fails closed and names the family and boundary whenever possible:
|
|
|
49
49
|
|
|
50
50
|
## Adding or changing a recogniser
|
|
51
51
|
|
|
52
|
-
For an additive field that increments an existing record schema,
|
|
53
|
-
declaration
|
|
54
|
-
|
|
55
|
-
only
|
|
56
|
-
|
|
57
|
-
Draftwright dependency/behavior PR locks the immutable artifact, adopts the field, and narrows the
|
|
58
|
-
declaration to the new schema.
|
|
52
|
+
For an additive field that increments an existing record schema, update the relevant Draftwright
|
|
53
|
+
adapter and declaration when advancing the exact `b123d-recognisers` dependency pin. Tests must
|
|
54
|
+
prove the installed schema is accepted while later schemas still fail. The package version belongs
|
|
55
|
+
only in `pyproject.toml` and `uv.lock`; the capability declaration derives runtime identities from
|
|
56
|
+
installed package metadata.
|
|
59
57
|
|
|
60
58
|
For each applicable stage, add the adapter, declaration, emitted-Sheet round trip, drawing behavior,
|
|
61
59
|
and completeness evidence; for an inapplicable or deferred stage, state why and link its tracking
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwright"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.11"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -18,7 +18,7 @@ dependencies = [
|
|
|
18
18
|
"build123d>=0.9.0,<0.11 ; python_full_version < '3.13'",
|
|
19
19
|
"build123d>=0.11,<0.12 ; python_full_version >= '3.13'",
|
|
20
20
|
"build123d-drafting-helpers>=0.14.1",
|
|
21
|
-
"b123d-recognisers==0.3.
|
|
21
|
+
"b123d-recognisers==0.3.1",
|
|
22
22
|
"numpy>=1.24",
|
|
23
23
|
# PNG raster export (SVG→PDF→PNG). Both permissively licensed (Pillow HPND; pypdfium2
|
|
24
24
|
# Apache-2.0 wrapping Google PDFium BSD-3) and ship pre-built wheels with NO native system
|
|
@@ -57,6 +57,35 @@ from draftwright.layout import _greedy_strip_1d, _solve_strip_1d
|
|
|
57
57
|
_log = logging.getLogger(__name__)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
def _decode_hole_location_fact(fact):
|
|
61
|
+
"""Decode a current or legacy ``covers_hole_locations`` fact.
|
|
62
|
+
|
|
63
|
+
Current facts carry ``(feature, parameter, point)``. Legacy/external facts
|
|
64
|
+
carry ``(measurement, point)`` and derive ownership from the measurement.
|
|
65
|
+
Invalid or incomplete riders return ``None`` so consumers can retain their
|
|
66
|
+
geometric fallback instead of treating malformed metadata as authoritative.
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
size = len(fact)
|
|
70
|
+
except TypeError:
|
|
71
|
+
return None
|
|
72
|
+
if size == 3:
|
|
73
|
+
feature, parameter, point = fact
|
|
74
|
+
elif size == 2:
|
|
75
|
+
measurement, point = fact
|
|
76
|
+
feature = getattr(measurement, "feature", None)
|
|
77
|
+
parameter = getattr(measurement, "parameter", None)
|
|
78
|
+
else:
|
|
79
|
+
return None
|
|
80
|
+
if feature is None or not isinstance(parameter, str):
|
|
81
|
+
return None
|
|
82
|
+
try:
|
|
83
|
+
HoleRef.of(point)
|
|
84
|
+
except (AttributeError, TypeError, ValueError):
|
|
85
|
+
return None
|
|
86
|
+
return feature, parameter, point
|
|
87
|
+
|
|
88
|
+
|
|
60
89
|
def place_annotation(registry, items, obj, name=None, view=None, feature=None, measurement=None):
|
|
61
90
|
"""The annotation-placement primitive (#817): register *obj* under *name* — replacing any
|
|
62
91
|
prior object of that name (dropped from the render list *items*) so a name maps to one
|
|
@@ -168,6 +197,19 @@ def _wrap_rows(header, data, ncols):
|
|
|
168
197
|
return wide
|
|
169
198
|
|
|
170
199
|
|
|
200
|
+
def _font_safe_text(value) -> str:
|
|
201
|
+
"""Return the font-safe spelling used to measure and draw user text.
|
|
202
|
+
|
|
203
|
+
IBM Plex Mono does not contain U+2300 DIAMETER SIGN, so FreeType substitutes
|
|
204
|
+
its missing-glyph box. The drafting surface already uses U+00F8 LATIN SMALL
|
|
205
|
+
LETTER O WITH STROKE for diameter labels; use that established glyph at the
|
|
206
|
+
shared render seams as well. Keeping the substitution here makes free notes,
|
|
207
|
+
declared notes, title blocks, BOMs, revision tables, and hole tables measure
|
|
208
|
+
exactly the text they render while preserving the caller's semantic source data.
|
|
209
|
+
"""
|
|
210
|
+
return str(value).replace("⌀", "ø")
|
|
211
|
+
|
|
212
|
+
|
|
171
213
|
def _table_metrics(rows, font_size, pad_around_text, block_cols=None):
|
|
172
214
|
"""The sizing model of a data table: per-column left/right edges (page-mm,
|
|
173
215
|
block gaps inserted), total width/height, row height and effective block
|
|
@@ -186,7 +228,11 @@ def _table_metrics(rows, font_size, pad_around_text, block_cols=None):
|
|
|
186
228
|
bc = block_cols if (block_cols and ncol % block_cols == 0 and block_cols < ncol) else ncol
|
|
187
229
|
block_gap = 3 * pad # whitespace between side-by-side blocks
|
|
188
230
|
col_w = [
|
|
189
|
-
max(
|
|
231
|
+
max(
|
|
232
|
+
max(_text_width(_font_safe_text(r[c]), fs) for r in rows) + 2 * pad,
|
|
233
|
+
fs * 2.5,
|
|
234
|
+
)
|
|
235
|
+
for c in range(ncol)
|
|
190
236
|
]
|
|
191
237
|
# Per-column left/right edges, inserting block_gap before each new block.
|
|
192
238
|
lefts, rights, cursor = [], [], 0.0
|
|
@@ -232,11 +278,12 @@ def _build_table(rows, draft, block_cols=None):
|
|
|
232
278
|
for ri, row in enumerate(rows): # rows[0] (header) sits at the top
|
|
233
279
|
cy = total_h - (ri + 0.5) * row_h
|
|
234
280
|
for ci, cell in enumerate(row):
|
|
235
|
-
|
|
281
|
+
display = _font_safe_text(cell)
|
|
282
|
+
if not display:
|
|
236
283
|
continue
|
|
237
284
|
cx = (lefts[ci] + rights[ci]) / 2
|
|
238
285
|
text = Text(
|
|
239
|
-
txt=
|
|
286
|
+
txt=display,
|
|
240
287
|
font_size=fs,
|
|
241
288
|
font_path=PLEX_MONO,
|
|
242
289
|
align=(Align.CENTER, Align.CENTER),
|
|
@@ -1158,15 +1205,15 @@ def _make_title_block(dwg, a: Analysis):
|
|
|
1158
1205
|
it, last) and :func:`_title_block_box` (which measures its footprint for GD&T avoidance, #481)
|
|
1159
1206
|
so the two never drift."""
|
|
1160
1207
|
tb = TitleBlock(
|
|
1161
|
-
a.title,
|
|
1162
|
-
a.number,
|
|
1208
|
+
_font_safe_text(a.title),
|
|
1209
|
+
_font_safe_text(a.number),
|
|
1163
1210
|
scale=format_drawing_scale(a.SCALE),
|
|
1164
|
-
general_tolerance=a.tolerance,
|
|
1165
|
-
designed_by=_attribution_author(a.drawn_by),
|
|
1166
|
-
material=a.material,
|
|
1167
|
-
date=a.date,
|
|
1168
|
-
revision=a.revision,
|
|
1169
|
-
legal_owner=a.company,
|
|
1211
|
+
general_tolerance=_font_safe_text(a.tolerance),
|
|
1212
|
+
designed_by=_font_safe_text(_attribution_author(a.drawn_by)),
|
|
1213
|
+
material=_font_safe_text(a.material),
|
|
1214
|
+
date=_font_safe_text(a.date),
|
|
1215
|
+
revision=_font_safe_text(a.revision),
|
|
1216
|
+
legal_owner=_font_safe_text(a.company),
|
|
1170
1217
|
width=a.TB_W,
|
|
1171
1218
|
# Title block renders in condensed sans (the tight ISO 7200 cells), a
|
|
1172
1219
|
# different face from the monospace dimensions — so it carries its own
|
|
@@ -20,6 +20,7 @@ from build123d_drafting.helpers import DEFAULT_FONT_PATH, Dimension, Note, SafeD
|
|
|
20
20
|
|
|
21
21
|
from draftwright._core import ( # noqa: F401 — _anno_box re-exported (#700)
|
|
22
22
|
_anno_box,
|
|
23
|
+
_decode_hole_location_fact,
|
|
23
24
|
_text_size,
|
|
24
25
|
place_annotation,
|
|
25
26
|
)
|
|
@@ -129,7 +130,24 @@ def _annotation_hole_features(registry, name, annotation) -> frozenset:
|
|
|
129
130
|
if getattr(feature, "kind", None) in {"hole", "pattern"}:
|
|
130
131
|
features.add(feature)
|
|
131
132
|
for fact in getattr(annotation, "covers_hole_locations", ()):
|
|
132
|
-
|
|
133
|
+
decoded = _decode_hole_location_fact(fact)
|
|
134
|
+
if decoded is not None:
|
|
135
|
+
feature = decoded[0]
|
|
136
|
+
else:
|
|
137
|
+
# Replacement ownership is a broader question than whether a fact can
|
|
138
|
+
# prove axis-specific coverage. Legacy/external riders may carry only
|
|
139
|
+
# ``(measurement, point)``; retain that measurement's semantic owner
|
|
140
|
+
# even when it has no parameter and the strict decoder rightly refuses
|
|
141
|
+
# to treat it as location evidence.
|
|
142
|
+
try:
|
|
143
|
+
candidate = fact[0]
|
|
144
|
+
except (IndexError, TypeError):
|
|
145
|
+
continue
|
|
146
|
+
feature = (
|
|
147
|
+
candidate
|
|
148
|
+
if getattr(candidate, "kind", None) in {"hole", "pattern"}
|
|
149
|
+
else getattr(candidate, "feature", None)
|
|
150
|
+
)
|
|
133
151
|
if getattr(feature, "kind", None) in {"hole", "pattern"}:
|
|
134
152
|
features.add(feature)
|
|
135
153
|
for feature, _requirement, _count in getattr(
|
|
@@ -52,6 +52,7 @@ from draftwright._core import (
|
|
|
52
52
|
_dim,
|
|
53
53
|
_first_free_index,
|
|
54
54
|
_fmt,
|
|
55
|
+
_font_safe_text,
|
|
55
56
|
_greedy_strip_ys,
|
|
56
57
|
_iso_bbox,
|
|
57
58
|
_legible_locations,
|
|
@@ -5685,7 +5686,7 @@ def _gdt_glyph(item, draft):
|
|
|
5685
5686
|
if item.kind == "datum_ref":
|
|
5686
5687
|
return DatumFeature(item.letter, draft=draft)
|
|
5687
5688
|
if item.kind == "note": # free-text manufacturing note (#488) — a single-line text glyph
|
|
5688
|
-
return TextBlock([item.text], position=(0.0, 0.0), draft=draft)
|
|
5689
|
+
return TextBlock([_font_safe_text(item.text)], position=(0.0, 0.0), draft=draft)
|
|
5689
5690
|
return SurfaceFinish(item.ra, position=(0.0, 0.0), draft=draft)
|
|
5690
5691
|
|
|
5691
5692
|
|
|
@@ -816,6 +816,7 @@ def _locate_across(dwg, ctx, a: Analysis, off):
|
|
|
816
816
|
_locate_off_axis_holes (#638)."""
|
|
817
817
|
draft = dwg.draft
|
|
818
818
|
SX, SZ = a.proj.side_x, a.proj.side_z
|
|
819
|
+
PX, PY = a.proj.plan_x, a.proj.plan_y
|
|
819
820
|
dy, dz = a.bb.min.Y, a.bb.min.Z
|
|
820
821
|
tier = draft.font_size + 2 * draft.pad_around_text
|
|
821
822
|
yw = SZ(dz) - _WITNESS_LIFT_MM
|
|
@@ -825,6 +826,7 @@ def _locate_across(dwg, ctx, a: Analysis, off):
|
|
|
825
826
|
loc_by_name: dict = {} # dim name -> contributing hole locations (for provenance)
|
|
826
827
|
mids_by_name: dict = {}
|
|
827
828
|
coverage_by_name: dict = {}
|
|
829
|
+
plan_alternates: dict = {}
|
|
828
830
|
for h in (h for h in off if h.axis == "x"):
|
|
829
831
|
# The VALUE is the approved entry's; `dy` survives only as the witness anchor.
|
|
830
832
|
entry = h.approved.get("y")
|
|
@@ -854,8 +856,70 @@ def _locate_across(dwg, ctx, a: Analysis, off):
|
|
|
854
856
|
),
|
|
855
857
|
)
|
|
856
858
|
)
|
|
859
|
+
# #1155: the same Y ordinate reads vertically in plan. Keep the
|
|
860
|
+
# side-view location as the natural first choice, but retain this
|
|
861
|
+
# requirement-driven alternate for a full below-side corridor (GRM-04
|
|
862
|
+
# at 5:1 shares that short strip with the overall depth). This is a
|
|
863
|
+
# view reassignment through the shared strip solver, not a raw position.
|
|
864
|
+
plan_edge = PX(a.bb.max.X)
|
|
865
|
+
plan_lo = (plan_edge, PY(dy), 0)
|
|
866
|
+
plan_hi = (plan_edge, PY(h.location[1]), 0)
|
|
867
|
+
alt_name = f"dim_loc_plan_y{round(yo * 100)}"
|
|
868
|
+
plan_alternates[name] = (
|
|
869
|
+
alt_name,
|
|
870
|
+
lambda pos, pl=plan_lo, ph=plan_hi, e=plan_edge, lb=entry.value_text, nm=name: (
|
|
871
|
+
_with_hole_location_coverage(
|
|
872
|
+
_dim(pl, ph, "right", pos - e, draft, label=lb),
|
|
873
|
+
coverage_by_name[nm],
|
|
874
|
+
)
|
|
875
|
+
),
|
|
876
|
+
)
|
|
857
877
|
feats = {nm: _off_axis_owner(ctx, locs) for nm, locs in loc_by_name.items()}
|
|
858
878
|
measurements = {name: tuple(ids) for name, ids in mids_by_name.items()}
|
|
879
|
+
|
|
880
|
+
def _fallback(name):
|
|
881
|
+
# Every queued side candidate is created in the same block as its plan
|
|
882
|
+
# alternate above; a missing key is an internal invariant violation.
|
|
883
|
+
alt = plan_alternates[name]
|
|
884
|
+
alt_name = alt[0]
|
|
885
|
+
|
|
886
|
+
def _retry():
|
|
887
|
+
# A fallback is never allowed to create an annotation in a view the
|
|
888
|
+
# resolved plan omitted. It also runs only after every shared corridor
|
|
889
|
+
# has drained, so its solitary carve cannot preempt a later candidate.
|
|
890
|
+
if "plan" not in dwg.views:
|
|
891
|
+
_off_axis_drop(
|
|
892
|
+
dwg,
|
|
893
|
+
"y",
|
|
894
|
+
"side",
|
|
895
|
+
ctx=ctx,
|
|
896
|
+
measurement=measurements.get(name, ()),
|
|
897
|
+
)
|
|
898
|
+
return
|
|
899
|
+
if not _off_axis_emit(
|
|
900
|
+
dwg,
|
|
901
|
+
tier,
|
|
902
|
+
a.pv_zones.right,
|
|
903
|
+
"plan",
|
|
904
|
+
"x",
|
|
905
|
+
[alt],
|
|
906
|
+
force=False,
|
|
907
|
+
features={alt_name: feats.get(name)},
|
|
908
|
+
measurements={alt_name: measurements.get(name, ())},
|
|
909
|
+
ctx=ctx,
|
|
910
|
+
trace=ctx.trace,
|
|
911
|
+
):
|
|
912
|
+
return
|
|
913
|
+
_off_axis_drop(
|
|
914
|
+
dwg,
|
|
915
|
+
"y",
|
|
916
|
+
"side",
|
|
917
|
+
ctx=ctx,
|
|
918
|
+
measurement=measurements.get(name, ()),
|
|
919
|
+
)
|
|
920
|
+
|
|
921
|
+
ctx.post_drain.append(_retry)
|
|
922
|
+
|
|
859
923
|
_off_axis_queue(
|
|
860
924
|
dwg,
|
|
861
925
|
ctx,
|
|
@@ -867,9 +931,7 @@ def _locate_across(dwg, ctx, a: Analysis, off):
|
|
|
867
931
|
cands,
|
|
868
932
|
features=feats,
|
|
869
933
|
measurements=measurements,
|
|
870
|
-
on_drop=
|
|
871
|
-
dwg, "y", "side", ctx=ctx, measurement=measurements.get(nm, ())
|
|
872
|
-
),
|
|
934
|
+
on_drop=_fallback,
|
|
873
935
|
order_key=lambda nm, _i: order_y.get(nm, _i),
|
|
874
936
|
)
|
|
875
937
|
|