Utils { @Nullable public static Point2D findRectEdgeIntersection(@Nonnull final Rectangle2D rect, final double outboundX, final double outboundY) { final int detectedSide = rect.outcode(outboundX, outboundY); if ((detectedSide & (Rectangle2D.OUT_TOP | Rectangle2D.OUT_BOTTOM)) != 0) { final boolean top = (detectedSide & Rectangle2D.OUT_BOTTOM) == 0; final double dx = outboundX - rect.getCenterX(); if (dx == 0.0d) { return new Point2D.Double(rect.getCenterX(), top ? rect.getMinY() : rect.getMaxY()); } else { final double halfy = top ? rect.getHeight() / 2 : -rect.getHeight() / 2; final double coeff = (outboundY - rect.getCenterY()) / dx; final double calculatedX = rect.getCenterX() - (halfy / coeff); if (calculatedX >= rect.getMinX() && calculatedX <= rect.getMaxX()) { return new Point2D.Double(calculatedX, top ? rect.getMinY() : rect.getMaxY()); } } } if ((detectedSide & (Rectangle2D.OUT_LEFT | Rectangle2D.OUT_RIGHT)) != 0) { final boolean left = (detectedSide & Rectangle2D.OUT_RIGHT) == 0; final double dy = outboundY - rect.getCenterY(); if (dy == 0.0d) { return new Point2D.Double(left ? rect.getMinX() : rect.getMaxX(), rect.getCenterY()); } else { final double halfx = left ? rect.getWidth() / 2 : -rect.getWidth() / 2; final double coeff = (outboundX - rect.getCenterX()) / dy; final double calculatedY = rect.getCenterY() - (halfx / coeff); if (calculatedY >= rect.getMinY() && calculatedY <= rect.getMaxY()) { return new Point2D.Double(left ? rect.getMinX() : rect.getMaxX(), calculatedY); } } } return null; } private  Utils(); @Nullable static InputStream findInputStreamForResource(@Nonnull final ZipFile zipFile, @Nonnull final String resourcePath); @Nullable static byte[] toByteArray(@Nonnull final ZipFile zipFile, @Nonnull final String path); @Nonnull static Document loadHtmlDocument(@Nonnull final InputStream inStream, @Nullable final String charset, final boolean autoClose); @Nonnull static Document loadXmlDocument(@Nonnull final InputStream inStream, @Nullable final String charset, final boolean autoClose); @Nullable static Element findFirstElement(@Nonnull final Element node, @Nonnull final String elementName); @Nonnull @MustNotContainNull static List<Element> findDirectChildrenForName(@Nonnull final Element element, @Nonnull final String childElementname); static boolean isUriCorrect(@Nonnull final String uri); static int getMaxImageSize(); @Nullable static String rescaleImageAndEncodeAsBase64(@Nonnull final InputStream in, final int maxSize); @Nonnull static String rescaleImageAndEncodeAsBase64(@Nonnull final File file, final int maxSize); @Nonnull static RenderQuality getDefaultRenderQialityForOs(); @Nonnull static String rescaleImageAndEncodeAsBase64(@Nonnull Image image, final int maxSize); static int calculateColorBrightness(@Nonnull final Color color); static boolean isDarkTheme(); @Nonnull static String convertCamelCasedToHumanForm(@Nonnull final String camelCasedString, final boolean capitalizeFirstChar); @Nonnull @MustNotContainNull static Topic[] getLeftToRightOrderedChildrens(@Nonnull final Topic topic); static boolean safeObjectEquals(@Nullable final Object obj1, @Nullable final Object obj2); static void setAttribute(@Nonnull final String name, @Nullable final String value, @Nonnull @MustNotContainNull final Topic[] topics); @Nullable static Color html2color(@Nullable final String str, final boolean hasAlpha); @Nullable static String color2html(@Nullable final Color color, final boolean hasAlpha); @Nonnull static String getFirstLine(@Nonnull final String text); @Nonnull static String makeShortTextVersion(@Nonnull String text, final int maxLength); static void safeSwingCall(@Nonnull final Runnable runnable); static void safeSwingBlockingCall(@Nonnull final Runnable runnable); @Nonnull @MustNotContainNull static String[] breakToLines(@Nonnull final String text); static int numberOfLines(@Nonnull final String text); @ImplementationNote("Must be called from Swing UI thread") static void foldUnfoldTree(@Nonnull final JTree tree, final boolean unfold); static @Nonnull String removeAllISOControlsButTabs(@Nonnull final String str); @Nullable static Point2D findRectEdgeIntersection(@Nonnull final Rectangle2D rect, final double outboundX, final double outboundY); static boolean isPlantUmlFileExtension(@Nonnull final String lowerCasedTrimmedExtension); @Nullable static Image scaleImage(@Nonnull final Image src, final double baseScaleX, final double baseScaleY, final double scale); @Nonnull static Image renderWithTransparency(final float opacity, @Nonnull final AbstractElement element, @Nonnull final MindMapPanelConfig config, @Nonnull final RenderQuality quality); @Nonnull static Color makeContrastColor(@Nonnull final Color color); static void assertSwingDispatchThread(); static boolean isDataFlavorAvailable(@Nonnull final Clipboard clipboard, @Nonnull final DataFlavor flavor); @Nonnull static JPopupMenu makePopUp(
      @Nonnull final PluginContext context,
      final boolean fullScreenModeActive,
      @Nullable final Topic topicUnderMouse
  ); static boolean isKeyStrokeEvent(@Nullable final KeyStroke keyStroke, final int keyEventType, @Nullable final KeyEvent event); @Nonnull static byte[] base64decode(@Nonnull final String text); @Nonnull static String strip(@Nonnull final String str, final boolean leading); @Nonnull static String base64encode(@Nonnull final byte[] data); static final UIComponentFactory UI_COMPO_FACTORY; static final ImageIconService ICON_SERVICE; static final String PROPERTY_MAX_EMBEDDED_IMAGE_SIDE_SIZE; static final boolean LTR_LANGUAGE; }
@Test public void testFindRectEdgeIntersection() { final Rectangle2D rect = new Rectangle2D.Double(50, 50, 100, 50); assertEquals(new Point2D.Double(100d, 50d), Utils.findRectEdgeIntersection(rect, 100d, 25d)); assertEquals(new Point2D.Double(100d, 100d), Utils.findRectEdgeIntersection(rect, 100d, 125d)); assertEquals(new Point2D.Double(50d, 75d), Utils.findRectEdgeIntersection(rect, 10d, 75d)); assertEquals(new Point2D.Double(150d, 75d), Utils.findRectEdgeIntersection(rect, 200d, 75d)); final Rectangle2D rect2 = new Rectangle2D.Double(550, 650, 100, 50); assertEquals(550d, Utils.findRectEdgeIntersection(rect2, 10d, 640d).getX(), 0.0d); assertTrue(rect2.getCenterY() > Utils.findRectEdgeIntersection(rect2, 10d, 640d).getY()); assertTrue(rect2.getCenterY() < Utils.findRectEdgeIntersection(rect2, 10d, 710d).getY()); assertEquals(650d, Utils.findRectEdgeIntersection(rect2, 1500d, 640d).getX(), 0.0d); assertTrue(rect2.getCenterY() > Utils.findRectEdgeIntersection(rect2, 1500d, 640d).getY()); assertTrue(rect2.getCenterY() < Utils.findRectEdgeIntersection(rect2, 1500d, 710d).getY()); assertEquals(650d, Utils.findRectEdgeIntersection(rect2, 590d, 10d).getY(), 0.0d); assertEquals(700d, Utils.findRectEdgeIntersection(rect2, 590d, 10000d).getY(), 0.0d); assertTrue(rect2.getCenterX() > Utils.findRectEdgeIntersection(rect2, 520d, 10d).getX()); assertTrue(rect2.getCenterX() < Utils.findRectEdgeIntersection(rect2, 660d, 10d).getX()); }